def handleConnected(self):
        self.notify.info('Yarn. Waking up (This may take a while!).')
        ToontownInternalRepository.handleConnected(self)
        self.districtId = self.allocateChannel()
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            self.districtId, self.getGameDoId(), 2)

        # Claim ownership of that district...
        dg = PyDatagram()
        dg.addServerHeader(
            self.districtId,
            self.ourChannel,
            STATESERVER_OBJECT_SET_AI)
        dg.addChannel(self.ourChannel)
        self.send(dg)

        self.notify.info('Creating Global Managers')
        self.createGlobals()
        self.notify.info('Creating Toontown')
        self.createZones()

        self.statusSender.start()

        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('District is now ready.')
 def enterControlled(self, avId, accId):
     self.driverId = avId
     fieldList = ['setComponentL',
      'setComponentX',
      'setComponentY',
      'setComponentZ',
      'setComponentH',
      'setComponentP',
      'setComponentR',
      'setComponentT',
      'setSmStop',
      'setSmH',
      'setSmZ',
      'setSmXY',
      'setSmXZ',
      'setSmPos',
      'setSmHpr',
      'setSmXYH',
      'setSmXYZH',
      'setSmPosHpr',
      'setSmPosHprL',
      'clearSmoothing',
      'suggestResync',
      'returnResync']
     #self.air.setAllowClientSend(avId, self, fieldList, accId)
     #hack until CLIENTAGENT_SET_FIELDS_SENDABLE works
     #probably should not be kept for any longer than it needs to
     dg = PyDatagram()
     dg.addServerHeader(self.doId, self.air.ourChannel, STATESERVER_OBJECT_SET_OWNER)
     dg.addUint64(accId << 32 | avId)
     self.air.send(dg)
     self.d_setState('C', self.driverId)
Beispiel #3
0
    def onCrossClicked(self):
        if self.phase == 'tile' and self.cux is not False and self.party['yourturn']:

            if self.subphase == 'free':

                # if we clicked on a character
                if self.party['map']['tiles'][self.cux][self.cuy][self.cuz].has_key('char'):
                    charid = self.party['map']['tiles'][self.cux][self.cuy][self.cuz]['char']
                    myPyDatagram = PyDatagram()
                    myPyDatagram.addUint8(GET_PASSIVE_WALKABLES)
                    myPyDatagram.addString(charid)
                    self.cWriter.send(myPyDatagram, self.myConnection)

            elif self.subphase == 'passivewalkables':
                self.clearZone()
                self.cancel_snd.play()
                self.subphase = 'free'

            elif self.subphase == 'move':
                self.clearZone()
                self.cancel_snd.play()
                self.subphase = None
                self.turn()
            elif self.subphase == 'attack':
                self.clearZone()
                self.cancel_snd.play()
                self.subphase = None
                self.turn()
Beispiel #4
0
    def updateAllPartyLists(self):
        parties = deepcopy(self.parties)
        for party in parties.values():
            del party['map']['tiles']

        for player in self.playersinlobby:
            myPyDatagram = PyDatagram()
            myPyDatagram.addUint8(UPDATE_PARTY_LIST)
            myPyDatagram.addString32(json.dumps(parties))
            self.cWriter.send(myPyDatagram, player)
 def __ready(self):
     dg = PyDatagram()
     dg.addServerHeader(self.districtStats.doId, self.ourChannel, STATESERVER_OBJECT_DELETE_RAM)
     dg.addUint32(self.districtStats.doId)
     self.addPostRemove(dg)
     
     self.apiMgr = self.generateGlobalObject(100001, "ShardAPIManager")
     self.apiMgr.start()
     self.apiMgr.d_setShardData()
     
     self.banMgr = self.generateGlobalObject(100002, "BanManager")
    def login(self, cookie):
        target = self.air.getMsgSender()

        datagram = PyDatagram()
        datagram.addServerHeader(
            target,
            self.air.ourChannel,
            CLIENTAGENT_SET_STATE)
        datagram.addUint16(2)
        self.air.send(datagram)

        self.sendUpdateToChannel(target, 'acceptLogin', [])
    def enterSetAvatarTask(self, channel, task):
        # Finally, grant ownership and shut down.
        datagram = PyDatagram()
        datagram.addServerHeader(
            self.avId,
            self.csm.air.ourChannel,
            STATESERVER_OBJECT_SET_OWNER)
        datagram.addChannel(self.target<<32 | self.avId)
        self.csm.air.send(datagram)

        self.csm.air.writeServerEvent('avatarChosen', self.avId, self.target)
        self.demand('Off')
        return task.done
    def handleConnected(self):
        self.districtId = self.allocateChannel()
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(simbase.air.districtId, self.getGameDoId(), 2)

        dg = PyDatagram()
        dg.addServerHeader(simbase.air.districtId, simbase.air.ourChannel, STATESERVER_OBJECT_SET_AI)
        dg.addChannel(simbase.air.ourChannel)
        simbase.air.send(dg)

        self.createGlobals()
        self.createZones()
 def killConnection(self, connId, reason):
     datagram = PyDatagram()
     datagram.addServerHeader(connId, self.air.ourChannel,
                              CLIENTAGENT_EJECT)
     datagram.addUint16(122)
     datagram.addString(reason)
     self.air.send(datagram)
Beispiel #10
0
 def bootClient(self, reason, av):
     dg = PyDatagram()
     dg.addServerHeader(self.GetPuppetConnectionChannel(av),
                        self.air.ourChannel, CLIENTAGENT_EJECT)
     dg.addUint16(106)
     dg.addString(reason)
     self.air.send(dg)
Beispiel #11
0
 def sendShardInfo(self):
     dg = PyDatagram()
     dg.addServerHeader(self.serverId, self.ourChannel,
                        STATESERVER_UPDATE_SHARD)
     dg.addString(self.districtName)
     dg.addUint32(self.districtPopulation)
     self.send(dg)
Beispiel #12
0
    def moveCharacterTo(self, charid, dest):

        (x2, y2, z2) = dest
        
        myPyDatagram = PyDatagram()
        myPyDatagram.addUint8(MOVE_TO)
        myPyDatagram.addString(charid)
        myPyDatagram.addUint8(x2)
        myPyDatagram.addUint8(y2)
        myPyDatagram.addUint8(z2)
        self.cWriter.send(myPyDatagram, self.myConnection)
    def doUpdate(self, updateType, data):
        self.heartbeat()

        if updateType == "inv":
            return  # rip crash

        dg = PyDatagram()
        dg.addUint8(0)
        dg.addString(updateType)
        dg.appendData(data)
        self.setShardData(dg.getMessage())
