def receive_update_field(self, dgi, do_id=None): if do_id is None: do_id = dgi.get_uint32() field_number = dgi.get_uint16() field = self.service.dc_file.fields[field_number]() sendable = False if field.is_ownsend and do_id in self.owned_objects: sendable = True elif field.is_clsend: sendable = True if not sendable: self.disconnect(ClientDisconnect.INTERNAL_ERROR, 'Tried to send nonsendable field to object.') self.service.log.warn( f'Client {self.channel} tried to update {do_id} with nonsendable field {field.name}. ' f'DCField keywords: {field.keywords}') return pos = dgi.tell() field.unpack_bytes(dgi) dgi.seek(pos) resp = Datagram() resp.add_server_header([do_id], self.channel, STATESERVER_OBJECT_UPDATE_FIELD) resp.add_uint32(do_id) resp.add_uint16(field_number) resp.add_bytes(dgi.remaining_bytes()) self.service.send_datagram(resp)
async def get_stored_values(self, sender, context, do_id, fields): try: field_dict = await self.backend.query_object_fields(do_id, [field.name for field in fields]) except OTPQueryNotFound: field_dict = None self.log.debug(f'Received query request from {sender} with context {context} for do_id: {do_id}.') dg = Datagram() dg.add_server_header([sender], DBSERVERS_CHANNEL, DBSERVER_GET_STORED_VALUES_RESP) dg.add_uint32(context) dg.add_uint32(do_id) pos = dg.tell() dg.add_uint16(0) if field_dict is None: print('object not found... %s' % do_id, sender, context) self.send_datagram(dg) return counter = 0 for field in fields: if field.name not in field_dict: continue if field_dict[field.name] is None: continue dg.add_uint16(field.number) dg.add_bytes(field_dict[field.name]) counter += 1 dg.seek(pos) dg.add_uint16(counter) self.send_datagram(dg)
def handle_one_update(self, dgi, sender): field_id = dgi.get_uint16() field = self.dclass.dcfile().fields[field_id]() pos = dgi.tell() data = field.unpack_bytes(dgi) if isinstance(field, MolecularField): dgi.seek(pos) self.save_molecular(field, dgi) else: self.save_field(field, data) targets = [] if field.is_broadcast: targets.append(location_as_channel(self.parent_id, self.zone_id)) if field.is_airecv and self.ai_channel and self.ai_channel != sender: targets.append(self.ai_channel) if field.is_ownrecv and self.owner_channel and self.owner_channel != sender: targets.append(self.owner_channel) if targets: dg = Datagram() dg.add_server_header(targets, sender, STATESERVER_OBJECT_UPDATE_FIELD) dg.add_uint32(self.do_id) dg.add_uint16(field_id) dg.add_bytes(data) self.service.send_datagram(dg)
async def created_avatar(self): f = DatagramFuture(self.service.loop, DBSERVER_CREATE_STORED_OBJECT_RESP) self.futures.append(f) sender, dgi = await f context = dgi.get_uint32() return_code = dgi.get_uint8() av_id = dgi.get_uint32() av = self.potential_avatar av.do_id = av_id self.potential_avatars[av.index] = av self.potential_avatar = None resp = Datagram() resp.add_uint16(CLIENT_CREATE_AVATAR_RESP) resp.add_uint16(0) # Context resp.add_uint8(return_code) # Return Code resp.add_uint32(av_id) # av_id self.send_datagram(resp) self.created_av_id = av_id self.service.log.debug( f'New avatar {av_id} created for client {self.channel}.')
def removeInterest(self, client_channel, handle, context): dg = Datagram() dg.add_server_header([client_channel], self.ourChannel, CLIENT_AGENT_REMOVE_INTEREST) dg.add_uint16(handle) dg.add_uint32(context) self.send(dg)
def test_get_remaining(self): dg = Datagram() dg.add_string16(b'test string') dg.add_uint32(2525) dgi = dg.iterator() self.assertEqual(dgi.remaining(), 2 + len('test string') + 4) self.assertEqual(dgi.get_remaining(), dg.get_message().tobytes())
def sendFriendOnline(self, avId, otherAvId): # Need this delay so that `setFriendsList` is set first to avoid # the online whisper message. dg = Datagram() dg.add_server_header([getPuppetChannel(avId)], self.air.ourChannel, CLIENT_FRIEND_ONLINE) dg.add_uint32(otherAvId) self.air.send(dg)
def receive_remove_interest(self, dgi, ai=False): handle = dgi.get_uint16() if dgi.remaining(): context = dgi.get_uint32() else: context = None interest = None for _interest in self.interests: if _interest.handle == handle: interest = _interest break if not interest: self.service.log.debug( f'Got unexpected interest removal from client {self.channel} for interest handle ' f'{handle} with context {context}') return self.service.log.debug( f'Got remove interest request from client {self.channel} for interest handle ' f'{handle} with context {context}') parent_id = interest.parent_id uninterested_zones = [] for zone in interest.zones: if len(self.lookup_interest(parent_id, zone)) == 1: uninterested_zones.append(zone) to_remove = [] for do_id in self.visible_objects: do = self.visible_objects[do_id] if do.parent_id == parent_id and do.zone_id in uninterested_zones: self.service.log.debug( f'Object {do_id} killed by interest remove.') self.send_remove_object(do_id) to_remove.append(do_id) for do_id in to_remove: del self.visible_objects[do_id] for zone in uninterested_zones: self.unsubscribe_channel(location_as_channel(parent_id, zone)) self.interests.remove(interest) if not ai: resp = Datagram() resp.add_uint16(CLIENT_DONE_INTEREST_RESP) resp.add_uint16(handle) resp.add_uint32(context) self.send_datagram(resp)
def receive_create_avatar(self, dgi): _ = dgi.get_uint16() dna = dgi.get_blob16() pos = dgi.get_uint8() self.service.log.debug( f'Client {self.channel} requesting avatar creation with dna {dna} and pos {pos}.' ) if not 0 <= pos < 6 or self.potential_avatars[pos] is not None: self.service.log.debug( f'Client {self.channel} tried creating avatar in invalid position.' ) return self.potential_avatar = PotentialAvatar(do_id=0, name='Toon', wish_name='', approved_name='', rejected_name='', dna_string=dna, index=pos) dclass = self.service.dc_file.namespace['DistributedToon'] dg = Datagram() dg.add_server_header([DBSERVERS_CHANNEL], self.channel, DBSERVER_CREATE_STORED_OBJECT) dg.add_uint32(0) dg.add_uint16(dclass.number) dg.add_uint32(self.account.disl_id) dg.add_uint8(pos) pos = dg.tell() dg.add_uint16(0) default_toon = dict(DEFAULT_TOON) default_toon['setDNAString'] = (dna, ) default_toon['setDISLid'] = (self.account.disl_id, ) default_toon['WishName'] = ('', ) default_toon['WishNameState'] = ('CLOSED', ) count = 0 for field in dclass.inherited_fields: if not isinstance(field, MolecularField) and field.is_db: if field.name == 'DcObjectType': continue dg.add_uint16(field.number) field.pack_value(dg, default_toon[field.name]) count += 1 dg.seek(pos) dg.add_uint16(count) self.state = ClientState.CREATING_AVATAR self.service.send_datagram(dg) self.tasks.append(self.service.loop.create_task(self.created_avatar()))
def test_add_uint32(self): dg = Datagram() dg.add_uint32(1 << 31) other = struct.pack('<I', 1 << 31) self.assertEqual(dg.bytes(), other) with self.assertRaises(OverflowError): dg.add_uint32(1 << 32)
def handle_query_all(self, dgi, sender): other = dgi.get_uint8() context = dgi.get_uint32() resp = Datagram() resp.add_server_header([sender], self.do_id, STATESERVER_QUERY_OBJECT_ALL_RESP) resp.add_uint32(self.do_id) resp.add_uint16(context) self.append_required_data(resp, False, True) self.service.send_datagram(resp)
def ai_format_update(self, do_id, to_id, from_id, args): dg = Datagram() dg.add_uint8(1) dg.add_channel(to_id) dg.add_channel(from_id) dg.add_uint16(STATESERVER_OBJECT_UPDATE_FIELD) dg.add_uint32(do_id) dg.add_uint16(self.number) self.pack_value(dg, args) return dg
def createObjects(self): self.registerForChannel(self.ourChannel) from .Objects import ToontownDistrictAI, ToontownDistrictStatsAI, DistributedInGameNewsMgrAI, NewsManagerAI, FriendManagerAI from .TimeManagerAI import TimeManagerAI self.district = ToontownDistrictAI(self) self.district.name = 'Nutty River' self.generateWithRequired(self.district, OTP_DO_ID_TOONTOWN, OTP_ZONE_ID_DISTRICTS) post_remove = Datagram() post_remove.add_server_control_header(CONTROL_ADD_POST_REMOVE) post_remove.add_server_header([ STATESERVERS_CHANNEL, ], self.ourChannel, STATESERVER_SHARD_REST) post_remove.add_channel(self.ourChannel) self.send(post_remove) dg = Datagram() dg.add_server_header([STATESERVERS_CHANNEL], self.ourChannel, STATESERVER_ADD_AI_RECV) dg.add_uint32(self.district.do_id) dg.add_channel(self.ourChannel) self.send(dg) stats = ToontownDistrictStatsAI(self) stats.settoontownDistrictId(self.district.do_id) self.generateWithRequired(stats, OTP_DO_ID_TOONTOWN, OTP_ZONE_ID_DISTRICTS_STATS) dg = Datagram() dg.add_server_header([STATESERVERS_CHANNEL], self.ourChannel, STATESERVER_ADD_AI_RECV) dg.add_uint32(stats.do_id) dg.add_channel(self.ourChannel) self.send(dg) self.timeManager = TimeManagerAI(self) self.timeManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT) self.ingameNewsMgr = DistributedInGameNewsMgrAI(self) self.ingameNewsMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT) self.newsManager = NewsManagerAI(self) self.newsManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT) self.friendManager = FriendManagerAI(self) self.friendManager.generateGlobalObject(OTP_ZONE_ID_MANAGEMENT) self.loadZones() self.district.b_setAvailable(True)
def receive_get_avatars(self, dgi): query = Datagram() query.add_server_header([ DBSERVERS_CHANNEL, ], self.channel, DBSERVER_ACCOUNT_QUERY) disl_id = self.account.disl_id query.add_uint32(disl_id) field_number = self.service.avatars_field.number query.add_uint16(field_number) self.service.send_datagram(query) self.tasks.append(self.service.loop.create_task(self.do_login()))
async def create_object(self, sender, context, dclass, fields): try: do_id = await self.backend.create_object(dclass, fields) except OTPCreateFailed as e: print('creation failed', e) do_id = 0 dg = Datagram() dg.add_server_header([sender], DBSERVERS_CHANNEL, DBSERVER_CREATE_STORED_OBJECT_RESP) dg.add_uint32(context) dg.add_uint8(do_id == 0) dg.add_uint32(do_id) self.send_datagram(dg)
def receive_delete_avatar(self, dgi): av_id = dgi.get_uint32() av = self.get_potential_avatar(av_id) if not av: return self.potential_avatars[av.index] = None avatars = [ pot_av.do_id if pot_av else 0 for pot_av in self.potential_avatars ] self.avs_deleted.append((av_id, int(time.time()))) field = self.service.dc_file.namespace['Account']['ACCOUNT_AV_SET'] del_field = self.service.dc_file.namespace['Account'][ 'ACCOUNT_AV_SET_DEL'] dg = Datagram() dg.add_server_header([DBSERVERS_CHANNEL], self.channel, DBSERVER_SET_STORED_VALUES) dg.add_uint32(self.account.disl_id) dg.add_uint16(2) dg.add_uint16(field.number) field.pack_value(dg, avatars) dg.add_uint16(del_field.number) del_field.pack_value(dg, self.avs_deleted) self.service.send_datagram(dg) resp = Datagram() resp.add_uint16(CLIENT_DELETE_AVATAR_RESP) resp.add_uint8(0) # Return code av_count = sum( (1 if pot_av else 0 for pot_av in self.potential_avatars)) dg.add_uint16(av_count) for pot_av in self.potential_avatars: if not pot_av: continue dg.add_uint32(pot_av.do_id) dg.add_string16(pot_av.name.encode('utf-8')) dg.add_string16(pot_av.wish_name.encode('utf-8')) dg.add_string16(pot_av.approved_name.encode('utf-8')) dg.add_string16(pot_av.rejected_name.encode('utf-8')) dg.add_string16(pot_av.dna_string.encode('utf-8')) dg.add_uint8(pot_av.index) self.send_datagram(resp)
def handle_owned_object_entrance(self, dgi, sender): do_id = dgi.get_uint32() parent_id = dgi.get_uint32() zone_id = dgi.get_uint32() dc_id = dgi.get_uint16() self.owned_objects[do_id] = ObjectInfo(do_id, dc_id, parent_id, zone_id) resp = Datagram() resp.add_uint16(CLIENT_GET_AVATAR_DETAILS_RESP) resp.add_uint32(self.avatar_id) resp.add_uint8(0) # Return code resp.add_bytes(dgi.remaining_bytes()) self.send_datagram(resp)
def save_field(self, field: AtomicField, data): if field.is_required: self.required[field.name] = data elif field.is_ram: self.ram[field.name] = data if self.db and field.is_db: dg = Datagram() dg.add_server_header([DBSERVERS_CHANNEL], self.do_id, DBSERVER_SET_STORED_VALUES) dg.add_uint32(self.do_id) dg.add_uint16(1) dg.add_uint16(field.number) dg.add_bytes(data) self.service.send_datagram(dg) self.service.log.debug(f'Object {self.do_id} saved value {data} for field {field.name} to database.')
def handle_location_change(self, new_parent, new_zone, sender): old_parent = self.parent_id old_zone = self.zone_id targets = list() if self.ai_channel is not None: targets.append(self.ai_channel) if self.owner_channel is not None: targets.append(self.owner_channel) if new_parent == self.do_id: raise Exception('Object cannot be parented to itself.\n') if new_parent != old_parent: if old_parent: self.unsubscribe_channel(parent_to_children(old_parent)) targets.append(old_parent) targets.append(location_as_channel(old_parent, old_zone)) self.parent_id = new_parent self.zone_id = new_zone if new_parent: self.subscribe_channel(parent_to_children(new_parent)) if not self.ai_explicitly_set: new_ai_channel = self.service.resolve_ai_channel(new_parent) if new_ai_channel != self.ai_channel: self.ai_channel = new_ai_channel self.send_ai_entry(new_ai_channel) targets.append(new_parent) elif new_zone != old_zone: self.zone_id = new_zone targets.append(self.parent_id) targets.append(location_as_channel(self.parent_id, old_zone)) else: # Not changing zones. return dg = Datagram() dg.add_server_header(targets, sender, STATESERVER_OBJECT_CHANGE_ZONE) dg.add_uint32(self.do_id) dg.add_uint32(new_parent) dg.add_uint32(new_zone) dg.add_uint32(old_parent) dg.add_uint32(old_zone) self.service.send_datagram(dg) self.parent_synced = False if new_parent: self.send_location_entry(location_as_channel(new_parent, new_zone))
def activate_callback(self, dgi): context = dgi.get_uint32() do_id = dgi.get_uint32() state_server = self.service parent_id, zone_id, owner_channel, number, other_data = state_server.queries[do_id] dclass = state_server.dc_file.classes[number] del state_server.queries[do_id] required = {} ram = {} count = dgi.get_uint16() for i in range(count): field_number = dgi.get_uint16() field = state_server.dc_file.fields[field_number]() if field.is_required: required[field.name] = field.unpack_bytes(dgi) else: ram[field.name] = field.unpack_bytes(dgi) for field_number, data in other_data: field = state_server.dc_file.fields[field_number]() if field.is_required: required[field.name] = data else: ram[field.name] = data if field.is_db: dg = Datagram() dg.add_server_header([DBSERVERS_CHANNEL], do_id, DBSERVER_SET_STORED_VALUES) dg.add_uint32(do_id) dg.add_uint16(1) dg.add_uint16(field.number) dg.add_bytes(data) self.service.send_datagram(dg) self.service.log.debug(f'Activating {do_id} with required:{required}\nram:{ram}\n') obj = DistributedObject(state_server, STATESERVERS_CHANNEL, do_id, parent_id, zone_id, dclass, required, ram, owner_channel=owner_channel, db=True) state_server.database_objects.add(do_id) state_server.objects[do_id] = obj obj.send_owner_entry(owner_channel)
def handle_db_generate(self, dgi, sender, other=False): do_id = dgi.get_uint32() if do_id in self.service.queries or do_id in self.service.database_objects: self.service.log.debug(f'Got duplicate activate request for object {do_id} from {sender}') return parent_id = dgi.get_uint32() zone_id = dgi.get_uint32() owner_channel = dgi.get_channel() number = dgi.get_uint16() other_data = [] state_server = self.service if other: field_count = dgi.get_uint16() for i in range(field_count): field_number = dgi.get_uint16() field = state_server.dc_file.fields[field_number]() data = field.unpack_bytes(dgi) other_data.append((field_number, data)) dclass = state_server.dc_file.classes[number] query = Datagram() query.add_server_header([DBSERVERS_CHANNEL], STATESERVERS_CHANNEL, DBSERVER_GET_STORED_VALUES) query.add_uint32(1) query.add_uint32(do_id) pos = query.tell() query.add_uint16(0) count = 0 for field in dclass: if not isinstance(field, MolecularField) and field.is_db: if field.name == 'DcObjectType': continue query.add_uint16(field.number) count += 1 query.seek(pos) query.add_uint16(count) self.service.log.debug(f'Querying {count} fields for {dclass.name} {do_id}. Other data: {other_data}') self.service.queries[do_id] = (parent_id, zone_id, owner_channel, number, other_data) self.service.send_datagram(query)
async def query_account(self, sender, do_id): dclass = self.dc.namespace['Account'] toon_dclass = self.dc.namespace['DistributedToon'] field_dict = await self.backend.query_object_all(do_id, dclass.name) temp = Datagram() temp.add_bytes(field_dict['ACCOUNT_AV_SET']) av_ids = dclass['ACCOUNT_AV_SET'].unpack_value(temp.iterator()) dg = Datagram() dg.add_server_header([sender], DBSERVERS_CHANNEL, DBSERVER_ACCOUNT_QUERY_RESP) dg.add_bytes(field_dict['ACCOUNT_AV_SET_DEL']) av_count = sum((1 if av_id else 0 for av_id in av_ids)) self.log.debug(f'Account query for {do_id} from {sender}: {field_dict}') dg.add_uint16(av_count) # Av count for av_id in av_ids: if not av_id: continue toon_fields = await self.backend.query_object_fields(av_id, ['setName', 'WishNameState', 'WishName', 'setDNAString'], 'DistributedToon') wish_name = toon_fields['WishName'] temp = Datagram() temp.add_bytes(toon_fields['WishNameState']) name_state = toon_dclass['WishNameState'].unpack_value(temp.iterator()) dg.add_uint32(av_id) dg.add_bytes(toon_fields['setName']) pending_name = b'\x00\x00' approved_name = b'\x00\x00' rejected_name = b'\x00\x00' if name_state == 'APPROVED': approved_name = wish_name elif name_state == 'REJECTED': rejected_name = wish_name else: pending_name = wish_name dg.add_bytes(pending_name) dg.add_bytes(approved_name) dg.add_bytes(rejected_name) dg.add_bytes(toon_fields['setDNAString']) dg.add_uint8(av_ids.index(av_id)) self.send_datagram(dg)
def handle_interest_done(self, dgi): handle = dgi.get_uint16() context = dgi.get_uint32() self.service.log.debug( f'sending interest done for handle {handle} context {context}') interest = None for _interest in self.interests: if _interest.handle == handle and _interest.context == context: interest = _interest break if not interest: self.service.log.debug( f'Got interest done for unknown interest: {handle} {context}') return if interest.done: self.service.log.debug('Received duplicate interest done...') return interest.done = True pending = [ self.pending_objects.pop(do_id) for do_id in interest.pending_objects if do_id in self.pending_objects ] # Need this sorting. pending.sort(key=lambda p: p.dc_id) del interest.pending_objects[:] self.service.log.debug( f'Replaying datagrams for {[p.do_id for p in pending]}') for pending_object in pending: for datagram in pending_object.datagrams: self.handle_datagram(datagram, datagram.iterator()) if not interest.ai: resp = Datagram() resp.add_uint16(CLIENT_DONE_INTEREST_RESP) resp.add_uint16(handle) resp.add_uint32(context) self.send_datagram(resp)
def sendLocation(self, do_id, old_parent: int, old_zone: int, new_parent: int, new_zone: int): dg = Datagram() dg.add_server_header([do_id], self.ourChannel, STATESERVER_OBJECT_SET_ZONE) dg.add_uint32(new_parent) dg.add_uint32(new_zone) dg.add_uint32(old_parent) dg.add_uint32(old_zone) self.send(dg)
def on_upstream_connect(self): self.subscribe_channel(self._client, self.GLOBAL_ID) self.log.debug('Uberdog online') dg = self.dclass.ai_format_generate(self, self.GLOBAL_ID, self.GAME_ID, OTP_ZONE_ID_MANAGEMENT, STATESERVERS_CHANNEL, self.GLOBAL_ID, optional_fields=None) self.send_datagram(dg) dg = Datagram() dg.add_server_control_header(CONTROL_ADD_POST_REMOVE) dg.add_server_header([self.GLOBAL_ID], self.GLOBAL_ID, STATESERVER_OBJECT_DELETE_RAM) dg.add_uint32(self.GLOBAL_ID) self.send_datagram(dg)
def test_overwrite(self): dg = Datagram() dg.add_uint32(2828) pos = dg.tell() self.assertEqual(pos, 4) dg.add_uint16(24) dg.add_int64(-352793) dg.seek(pos) dg.add_uint16(5000) dg.seek(len(dg)) dg.add_string32(b'overwrite') dgi = dg.iterator() self.assertEqual(dgi.get_uint32(), 2828) self.assertEqual(dgi.get_uint16(), 5000) self.assertEqual(dgi.get_int64(), -352793) self.assertEqual(dgi.get_string32(), 'overwrite')
def handle_datagram(self, dg, dgi): sender = dgi.get_channel() msgtype = dgi.get_uint16() self.service.log.debug(f'State server directly received msgtype {MSG_TO_NAME_DICT[msgtype]} from {sender}.') if msgtype == STATESERVER_OBJECT_GENERATE_WITH_REQUIRED: self.handle_generate(dgi, sender, False) elif msgtype == STATESERVER_OBJECT_GENERATE_WITH_REQUIRED_OTHER: self.handle_generate(dgi, sender, True) elif msgtype == STATESERVER_OBJECT_CREATE_WITH_REQUIRED_CONTEXT: # DBSS msg self.handle_db_generate(dgi, sender, False) elif msgtype == STATESERVER_OBJECT_CREATE_WITH_REQUIR_OTHER_CONTEXT: # DBSS msg self.handle_db_generate(dgi, sender, True) elif msgtype == STATESERVER_ADD_AI_RECV: self.handle_add_ai(dgi, sender) elif msgtype == STATESERVER_OBJECT_SET_OWNER_RECV: self.handle_set_owner(dgi, sender) elif msgtype == DBSERVER_GET_STORED_VALUES_RESP: self.activate_callback(dgi) elif msgtype == STATESERVER_SHARD_REST: self.handle_shard_rest(dgi) elif msgtype == STATESERVER_OBJECT_LOCATE: context = dgi.get_uint32() do_id = dgi.get_uint32() do = self.service.objects.get(do_id) resp = Datagram() resp.add_server_header([sender], do_id, STATESERVER_OBJECT_LOCATE_RESP) resp.add_uint32(context) resp.add_uint32(do_id) if do is None: resp.add_uint8(False) self.service.send_datagram(resp) else: resp.add_uint8(True) parent_id, zone_id = do.parent_id, do.zone_id resp.add_uint32(parent_id) resp.add_uint32(zone_id) ai_channel = do.ai_channel if do.ai_channel else 0 resp.add_uint32(ai_channel) self.service.send_datagram(resp)
def handle_update_field(self, dgi, sender, do_id): if sender == self.channel: return if not self.object_exists(do_id): self.service.log.debug( f'Got field update for unknown object {do_id}') pos = dgi.tell() field_number = dgi.get_uint16() field = self.service.dc_file.fields[field_number]() resp = Datagram() resp.add_uint16(CLIENT_OBJECT_UPDATE_FIELD) resp.add_uint32(do_id) resp.add_uint16(field_number) resp.add_bytes(dgi.remaining_bytes()) self.send_datagram(resp)
def receive_set_wishname(self, dgi): av_id = dgi.get_uint32() name = dgi.get_string16() av = self.get_potential_avatar(av_id) self.service.log.debug( f'Received wishname request from {self.channel} for avatar {av_id} for name "{name}".' ) pending = name.encode('utf-8') approved = b'' rejected = b'' failed = False resp = Datagram() resp.add_uint16(CLIENT_SET_WISHNAME_RESP) resp.add_uint32(av_id) resp.add_uint16(failed) resp.add_string16(pending) resp.add_string16(approved) resp.add_string16(rejected) self.send_datagram(resp) if av_id and av: dclass = self.service.dc_file.namespace['DistributedToon'] wishname_field = dclass['WishName'] wishname_state_field = dclass['WishNameState'] resp = Datagram() resp.add_server_header([DBSERVERS_CHANNEL], self.channel, DBSERVER_SET_STORED_VALUES) resp.add_uint32(av_id) resp.add_uint16(2) resp.add_uint16(wishname_state_field.number) wishname_state_field.pack_value(resp, ('PENDING', )) resp.add_uint16(wishname_field.number) wishname_field.pack_value(resp, (name, )) self.service.send_datagram(resp)
async def query_location(self, avId, context): dg = Datagram() dg.add_server_header([STATESERVERS_CHANNEL], self.GLOBAL_ID, STATESERVER_OBJECT_LOCATE) dg.add_uint32(context) dg.add_uint32(avId) self.send_datagram(dg) f = self.register_future(STATESERVER_OBJECT_LOCATE_RESP, avId, context) try: sender, dgi = await asyncio.wait_for(f, timeout=10, loop=self.loop) except TimeoutError: return None, None dgi.get_uint32(), dgi.get_uint32() success = dgi.get_uint8() if not success: return None, None parent_id, zone_id = dgi.get_uint32(), dgi.get_uint32() return parent_id, zone_id