예제 #1
0
    def handle_query_object_resp(self, message_type, di):
        ctx = di.get_uint32()
        success = di.get_uint8()

        if ctx not in self._callbacks:
            self.notify.warning('Received unexpected %s (ctx %d)' %
                                (MsgId2Names[message_type], ctx))

            return

        try:
            if not success:
                if self._callbacks[ctx]:
                    self._callbacks[ctx](None, None)

                return

            if message_type == types.DBSERVER_OBJECT_GET_ALL_RESP:
                dclass_id = di.get_uint16()
                dclass = self._network.dc_loader.dclasses_by_number.get(
                    dclass_id)
            else:
                dclass = self._dclasses[ctx]

            if not dclass:
                self.notify.error(
                    'Received bad dclass %d in DBSERVER_OBJECT_GET_ALL_RESP' %
                    (dclass_id))

            if message_type == types.DBSERVER_OBJECT_GET_FIELD_RESP:
                field_count = 1
            else:
                field_count = di.get_uint16()

            field_packer = DCPacker()
            field_packer.set_unpack_data(di.get_remaining_bytes())
            fields = {}
            for x in xrange(field_count):
                field_id = field_packer.raw_unpack_uint16()
                field = dclass.get_field_by_index(field_id)

                if not field:
                    self.notify.error(
                        'Received bad field %d in query for %s object' %
                        (field_id, dclass.get_name()))

                field_packer.begin_unpack(field)
                fields[field.get_name()] = field.unpack_args(field_packer)
                field_packer.end_unpack()

            if self._callbacks[ctx]:
                self._callbacks[ctx](dclass, fields)

        finally:
            del self._callbacks[ctx]
            del self._dclasses[ctx]
예제 #2
0
    def handle_object_set_field(self, sender, di):
        do_id = di.get_uint32()
        file_object = self._backend.open_file(
            self._backend.get_filename(do_id))

        if not file_object:
            self.notify.warning(
                'Failed to set fields for object: %d, unknown object!' %
                (do_id))

            return

        dc_name = file_object.get_value('dclass')
        dc_class = self.dc_loader.dclasses_by_name.get(dc_name)

        if not dc_class:
            self.notify.warning(
                'Failed to set fields for object: %d, unknown dclass: %s!' %
                (do_id, dc_name))

            return

        fields = file_object.get_value('fields')

        if not fields:
            self.notify.warning(
                'Failed to set fields for object: %d, invalid fields!' %
                (do_id))

            return

        field_packer = DCPacker()
        field_packer.set_unpack_data(di.get_remaining_bytes())
        field_id = field_packer.raw_unpack_uint16()
        field = dc_class.get_field_by_index(field_id)

        if not field:
            self.notify.error(
                'Failed to unpack field: %d dclass: %s, invalid field!' %
                (field_id, dc_class.get_name()))

        field_packer.begin_unpack(field)
        field_args = field.unpack_args(field_packer)
        field_packer.end_unpack()

        if not field_args:
            self.notify.error(
                'Failed to unpack field args for field: %d dclass: %s, invalid result!'
                % (field.get_name(), dc_class.get_name()))

        fields[field.get_name()] = field_args
        file_object.set_value('fields', fields)

        self._backend.close_file(file_object)