Beispiel #14
0
 def killConnection(self, connectionId, reason):
     # Sends CLIENTAGENT_EJECT to the given connectionId with the given reason.
     datagram = PyDatagram()
     datagram.addServerHeader(connectionId, self.air.ourChannel,
                              CLIENTAGENT_EJECT)
     datagram.addUint16(OTPGlobals.BootedReason["connectionKilled"])
     datagram.addString(reason)
     self.air.send(datagram)
    def toonOnline(self, doId, friendsList):
        self.onlineToons.append(doId)

        channel = self.GetPuppetConnectionChannel(doId)
        dgcleanup = self.dclass.aiFormatUpdate('goingOffline', self.doId, self.doId, self.air.ourChannel, [doId])
        dg = PyDatagram()
        dg.addServerHeader(channel, self.air.ourChannel, CLIENTAGENT_ADD_POST_REMOVE)
        dg.addString(dgcleanup.getMessage())
        self.air.send(dg)

        for friend in friendsList:
            friendId = friend[0]
            if friend[0] in self.onlineToons:
                self.sendUpdateToAvatarId(doId, 'friendOnline', [friendId, 0, 0])
            self.sendUpdateToAvatarId(friendId, 'friendOnline', [doId, 0, 0])
 def killConnection(self, connId, code=122, reason=''):
     self.notify.info('Booting client: %d out for reason(%d): %s' %
                      (int(connId), int(code), str(reason)))
     dg = PyDatagram()
     dg.addServerHeader(connId, self.air.ourChannel, CLIENTAGENT_EJECT)
     dg.addUint16(int(code))
     dg.addString(str(reason))
     self.air.send(dg)
Beispiel #17
0
 def path(self, charid, dest):
     orig = self.getCharacterCoords(charid)
     origdir = self.sprites[charid].realdir
     (x, y, z) = dest
     
     myPyDatagram = PyDatagram()
     myPyDatagram.addUint8(GET_PATH)
     myPyDatagram.addString(charid)
     myPyDatagram.addUint8(x)
     myPyDatagram.addUint8(y)
     myPyDatagram.addUint8(z)
     self.cWriter.send(myPyDatagram, self.myConnection)
    def enterSetAvatarTask(self, channel, task):
        # Finally, grant ownership and shut down.
        datagram = PyDatagram()
        datagram.addServerHeader(
            self.avId,
            self.csm.air.ourChannel,
            STATESERVER_OBJECT_SET_OWNER)
        datagram.addChannel(self.target<<32 | self.avId)
        self.csm.air.send(datagram)

        # Tell the GlobalPartyManager as well:
        self.csm.air.globalPartyMgr.avatarJoined(self.avId)

        self.csm.air.writeServerEventMessage('avatarChosen', self.avId, self.target)
        self.demand('Off')
        return task.done
    def setAllowClientSend(self, avId, distObj, fieldNameList=[]):
        dg = PyDatagram()
        dg.addServerHeader(distObj.GetPuppetConnectionChannel(avId),
                           self.ourChannel, CLIENTAGENT_SET_FIELDS_SENDABLE)
        fieldIds = []
        for fieldName in fieldNameList:
            field = distObj.dclass.getFieldByName(fieldName)
            if field:
                fieldIds.append(field.getNumber())

        dg.addUint32(distObj.getDoId())
        dg.addUint16(len(fieldIds))
        for fieldId in fieldIds:
            dg.addUint16(fieldId)

        self.send(dg)
    def enterJudgeName(self):
        dg = PyDatagram(self.name)
        dgi = PyDatagramIterator(dg)
        isPattern, name = isNamePattern(dgi, self.csm.namePattern, self.dna.gender)
        
        if not name:
            self.demand('Kill', 'There\'s an issue with your name request!')
            return
        
        toonFields = {'WishNameState': ('PENDING',), 'WishName': (name,)}
        
        if isPattern:
            toonFields['WishNameState'] = ('',)
            toonFields['WishName'] = ('',)
            toonFields['setName'] = (name,)

        if self.avId:
            self.csm.air.dbInterface.updateObject(
                self.csm.air.dbId,
                self.avId,
                self.csm.air.dclassesByName['DistributedToonUD'],
                toonFields)

            self.csm.air.writeServerEvent('avatarWishname', self.avId, name)
            self.csm.accountDB.handlePostNameRequest(self.avId, name)

        self.csm.sendUpdateToAccountId(self.target, 'updateNameResp', [])
        self.demand('Off')
    def __offlineToonOnline(self, avId, activated, otherId=None, accId=None):
        if not (otherId and activated and accId):
            return
        # Undeclare to the friend!
        dg = PyDatagram()
        dg.addServerHeader(self.GetPuppetConnectionChannel(avId), self.air.ourChannel, CLIENTAGENT_UNDECLARE_OBJECT)
        dg.addUint32(otherId)
        self.air.send(dg)

        # Undeclare to our now-offline avId (they may still be around, about to log into a new toon!)
        dg = PyDatagram()
        dg.addServerHeader(self.GetAccountConnectionChannel(accId), self.air.ourChannel, CLIENTAGENT_UNDECLARE_OBJECT)
        dg.addUint32(avId)
        self.air.send(dg)

        # Tell them they're offline!
        self.sendUpdateToAvatarId(avId, 'friendOffline', [otherId])
Beispiel #22
0
 def killConnection(self,
                    connectionId,
                    reason,
                    code=OTPGlobals.BootedConnectionKilled):
     datagram = PyDatagram()
     datagram.addServerHeader(connectionId, self.air.ourChannel,
                              CLIENTAGENT_EJECT)
     datagram.addUint16(code)
     datagram.addString(reason)
     self.air.send(datagram)
