Пример #1
0
 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)
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
 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)
Пример #6
0
 def send_location_entry(self, location):
     dg = Datagram()
     dg.add_server_header([location], self.do_id, STATESERVER_OBJECT_ENTERZONE_WITH_REQUIRED_OTHER)
     dg.add_uint8(bool(self.ram))
     self.append_required_data(dg, True, False)
     if self.ram:
         self.append_other_data(dg, True, False)
     self.service.send_datagram(dg)
Пример #7
0
    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))
Пример #8
0
    def send_ai_entry(self, location):
        dg = Datagram()
        dg.add_server_header([location], self.do_id, STATESERVER_OBJECT_ENTER_AI_RECV)
        self.append_required_data(dg, False, False)

        if self.ram:
            self.append_other_data(dg, False, False)

        self.service.send_datagram(dg)
Пример #9
0
    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()))
Пример #10
0
 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)
Пример #11
0
 def setInterest(self, client_channel, handle, context, parent_id, zones):
     dg = Datagram()
     dg.add_server_header([client_channel], self.ourChannel,
                          CLIENT_AGENT_SET_INTEREST)
     dg.add_uint16(handle)
     dg.add_uint32(context)
     dg.add_uint32(parent_id)
     for zone in zones:
         dg.add_uint32(zone)
     self.send(dg)
Пример #12
0
    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)
Пример #13
0
 def test_server_header(self):
     dg = Datagram()
     targets = [4200, 2878, 300, 1]
     dg.add_server_header(targets, 10000000, 1)
     dgi = dg.iterator()
     self.assertEqual(dgi.get_uint8(), 4)
     self.assertEqual(dgi.get_channel(), 4200)
     self.assertEqual(dgi.get_channel(), 2878)
     self.assertEqual(dgi.get_channel(), 300)
     self.assertEqual(dgi.get_channel(), 1)
     self.assertEqual(dgi.get_channel(), 10000000)
     self.assertEqual(dgi.get_uint16(), 1)
Пример #14
0
    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()))
Пример #15
0
    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)
Пример #16
0
    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)
Пример #17
0
    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.')
Пример #18
0
    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)
Пример #19
0
    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)
Пример #20
0
    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)
Пример #21
0
    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)
Пример #22
0
    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)
Пример #23
0
    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)
Пример #24
0
    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
Пример #25
0
    async def create_toon(self, sender, context, dclass, disl_id, pos, fields):
        try:
            do_id = await self.backend.create_object(dclass, fields)
            account = await self.backend.query_object_fields(disl_id, ['ACCOUNT_AV_SET'], 'Account')
            temp = Datagram()
            temp.add_bytes(account['ACCOUNT_AV_SET'])
            av_set = self.dc.namespace['Account']['ACCOUNT_AV_SET'].unpack_value(temp.iterator())
            print(do_id, disl_id, pos, av_set)
            av_set[pos] = do_id
            temp.seek(0)
            self.dc.namespace['Account']['ACCOUNT_AV_SET'].pack_value(temp, av_set)
            await self.backend.set_field(disl_id, 'ACCOUNT_AV_SET', temp.bytes(), 'Account')
        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)
Пример #26
0
    def receive_client_location(self, dgi):
        do_id = dgi.get_uint32()
        parent_id = dgi.get_uint32()
        zone_id = dgi.get_uint32()

        self.service.log.debug(
            f'Client {self.channel} is setting their location to {parent_id} {zone_id}'
        )

        if do_id in self.owned_objects:
            self.owned_objects[do_id].zone_id = zone_id
            self.owned_objects[do_id].parent_id = parent_id
            dg = Datagram()
            dg.add_server_header([do_id], self.channel,
                                 STATESERVER_OBJECT_SET_ZONE)
            dg.add_uint32(parent_id)
            dg.add_uint32(zone_id)
            self.service.send_datagram(dg)
        else:
            self.service.log.debug(
                f'Client {self.channel} tried setting location for unowned object {do_id}!'
            )
Пример #27
0
    def handle_query_zone(self, dgi, sender):
        # STATESERVER_QUERY_ZONE_OBJECT_ALL_DONE
        handle = dgi.get_uint16()
        context_id = dgi.get_uint32()
        parent_id = dgi.get_uint32()

        if parent_id != self.do_id:
            return

        num_zones = dgi.remaining() // 4

        zones = []

        for i in range(num_zones):
            zones.append(dgi.get_uint32())

        object_ids = []

        for zone in zones:
            if zone not in self.zone_objects:
                continue

            object_ids.extend(self.zone_objects[zone])

        resp = Datagram()
        resp.add_server_header([sender], self.do_id, STATESERVER_QUERY_ZONE_OBJECT_ALL_DONE)
        resp.add_uint16(handle)
        resp.add_uint32(context_id)

        if not len(object_ids):
            self.service.send_datagram(resp)
            return

        self.send_location_entry(sender)

        for do_id in object_ids:
            self.service.objects[do_id].send_location_entry(sender)

        self.service.send_datagram(resp)
Пример #28
0
    def annihilate(self, sender, notify_parent=True):
        targets = list()

        if self.parent_id:
            targets.append(location_as_channel(self.parent_id, self.zone_id))

            if notify_parent:
                dg = Datagram()
                dg.add_server_header([self.parent_id], sender, STATESERVER_OBJECT_CHANGE_ZONE)
                dg.add_uint32(self.do_id)
                dg.add_uint32(0)  # New parent
                dg.add_uint32(0)  # new zone
                dg.add_uint32(self.parent_id)   # old parent
                dg.add_uint32(self.zone_id)  # old zone
                self.service.send_datagram(dg)

        if self.owner_channel:
            targets.append(self.owner_channel)
        if self.ai_channel:
            targets.append(self.ai_channel)

        dg = Datagram()
        dg.add_server_header(targets, sender, STATESERVER_OBJECT_DELETE_RAM)
        dg.add_uint32(self.do_id)
        self.service.send_datagram(dg)

        self.delete_children(sender)

        del self.service.objects[self.do_id]

        self.service.remove_participant(self)

        if self.db:
            self.service.database_objects.remove(self.do_id)

        self.service.log.debug(f'Object {self.do_id} has been deleted.')
Пример #29
0
    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)
Пример #30
0
 def requestDelete(self, do):
     dg = Datagram()
     dg.add_server_header([do.do_id], self.ourChannel,
                          STATESERVER_OBJECT_DELETE_RAM)
     dg.add_uint32(do.do_id)
     self.send(dg)