예제 #3
0
    def handle_update_object_resp(self, di, multi):
        ctx = di.get_uint32()
        success = di.get_uint8()

        if ctx not in self._callbacks:
            self.notify.warning(
                'Received unexpected DBSERVER_OBJECT_SET_FIELD(S)_IF_EQUALS_RESP (ctx %d)'
                % (ctx))

            return

        try:
            if success:
                if self._callbacks[ctx]:
                    self._callbacks[ctx](None)

                return

            if not di.get_remaining_size():
                # We failed due to other reasons.
                if self._callbacks[ctx]:
                    return self._callbacks[ctx]({})

            if multi:
                field_count = di.get_uint16()
            else:
                field_count = 1

            field_packer = DCPacker()
            field_packer.set_unpack_data(di.get_remaining_bytes())
            fields = {}
            for x in xrange(field_count):
                fieldId = field_packer.raw_pack_uint16()
                field = self._network.dc_loader.dc_file.get_field_by_index(
                    fieldId)

                if not field:
                    self.notify.error(
                        'Received bad field %d in update failure response message'
                        % (fieldId))

                field_packer.begin_unpack(field)
                fields[field.get_name()] = field.unpack_args(field_packer)
                field_packer.end_unpack()

            if self._callbacks[ctx]:
                self._callbacks[ctx](fields)

        finally:
            del self._callbacks[ctx]
    def __init__(self, network, do_id, parent_id, zone_id, dc_class, has_other,
                 di):
        self._network = network
        self._do_id = do_id

        self._old_owner_id = 0
        self._owner_id = 0

        self._old_parent_id = 0
        self._parent_id = parent_id

        self._old_zone_id = 0
        self._zone_id = zone_id

        self._dc_class = dc_class
        self._has_other = has_other

        self._required_fields = {}
        self._other_fields = {}

        field_packer = DCPacker()
        field_packer.set_unpack_data(di.get_remaining_bytes())

        for field_index in xrange(self._dc_class.get_num_inherited_fields()):
            field = self._dc_class.get_inherited_field(field_index)

            if not field:
                self.notify.error(
                    'Failed to unpack required field: %d dclass: %s, unknown field!'
                    % (field_index, self._dc_class.get_name()))

            if field.as_molecular_field() or not field.is_required():
                continue

            field_packer.begin_unpack(field)
            field_args = field.unpack_args(field_packer)
            field_packer.end_unpack()

            self._required_fields[field.get_number()] = field_args

        self._network.register_for_channel(self._do_id)
    def handle_update_field(self, sender, channel, di):
        field_id = di.get_uint16()
        field = self._dc_class.get_field_by_index(field_id)

        if not field:
            self.notify.warning(
                'Failed to update field: %d dclass: %s, unknown field!' %
                (field_id, self._dc_class.get_name()))

            return

        # copy the field update so we can unpack it and
        # update any required fields here on the state server.
        # we must do this after we allow the field to be updated
        # because the checks to ensure the field is valid must be ran first...
        datagram = io.NetworkDatagram()
        datagram.append_data(di.get_remaining_bytes())

        # create a new datagram iterator object that the field
        # response update can unpack from...
        di = io.NetworkDatagramIterator(datagram)

        # ensure this field is not a bogus field...
        if field.is_bogus_field():
            self.notify.debug(
                'Cannot handle field update for field: %s dclass: %s, field is bogus!'
                % (field.get_name(), self._dc_class.get_name()))

            return

        if not self._network.shard_manager.has_shard(sender):
            avatar_id = self._network.get_avatar_id_from_connection_channel(
                sender)

            if not avatar_id:
                self.notify.warning(
                    'Cannot handle field update for field: %s dclass: %s, unknown avatar: %d!'
                    % (field.get_name(), self._dc_class.get_name(), avatar_id))

                return

            if field.is_ownsend():
                if sender != self._owner_id:
                    self.notify.warning(
                        'Cannot handle field update for field: %s dclass: %s, field not sendable!'
                        % (field.get_name(), self._dc_class.get_name()))

                    return
            else:
                if not field.is_clsend():
                    self.notify.warning(
                        'Cannot handle field update for field: %s dclass: %s, field not sendable!'
                        % (field.get_name(), self._dc_class.get_name()))

                    return

            if not field.is_broadcast():
                self.handle_send_update(field, sender, self._parent_id, di)
            else:
                self.handle_send_update_broadcast(field,
                                                  sender,
                                                  di,
                                                  excludes=[avatar_id])
        else:
            if not field.is_broadcast():
                self.handle_send_update(field, self._parent_id, channel, di)
            else:
                self.handle_send_update_broadcast(field,
                                                  self._parent_id,
                                                  di,
                                                  excludes=[self._do_id])

        # unpack the field arguments so that we can update our
        # view of the object's required or other fields dictionaries...
        di = io.NetworkDatagramIterator(datagram)

        # if the iterator is empty, this means that the field
        # has no arguents and that we should not attempt to update it...
        if not di.get_remaining_size():
            return

        field_packer = DCPacker()
        field_packer.set_unpack_data(di.get_remaining_bytes())

        field_packer.begin_unpack(field)
        field_args = field.unpack_args(field_packer)
        field_packer.end_unpack()

        # check to see if the field is a required or other field,
        # and store the new arguments appropriately.
        if field.is_required():
            self._required_fields[field.get_number()] = field_args
        elif field.is_ram():
            self._other_fields[field.get_number()] = field_args
예제 #6
0
    def handle_create_object(self, sender, di):
        context = di.get_uint32()
        dc_id = di.get_uint16()
        field_count = di.get_uint16()
        dc_class = self.dc_loader.dclasses_by_number.get(dc_id)

        if not dc_class:
            self.notify.error(
                'Failed to create object: %d context: %d, unknown dclass!' %
                (dc_id, context))

        do_id = self._backend.allocator.allocate()
        file_object = self._backend.open_file(
            self._backend.get_filename(do_id))

        file_object.set_value('dclass', dc_class.get_name())
        file_object.set_value('do_id', do_id)

        fields = {}
        field_packer = DCPacker()
        field_packer.set_unpack_data(di.get_remaining_bytes())

        for _ in xrange(field_count):
            field_id = field_packer.raw_unpack_uint16()
            field = dc_class.get_field_by_index(field_id)

            if not field:
                self.notify.error(
                    'Failed to unpack field: %d dclass: %s, invalid field!' %
                    (field_id, dc_class.get_name()))

            field_packer.begin_unpack(field)
            field_args = field.unpack_args(field_packer)
            field_packer.end_unpack()

            if not field_args:
                self.notify.error(
                    'Failed to unpack field args for field: %d dclass: %s, invalid result!'
                    % (field.get_name(), dc_class.get_name()))

            fields[field.get_name()] = field_args

        for index in xrange(dc_class.get_num_inherited_fields()):
            field_packer = DCPacker()
            field = dc_class.get_inherited_field(index)

            if not field:
                continue

            if field.get_name() in fields:
                continue

            if not field.is_db() or not field.has_default_value():
                continue

            field_packer.set_unpack_data(field.get_default_value())
            field_packer.begin_unpack(field)
            field_args = field.unpack_args(field_packer)
            field_packer.end_unpack()

            if not field_args:
                self.notify.error(
                    'Failed to unpack field args for field: %d dclass: %s, invalid result!'
                    % (field.get_name(), dc_class.get_name()))

            fields[field.get_name()] = field_args

        file_object.set_value('fields', fields)

        self._backend.close_file(file_object)
        self._backend.tracker.set_value('next', do_id + 1)

        datagram = io.NetworkDatagram()
        datagram.add_header(sender, self.channel,
                            types.DBSERVER_CREATE_OBJECT_RESP)

        datagram.add_uint32(context)
        datagram.add_uint32(do_id)
        self.handle_send_connection_datagram(datagram)