Beispiel #23
0
    def authenticate(self):
        login = self.loginwindow.loginEntry.get()
        password = self.loginwindow.passwordEntry.get()

        self.cManager  = QueuedConnectionManager()
        self.cListener = QueuedConnectionListener(self.cManager, 0)
        self.cReader   = QueuedConnectionReader(self.cManager, 0)
        self.cWriter   = ConnectionWriter(self.cManager, 0)
        self.cReader.setTcpHeaderSize(4)
        self.cWriter.setTcpHeaderSize(4)

        self.myConnection = self.cManager.openTCPClientConnection(IP, PORT, 5000)
        if self.myConnection:
            self.cReader.addConnection(self.myConnection)
            print 'Client listening on', IP, ':', PORT
            taskMgr.add(self.tskReaderPolling, "Poll the connection reader")

            myPyDatagram = PyDatagram()
            myPyDatagram.addUint8(LOGIN_MESSAGE)
            myPyDatagram.addString(login)
            myPyDatagram.addString(password)
            self.cWriter.send(myPyDatagram, self.myConnection)

        else:
            print 'Can\'t connect to server on', IP, ':', PORT
    def login(self, cookie, sig):
        self.notify.debug("Received login cookie %r from %d" % (cookie, self.air.getMsgSender()))

        sender = self.air.getMsgSender()

        if not self.loginsEnabled:
            # Logins are currently disabled... RIP!
            dg = PyDatagram()
            dg.addServerHeader(sender, self.air.ourChannel, CLIENTAGENT_EJECT)
            dg.addUint16(200)
            dg.addString("Logins are currently disabled. Please try again later.")
            self.air.send(dg)

        if sender >> 32:
            # Oops, they have an account ID on their connection already!
            self.killConnection(sender, "Client is already logged in.")
            return

        # Test the signature
        key = (
            config.GetString("csmud-secret", "streetlamps")
            + config.GetString("server-version", "no_version_set")
            + FIXED_KEY
        )
        computedSig = hmac.new(key, cookie, hashlib.sha256).digest()
        if sig != computedSig:
            self.killConnection(sender, "The accounts database rejected your cookie")
            return

        if sender in self.connection2fsm:
            self.killConnectionFSM(sender)
            return

        self.connection2fsm[sender] = LoginAccountFSM(self, sender)
        self.connection2fsm[sender].request("Start", cookie)
Beispiel #25
0
 def attack(self, charid, targetid):
     
     myPyDatagram = PyDatagram()
     myPyDatagram.addUint8(ATTACK)
     myPyDatagram.addString(charid)
     myPyDatagram.addString(targetid)
     self.cWriter.send(myPyDatagram, self.myConnection)
    def doUpdate(self, updateType, data):
        self.heartbeat()

        if updateType == "inv":
            return  # rip crash

        dg = PyDatagram()
        dg.addUint8(0)
        dg.addString(updateType)
        dg.appendData(data)
        self.setShardData(dg.getMessage())
    def toonOnline(self, doId, fields):
        self.onlineToons.append(doId)
        self.toonAccess[doId] = fields.get("setAdminAccess", [0])[0]
        self.toonNames[doId] = fields["setName"][0]
        self.toonAccIds[doId] = fields.get("setDISLid", [0])[0]
        friendsList = fields["setFriendsList"][0]

        channel = self.GetPuppetConnectionChannel(doId)
        dgcleanup = self.dclass.aiFormatUpdate("goingOffline", self.doId, self.doId, self.air.ourChannel, [doId])
        dg = PyDatagram()
        dg.addServerHeader(channel, self.air.ourChannel, CLIENTAGENT_ADD_POST_REMOVE)
        dg.addString(dgcleanup.getMessage())
        self.air.send(dg)

        for friend in friendsList:
            friendId = friend[0]
            if friend[0] in self.onlineToons:
                self.sendUpdateToAvatarId(doId, "friendOnline", [friendId, 0, 0])
            self.sendUpdateToAvatarId(friendId, "friendOnline", [doId, 0, 0])
 def killConnection(self, connId, reason):
     datagram = PyDatagram()
     datagram.addServerHeader(
         connId,
         self.air.ourChannel,
         CLIENTAGENT_EJECT)
     datagram.addUint16(122)
     datagram.addString(reason)
     self.air.send(datagram)
