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]
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)
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
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)