Beispiel #29
0
 def createParty(self, mapname):
     import time
     partyname = str(int(time.time()))
     
     myPyDatagram = PyDatagram()
     myPyDatagram.addUint8(CREATE_PARTY)
     myPyDatagram.addString(partyname)
     myPyDatagram.addString(mapname)
     self.cWriter.send(myPyDatagram, self.myConnection)
    def enterSetAvatarTask(self, channel, task):
        # Finally, grant ownership and shut down.
        datagram = PyDatagram()
        datagram.addServerHeader(
            self.avId,
            self.csm.air.ourChannel,
            STATESERVER_OBJECT_SET_OWNER)
        datagram.addChannel(self.target<<32 | self.avId)
        self.csm.air.send(datagram)

        # Tell the GlobalPartyManager as well:
        self.csm.air.globalPartyMgr.avatarJoined(self.avId)
        
        fields = self.avatar
        fields.update({'setAdminAccess': [self.account.get('ACCESS_LEVEL', 100)]})
        self.csm.air.friendsManager.addToonData(self.avId, fields)        

        self.csm.air.writeServerEvent('avatarChosen', self.avId, self.target)
        self.demand('Off')
        return task.done
    def setShardData(self, data):
        dg = PyDatagram(data)
        di = PyDatagramIterator(dg)
        context = di.getUint8()

        while di.getRemainingSize():
            self._doUpdateShard(di)

        if context > 0:
            self.sendUpdateToChannel(self.air.getMsgSender(),
                                     "setShardDataRes", [context])
    def doSend(self, targets, origin=None):
        if origin is None:
            origin = self.air.ourChannel

        self.setOrigin(origin)
        self.setTargets(targets)

        for target in targets:
            dg = self.dclass.aiFormatGenerate(self, self.air.allocateChannel(),
                                              0, 0, target, self.air.serverId,
                                              [])
            self.air.send(PyDatagram(dg.getMessage()[17:]))
 def enterControlled(self, avId, accId):
     self.driverId = avId
     fieldList = ['setComponentL',
      'setComponentX',
      'setComponentY',
      'setComponentZ',
      'setComponentH',
      'setComponentP',
      'setComponentR',
      'setComponentT',
      'setSmStop',
      'setSmH',
      'setSmZ',
      'setSmXY',
      'setSmXZ',
      'setSmPos',
      'setSmHpr',
      'setSmXYH',
      'setSmXYZH',
      'setSmPosHpr',
      'setSmPosHprL',
      'clearSmoothing',
      'suggestResync',
      'returnResync']
     #self.air.setAllowClientSend(avId, self, fieldList, accId)
     #hack until CLIENTAGENT_SET_FIELDS_SENDABLE works
     #probably should not be kept for any longer than it needs to
     dg = PyDatagram()
     dg.addServerHeader(self.doId, self.air.ourChannel, STATESERVER_OBJECT_SET_OWNER)
     dg.addUint64(accId << 32 | avId)
     self.air.send(dg)
     self.d_setState('C', self.driverId)
    def handleConnected(self):
        ToontownInternalRepository.handleConnected(self)
        self.districtId = self.allocateChannel()
        self.notify.info('Creating new district (%d)...' % self.districtId)
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            self.districtId, self.getGameDoId(), 2)

        # Claim ownership of that district...
        self.notify.info('Claiming ownership of district (%d)...' %
                         self.districtId)
        dg = PyDatagram()
        dg.addServerHeader(self.districtId, self.ourChannel,
                           STATESERVER_OBJECT_SET_AI)
        dg.addChannel(self.ourChannel)
        self.send(dg)
        self.notify.info('Creating global objects...')
        self.createGlobals()
        self.notify.info('Creating zones (Playgrounds and Cog HQs)...')
        self.createZones()

        self.statusSender.start()
        self.notify.info('Making district available to enter...')
        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('District is now ready. Have fun in Toontown!')
    def createGlobals(self):
        self.csm = simbase.air.generateGlobalObject(
            OTP_DO_ID_CLIENT_SERVICES_MANAGER, 'ClientServicesManager')

        self.chatAgent = simbase.air.generateGlobalObject(
            OTP_DO_ID_CHAT_MANAGER, 'ChatAgent')

        self.friendsManager = simbase.air.generateGlobalObject(
            OTP_DO_ID_TT_FRIENDS_MANAGER, 'TTFriendsManager')

        self.globalPartyMgr = simbase.air.generateGlobalObject(
            OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')

        if config.GetBool('want-top-toons', True):
            if OTP_DO_ID_TOONTOWN_TOP_TOONS_MGR == 100003:
                self.topToonsMgr = DistributedTopToonsManagerUD(self)
                self.topToonsMgr.generateWithRequiredAndId(
                    100003, self.getGameDoId(), 2)

                dg = PyDatagram()
                dg.addServerHeader(100003, self.ourChannel,
                                   STATESERVER_OBJECT_SET_AI)
                dg.addChannel(self.ourChannel)
                self.send(dg)

            else:
                self.topToonsMgr = self.generateGlobalObject(
                    OTP_DO_ID_TOONTOWN_TOP_TOONS_MGR,
                    'DistributedTopToonsManager')
Beispiel #36
0
 def handleConnected(self):
     ToontownInternalRepository.handleConnected(self)
     self.districtId = self.allocateChannel()
     self.notify.info('Creating district (%d)...' % self.districtId)
     self.district = ToontownDistrictAI(self)
     self.district.setName(self.districtName)
     self.district.setDescription(self.districtDescription)
     self.district.generateWithRequiredAndId(self.districtId,
                                             self.getGameDoId(),
                                             OTP_ZONE_ID_MANAGEMENT)
     self.notify.info('Claiming ownership of district (%d)...' %
                      self.districtId)
     datagram = PyDatagram()
     datagram.addServerHeader(self.districtId, self.ourChannel,
                              STATESERVER_OBJECT_SET_AI)
     datagram.addChannel(self.ourChannel)
     self.send(datagram)
     self.notify.info('Creating local objects...')
     self.createLocals()
     self.notify.info('Creating global objects...')
     self.createGlobals()
     self.notify.info('Creating zones (Playgrounds and Cog HQs)...')
     self.createZones()
     self.notify.info('Making district available...')
     self.district.b_setAvailable(1)
     self.notify.info(
         'District is now ready. Have fun in Toontown Offline!')
Beispiel #37
0
    def handleConnected(self):
        self.notify.info('Yarn. Waking up (This may take a while!).')
        ToontownInternalRepository.handleConnected(self)
        self.districtId = self.allocateChannel()
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            self.districtId, self.getGameDoId(), 2)

        # Claim ownership of that district...
        dg = PyDatagram()
        dg.addServerHeader(self.districtId, self.ourChannel,
                           STATESERVER_OBJECT_SET_AI)
        dg.addChannel(self.ourChannel)
        self.send(dg)

        self.notify.info('Creating Global Managers')
        self.createGlobals()
        self.notify.info('Creating Toontown')
        self.createZones()

        self.statusSender.start()

        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('District is now ready.')
Beispiel #38
0
    def login(self, cookie, sessionKey):
        self.notify.debug('Received login cookie %r from %d' %
                          (cookie, self.air.getMsgSender()))

        sender = self.air.getMsgSender()

        if not self.loginsEnabled:
            # Logins are currently disabled... RIP!
            dg = PyDatagram()
            dg.addServerHeader(sender, self.air.ourChannel, CLIENTAGENT_EJECT)
            dg.addUint16(200)
            dg.addString(
                'Logins are currently disabled. Please try again later.')
            self.air.send(dg)

        if sender >> 32:
            # Oops, they have an account ID on their connection already!
            self.killConnection(sender, 'Client is already logged in.')
            return

        if sender in self.connection2fsm:
            # Hot fix for potential toons that's FSM is stuck in state.
            self.connection2fsm[sender].demand('Off')

            # kick the client because there is a major issue!
            self.killConnection(
                sender,
                'Failed to login, because your account is already in FSM state!'
            )
            return

        if sessionKey != self.sessionKey:
            self.killConnection(
                sender, 'Failed to login, recieved a bad login cookie!')

            # notify the admin that someone tried to login with a custom client.
            self.notify.warning(
                '%s: Tried to login with a custom client using sessionKey, %s!'
                % (sender, str(sessionKey)))

            return

        if self.banManager.getToonBanned(cookie):
            self.killConnection(sender,
                                self.banManager.getToonBanReason(cookie))
            return

        self.connection2fsm[sender] = LoginAccountFSM(self, sender)
        self.connection2fsm[sender].request('Start', cookie)
Beispiel #39
0
 def enterSetAvatarTask(self, channel, task):
     datagram = PyDatagram()
     datagram.addServerHeader(self.avId, self.csm.air.ourChannel,
                              STATESERVER_OBJECT_SET_OWNER)
     datagram.addChannel(self.target << 32 | self.avId)
     self.csm.air.send(datagram)
     self.csm.air.writeServerEvent('avatarChosen', self.avId, self.target)
     self.demand('Off')
     return task.done
    def createGlobals(self):
        self.csm = simbase.air.generateGlobalObject(OTP_DO_ID_CLIENT_SERVICES_MANAGER,
                                                    'ClientServicesManager')

        self.chatAgent = simbase.air.generateGlobalObject(OTP_DO_ID_CHAT_MANAGER,
                                                          'ChatAgent')
        
        self.friendsManager = simbase.air.generateGlobalObject(OTP_DO_ID_TT_FRIENDS_MANAGER,
                                                               'TTFriendsManager')

        self.globalPartyMgr = simbase.air.generateGlobalObject(OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')
        
        if config.GetBool('want-top-toons', True):
            if OTP_DO_ID_TOONTOWN_TOP_TOONS_MGR == 100003:
                self.topToonsMgr = DistributedTopToonsManagerUD(self)
                self.topToonsMgr.generateWithRequiredAndId(100003, self.getGameDoId(), 2)
                
                dg = PyDatagram()
                dg.addServerHeader(100003, self.ourChannel, STATESERVER_OBJECT_SET_AI)
                dg.addChannel(self.ourChannel)
                self.send(dg)
            
            else:
                self.topToonsMgr = self.generateGlobalObject(OTP_DO_ID_TOONTOWN_TOP_TOONS_MGR, 'DistributedTopToonsManager')
    def login(self, cookie):
        target = self.air.getMsgSender()

        datagram = PyDatagram()
        datagram.addServerHeader(target, self.air.ourChannel,
                                 CLIENTAGENT_SET_STATE)
        datagram.addUint16(2)
        self.air.send(datagram)

        self.sendUpdateToChannel(target, 'acceptLogin', [])
Beispiel #42
0
    def login(self, cookie, sessionKey):
        sender = self.air.getMsgSender()

        #if not self.AccountFirewallUD.checkPlayerLogin(cookie):
        #   self.killConnection(sender, 'Your account has been disallowed login to Project Altis. Please try again later.')
        #    return

        self.notify.debug('Received login cookie %r from %d' %
                          (cookie, sender))

        if not self.loginsEnabled:
            # Logins are currently disabled... RIP!
            dg = PyDatagram()
            dg.addServerHeader(sender, self.air.ourChannel, CLIENTAGENT_EJECT)
            dg.addUint16(200)
            dg.addString(
                'Logins are currently disabled. Please try again later.')
            self.air.send(dg)

        if sender >> 32:
            # Oops, they have an account ID on their connection already!
            self.killConnection(sender, 'Client is already logged in.')
            return

        if sender in self.connection2fsm:
            # hot fix, remove the sender from the fsm and request the fsm state OFF
            self.connection2fsm[sender].demand('Off')

        if sessionKey != self.sessionKey:
            self.killConnection(
                sender, 'Failed to login, recieved a bad login cookie!')

            # notify the admin that someone tried to login with a custom client.
            self.notify.warning('%s: Tried to login with a custom client!' %
                                (sender))
            return

        if self.banManager.getToonBanned(cookie):
            self.killConnection(sender,
                                self.banManager.getToonBanReason(cookie))
            return

        self.connection2fsm[sender] = LoginAccountFSM(self, sender)
        self.connection2fsm[sender].request('Start', cookie)
    def enterSetAvatarTask(self, channel, task):
        # Finally, grant ownership and shut down.
        datagram = PyDatagram()
        datagram.addServerHeader(self.avId, self.csm.air.ourChannel, STATESERVER_OBJECT_SET_OWNER)
        datagram.addChannel(self.target<<32 | self.avId)
        self.csm.air.send(datagram)

        # Tell the GlobalPartyManager as well:
        self.csm.air.globalPartyMgr.avatarJoined(self.avId)

        self.csm.air.writeServerEvent('avatarChosen', self.avId, self.target)
        self.demand('Off')
        return task.done
    def login(self, cookie, sig, secret):
        self.notify.debug('Received login cookie %r from %d' %
                          (cookie, self.air.getMsgSender()))

        sender = self.air.getMsgSender()

        if not self.loginsEnabled:
            # Logins are currently disabled... RIP!
            dg = PyDatagram()
            dg.addServerHeader(sender, self.air.ourChannel, CLIENTAGENT_EJECT)
            dg.addUint16(200)
            dg.addString(
                'Logins are currently disabled. Please try again later.')
            self.air.send(dg)

        if sender >> 32:
            # Oops, they have an account ID on their connection already!
            self.killConnection(sender, 'Client is already logged in.')
            return
        # Test Server Secret
        serversecret = config.GetString('csmud-secret', 'streetlamps')
        if secret != serversecret:
            self.killConnection(sender,
                                'The accounts database rejcts you secret key')
            return
        # Test the signature
        key = config.GetString(
            'csmud-secret', 'streetlamps') + config.GetString(
                'server-version', 'no_version_set') + FIXED_KEY
        computedSig = hmac.new(key, cookie, hashlib.sha256).digest()
        if sig != computedSig:
            self.killConnection(sender,
                                'The accounts database rejected your cookie')
            return

        if sender in self.connection2fsm:
            self.killConnectionFSM(sender)
            return

        self.connection2fsm[sender] = LoginAccountFSM(self, sender)
        self.connection2fsm[sender].request('Start', cookie)
Beispiel #45
0
    def login(self, cookie, authKey):
        sender = self.air.getMsgSender()
        hwid = cookie.split("#")[1]
        backupCookie = cookie.split("#")[0]
        cookie = cookie.split("#")[0]
        self.pendingLogins[sender] = (sender, hwid, backupCookie, cookie,
                                      authKey)

        # CLIENTAGENT_GET_NETWORK_ADDRESS is defined in OtpDoGlobals for backwards compatibility with old versions of Panda3D
        datagram = PyDatagram()
        datagram.addServerHeader(sender, self.air.ourChannel,
                                 OtpDoGlobals.CLIENTAGENT_GET_NETWORK_ADDRESS)
        datagram.addUint32(sender)
        self.air.send(datagram)
    def __ready(self):
        dg = PyDatagram()
        dg.addServerHeader(self.districtStats.doId, self.ourChannel,
                           STATESERVER_OBJECT_DELETE_RAM)
        dg.addUint32(self.districtStats.doId)
        self.addPostRemove(dg)

        self.apiMgr = self.generateGlobalObject(100001, "ShardAPIManager")
        self.apiMgr.start()
        self.apiMgr.d_setShardData()

        self.banMgr = self.generateGlobalObject(100002, "BanManager")

        self.trophyMgr.updateToonData()
    def handleConnected(self):
        self.districtId = self.allocateChannel()
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            simbase.air.districtId, self.getGameDoId(), 2)

        dg = PyDatagram()
        dg.addServerHeader(simbase.air.districtId, simbase.air.ourChannel,
                           STATESERVER_OBJECT_SET_AI)
        dg.addChannel(simbase.air.ourChannel)
        simbase.air.send(dg)

        self.createGlobals()
        self.createZones()
 def enterControlled(self, avId, accId):
     self.driverId = avId
     fieldList = [
         'setComponentL', 'setComponentX', 'setComponentY', 'setComponentZ',
         'setComponentH', 'setComponentP', 'setComponentR', 'setComponentT',
         'setSmStop', 'setSmH', 'setSmZ', 'setSmXY', 'setSmXZ', 'setSmPos',
         'setSmHpr', 'setSmXYH', 'setSmXYZH', 'setSmPosHpr', 'setSmPosHprL',
         'clearSmoothing', 'suggestResync', 'returnResync'
     ]
     dg = PyDatagram()
     dg.addServerHeader(self.doId, self.air.ourChannel,
                        STATESERVER_OBJECT_SET_OWNER)
     dg.addUint64(accId << 32 | avId)
     self.air.send(dg)
     self.d_setState('C', self.driverId)
    def toonOnline(self, doId, friendsList):
        self.onlineToons.append(doId)

        channel = self.GetPuppetConnectionChannel(doId)
        dgcleanup = self.dclass.aiFormatUpdate('goingOffline', self.doId, self.doId, self.air.ourChannel, [doId])
        dg = PyDatagram()
        dg.addServerHeader(channel, self.air.ourChannel, CLIENTAGENT_ADD_POST_REMOVE)
        dg.addString(dgcleanup.getMessage())
        self.air.send(dg)

        for friend in friendsList:
            friendId = friend[0]
            if friend[0] in self.onlineToons:
                self.sendUpdateToAvatarId(doId, 'friendOnline', [friendId, 0, 0])
            self.sendUpdateToAvatarId(friendId, 'friendOnline', [doId, 0, 0])
Beispiel #50
0
    def w(klass, data):
        if data:
            dg = PyDatagram(data)
            dgi = PyDatagramIterator(dg)

            def unpackPlant(_):
                return dgi.getUint32, dgi.getInt8(), dgi.getUint32(
                ), dgi.getInt8(), dgi.getUint16()

            flowers = map(unpackPlant, range(10))
            trees = map(unpackPlant, range(8))
            st = dgi.getUint8()
            started = dgi.getBool()

        else:
            flowers = NULL_FLOWERS
            trees = NULL_TREES
            st = NULL_STATUARY
            started = 0

        return f(klass, started, flowers, trees, st)
Beispiel #51
0
    def enterSetAvatarTask(self, channel, task):
        # Finally, grant ownership and shut down.
        datagram = PyDatagram()
        datagram.addServerHeader(self.avId, self.csm.air.ourChannel,
                                 STATESERVER_OBJECT_SET_OWNER)
        datagram.addChannel(self.target << 32 | self.avId)
        self.csm.air.send(datagram)

        # Tell the GlobalPartyManager as well:
        self.csm.air.globalPartyMgr.avatarJoined(self.avId)

        fields = self.avatar
        fields.update(
            {'setAdminAccess': [self.account.get('ACCESS_LEVEL', 100)]})
        self.csm.air.friendsManager.addToonData(self.avId, fields)

        self.csm.air.writeServerEvent('avatarChosen', self.avId, self.target)
        self.demand('Off')
        return task.done
Beispiel #52
0
 def toonOnline(self, doId, fields):
     self.onlineToons.append(doId)
     self.toonAccess[doId] = fields.get('setAdminAccess', [0])[0]
     self.toonNames[doId] = fields['setName'][0]
     self.toonAccIds[doId] = fields.get('setDISLid', [0])[0]
     friendsList = fields['setFriendsList'][0]
     channel = self.GetPuppetConnectionChannel(doId)
     dgcleanup = self.dclass.aiFormatUpdate('goingOffline', self.doId,
                                            self.doId, self.air.ourChannel,
                                            [doId])
     dg = PyDatagram()
     dg.addServerHeader(channel, self.air.ourChannel,
                        CLIENTAGENT_ADD_POST_REMOVE)
     dg.addString(dgcleanup.getMessage())
     self.air.send(dg)
     for friend in friendsList:
         friendId = friend[0]
         if friend[0] in self.onlineToons:
             self.sendUpdateToAvatarId(doId, 'friendOnline',
                                       [friendId, 0, 0])
         self.sendUpdateToAvatarId(friendId, 'friendOnline', [doId, 0, 0])
    def inviteeFriendResponse(self, response, context):
        avId = self.air.getAvatarIdFromSender()
        if not context in self.requests:
            self.air.writeServerEvent('suspicious', avId=avId, issue='Player tried to respond to a friend request that doesn\'t exist!')
            return
        if avId != self.requests[context][0][1]:
            self.air.writeServerEvent('suspicious', avId=avId, issue='Player tried to respond to someone else\'s request!')
            return
        if self.requests[context][1] == 'cancelled':
            self.air.writeServerEvent('suspicious', avId=avId, issue='Player tried to respond to non-active friend request!')
            return
        self.sendUpdateToAvatarId(self.requests[context][0][0], 'friendResponse', [response, context])
        if response == 1:
            requested = self.air.doId2do.get(self.requests[context][0][1])
            requester = self.air.doId2do.get(self.requests[context][0][0])

            if not (requested and requester):
                # Likely they logged off just before a response was sent. RIP.
                return


            # Allow both toons to teleport to each other.
            dg = PyDatagram()
            dg.addServerHeader(self.GetPuppetConnectionChannel(requested.getDoId()), self.air.ourChannel, CLIENTAGENT_DECLARE_OBJECT)
            dg.addUint32(requester.getDoId())
            dg.addUint16(self.air.dclassesByName['DistributedToonAI'].getNumber())
            self.air.send(dg)

            dg = PyDatagram()
            dg.addServerHeader(self.GetPuppetConnectionChannel(requester.getDoId()), self.air.ourChannel, CLIENTAGENT_DECLARE_OBJECT)
            dg.addUint32(requested.getDoId())
            dg.addUint16(self.air.dclassesByName['DistributedToonAI'].getNumber())
            self.air.send(dg)

            requested.extendFriendsList(requester.getDoId(), 0)
            requester.extendFriendsList(requested.getDoId(), 0)

            requested.d_setFriendsList(requested.getFriendsList())
            requester.d_setFriendsList(requester.getFriendsList())
        del self.requests[context]
    def enterUnloadAvatar(self):
        channel = self.csm.GetAccountConnectionChannel(self.target)
        
        # Tell FriendsManager somebody is logging off:
        self.csm.air.friendsManager.toonOffline(self.avId)

        # Clear off POSTREMOVE:
        dg = PyDatagram()
        dg.addServerHeader(channel, self.csm.air.ourChannel, CLIENTAGENT_CLEAR_POST_REMOVES)
        self.csm.air.send(dg)

        # Remove avatar channel:
        dg = PyDatagram()
        dg.addServerHeader(channel, self.csm.air.ourChannel, CLIENTAGENT_CLOSE_CHANNEL)
        dg.addChannel(self.csm.GetPuppetConnectionChannel(self.avId))
        self.csm.air.send(dg)

        # Reset sender channel:
        dg = PyDatagram()
        dg.addServerHeader(channel, self.csm.air.ourChannel, CLIENTAGENT_SET_CLIENT_ID)
        dg.addChannel(self.target<<32) # accountId in high 32 bits, no avatar in low
        self.csm.air.send(dg)

        # Unload avatar object:
        dg = PyDatagram()
        dg.addServerHeader(self.avId, channel, STATESERVER_OBJECT_DELETE_RAM)
        dg.addUint32(self.avId)
        self.csm.air.send(dg)

        # Done!
        self.csm.air.writeServerEvent('avatarUnload', self.avId)
        try:
            del self.csm.account2username[channel]
        
        except KeyError:
            self.csm.notify.warning('Unload avatar: %s not in account2username??' % channel)
        
        self.demand('Off')
    def enterSetAvatar(self):
        channel = self.csm.GetAccountConnectionChannel(self.target)

        # First, give them a POSTREMOVE to unload the avatar, just in case they
        # disconnect while we're working.
        dgcleanup = PyDatagram()
        dgcleanup.addServerHeader(self.avId, channel, STATESERVER_OBJECT_DELETE_RAM)
        dgcleanup.addUint32(self.avId)
        dg = PyDatagram()
        dg.addServerHeader(channel, self.csm.air.ourChannel, CLIENTAGENT_ADD_POST_REMOVE)
        dg.addString(dgcleanup.getMessage())
        self.csm.air.send(dg)

        # Activate the avatar on the DBSS:
        self.csm.air.sendActivate(self.avId, 0, 0,
                                  self.csm.air.dclassesByName['DistributedToonUD'],
                                  {'setAdminAccess': [self.account.get('ADMIN_ACCESS', 0)]})

        # Next, add them to the avatar channel:
        dg = PyDatagram()
        dg.addServerHeader(channel, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL)
        dg.addChannel(self.csm.GetPuppetConnectionChannel(self.avId))
        self.csm.air.send(dg)

        # Now set their sender channel to represent their account affiliation:
        dg = PyDatagram()
        dg.addServerHeader(channel, self.csm.air.ourChannel, CLIENTAGENT_SET_CLIENT_ID)
        dg.addChannel(self.target<<32 | self.avId) # accountId in high 32 bits, avatar in low
        self.csm.air.send(dg)

        # Finally, grant ownership and shut down.
        dg = PyDatagram()
        dg.addServerHeader(self.avId, self.csm.air.ourChannel, STATESERVER_OBJECT_SET_OWNER)
        dg.addChannel(self.target<<32 | self.avId) # accountId in high 32 bits, avatar in low
        self.csm.air.send(dg)
        
        # Tell TTFriendsManager somebody is logging in:
        self.csm.air.friendsManager.toonOnline(self.avId, self.avatar)

        # Tell the GlobalPartyManager as well
        self.csm.air.globalPartyMgr.avatarJoined(self.avId)

        self.csm.air.writeServerEvent('avatarChosen', self.avId, self.target)
        self.demand('Off')
    def enterSetAccount(self):
        # First, if there's anybody on the account, kill 'em for redundant login:
        dg = PyDatagram()
        dg.addServerHeader(self.csm.GetAccountConnectionChannel(self.accountId),
                           self.csm.air.ourChannel, CLIENTAGENT_EJECT)
        dg.addUint16(100)
        dg.addString('This account has been logged in elsewhere.')
        self.csm.air.send(dg)

        # Next, add this connection to the account channel.
        dg = PyDatagram()
        dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL)
        dg.addChannel(self.csm.GetAccountConnectionChannel(self.accountId))
        self.csm.air.send(dg)

        # Now set their sender channel to represent their account affiliation:
        dg = PyDatagram()
        dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_SET_CLIENT_ID)
        dg.addChannel(self.accountId << 32) # accountId in high 32 bits, 0 in low (no avatar)
        self.csm.air.send(dg)

        # Un-sandbox them!
        dg = PyDatagram()
        dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_SET_STATE)
        dg.addUint16(2) # ESTABLISHED state.
        self.csm.air.send(dg)

        fields = {'LAST_LOGIN': time.ctime(), 'ACCOUNT_ID': str(self.databaseId)}
        
        if self.adminAccess != -1:
            fields.update({'ADMIN_ACCESS': self.adminAccess})
            
        # Update the last login timestamp:
        self.csm.air.dbInterface.updateObject(
            self.csm.air.dbId,
            self.accountId,
            self.csm.air.dclassesByName['AccountUD'],
            fields)

        # We're done.
        self.csm.air.writeServerEvent('accountLogin', self.target, self.accountId, self.databaseId)
        self.csm.sendUpdateToChannel(self.target, 'acceptLogin', [])
        self.csm.account2username[self.target] = self.username
        self.demand('Off')
    def enterUnloadAvatar(self):
        channel = self.csm.GetAccountConnectionChannel(self.target)

        # Tell TTIFriendsManager somebody is logging off:
        self.csm.air.friendsManager.toonOffline(self.avId)

        # Clear off POSTREMOVE:
        datagram = PyDatagram()
        datagram.addServerHeader(
            channel,
            self.csm.air.ourChannel,
            CLIENTAGENT_CLEAR_POST_REMOVES)
        self.csm.air.send(datagram)

        # Remove avatar channel:
        datagram = PyDatagram()
        datagram.addServerHeader(
            channel,
            self.csm.air.ourChannel,
            CLIENTAGENT_CLOSE_CHANNEL)
        datagram.addChannel(self.csm.GetPuppetConnectionChannel(self.avId))
        self.csm.air.send(datagram)

        # Reset sender channel:
        datagram = PyDatagram()
        datagram.addServerHeader(
            channel,
            self.csm.air.ourChannel,
            CLIENTAGENT_SET_CLIENT_ID)
        datagram.addChannel(self.target<<32)
        self.csm.air.send(datagram)

        # Unload avatar object:
        datagram = PyDatagram()
        datagram.addServerHeader(
            self.avId,
            channel,
            STATESERVER_OBJECT_DELETE_RAM)
        datagram.addUint32(self.avId)
        self.csm.air.send(datagram)

        # Done!
        self.csm.air.writeServerEvent('avatarUnload', self.avId)
        self.demand('Off')
    def enterSetAvatar(self):
        channel = self.csm.GetAccountConnectionChannel(self.target)

        # First, give them a POSTREMOVE to unload the avatar, just in case they
        # disconnect while we're working.
        datagramCleanup = PyDatagram()
        datagramCleanup.addServerHeader(
            self.avId,
            channel,
            STATESERVER_OBJECT_DELETE_RAM)
        datagramCleanup.addUint32(self.avId)
        datagram = PyDatagram()
        datagram.addServerHeader(
            channel,
            self.csm.air.ourChannel,
            CLIENTAGENT_ADD_POST_REMOVE)
        datagram.addString(datagramCleanup.getMessage())
        self.csm.air.send(datagram)

        # Activate the avatar on the DBSS:
        self.csm.air.sendActivate(
            self.avId, 0, 0, self.csm.air.dclassesByName['DistributedToonUD'],
            {'setAdminAccess': [self.account.get('ACCESS_LEVEL', 100)],
             'setBankMoney': [self.account.get('MONEY', 0)]})

        # Next, add them to the avatar channel:
        datagram = PyDatagram()
        datagram.addServerHeader(
            channel,
            self.csm.air.ourChannel,
            CLIENTAGENT_OPEN_CHANNEL)
        datagram.addChannel(self.csm.GetPuppetConnectionChannel(self.avId))
        self.csm.air.send(datagram)

        # Now set their sender channel to represent their account affiliation:
        datagram = PyDatagram()
        datagram.addServerHeader(
            channel,
            self.csm.air.ourChannel,
            CLIENTAGENT_SET_CLIENT_ID)
        datagram.addChannel(self.target<<32 | self.avId)
        self.csm.air.send(datagram)

        # Eliminate race conditions.
        taskMgr.doMethodLater(0.2, self.enterSetAvatarTask,
                              'avatarTask-%s' % self.avId, extraArgs=[channel],
                              appendTask=True)
    def enterSetAccount(self):
        # If necessary, update their account information:
        if self.accessLevel:
            self.csm.air.dbInterface.updateObject(
                self.csm.air.dbId,
                self.accountId,
                self.csm.air.dclassesByName['AccountUD'],
                {'ACCESS_LEVEL': self.accessLevel})

        # If there's anybody on the account, kill them for redundant login:
        datagram = PyDatagram()
        datagram.addServerHeader(
            self.csm.GetAccountConnectionChannel(self.accountId),
            self.csm.air.ourChannel,
            CLIENTAGENT_EJECT)
        datagram.addUint16(100)
        datagram.addString('This account has been logged in from elsewhere.')
        self.csm.air.send(datagram)

        # Next, add this connection to the account channel.
        datagram = PyDatagram()
        datagram.addServerHeader(
            self.target,
            self.csm.air.ourChannel,
            CLIENTAGENT_OPEN_CHANNEL)
        datagram.addChannel(self.csm.GetAccountConnectionChannel(self.accountId))
        self.csm.air.send(datagram)

        # Add this connection to extra channels which may be useful:
        if self.accessLevel > 100:
            datagram = PyDatagram()
            datagram.addServerHeader(self.target, self.csm.air.ourChannel,
                                     CLIENTAGENT_OPEN_CHANNEL)
            datagram.addChannel(OtpDoGlobals.OTP_STAFF_CHANNEL)
            self.csm.air.send(datagram)

        # Now set their sender channel to represent their account affiliation:
        datagram = PyDatagram()
        datagram.addServerHeader(
            self.target,
            self.csm.air.ourChannel,
            CLIENTAGENT_SET_CLIENT_ID)
        # Account ID in high 32 bits, 0 in low (no avatar):
        datagram.addChannel(self.accountId << 32)
        self.csm.air.send(datagram)

        # Un-sandbox them!
        datagram = PyDatagram()
        datagram.addServerHeader(
            self.target,
            self.csm.air.ourChannel,
            CLIENTAGENT_SET_STATE)
        datagram.addUint16(2)  # ESTABLISHED
        self.csm.air.send(datagram)

        # Update the last login timestamp:
        self.csm.air.dbInterface.updateObject(
            self.csm.air.dbId,
            self.accountId,
            self.csm.air.dclassesByName['AccountUD'],
            {'LAST_LOGIN': time.ctime(),
             'ACCOUNT_ID': str(self.userId)})

        # We're done.
        self.csm.air.writeServerEvent('accountLogin', self.target, self.accountId, self.userId)
        self.csm.sendUpdateToChannel(self.target, 'acceptLogin', [int(time.time())])
        self.demand('Off')
 def claimOwnership(self, channelId):
     datagram = PyDatagram()
     datagram.addServerHeader(channelId, self.ourChannel, STATESERVER_OBJECT_SET_AI)
     datagram.addChannel(self.ourChannel)
     self.send(datagram)