def create_exit(session, player, start_room, direction, dest_id, is_new, one_way, dest_title=None, **_): area, room = find_area_room(start_room, player) if room.find_exit(direction): raise DataError("Room already has " + direction + " exit.") rev_dir = Direction.ref_map[direction].rev_key other_id = dest_id if is_new: other_room = db.create_object('room', {'dbo_id': other_id, 'title': dest_title}, False) edit_update.publish_edit('create', other_room, session, True) update_next_room_id(area, session) else: other_area, other_room = find_area_room(other_id, player) if not one_way and other_room.find_exit(rev_dir): raise DataError("Room " + other_id + " already has a " + rev_dir + " exit.") this_exit = get_dbo_class('exit')() this_exit.dbo_owner = room this_exit.direction = direction this_exit.destination = other_room this_exit.on_loaded() room.exits.append(this_exit) db.save_object(room) edit_update.publish_edit('update', room, session) if not one_way: other_exit = get_dbo_class('exit')() other_exit.dbo_owner = room other_exit.direction = rev_dir other_exit.destination = room other_exit.on_loaded() other_room.exits.append(other_exit) db.save_object(other_room) other_room.reload() edit_update.publish_edit('update', other_room, session, True) return this_exit.dto_value
def update(update_cls, set_key=None): nonlocal updated for dbo in db.load_object_set(update_cls, set_key): db.save_object(dbo) updated += 1 for child_type in getattr(dbo_cls, 'dbo_children_types', ()): update(get_dbo_class(child_type), '{}_{}s:{}'.format(dbo_key_type, child_type, dbo.dbo_id))
def load_object_set(self, dbo_class, set_key=None): dbo_class = get_dbo_class(getattr(dbo_class, 'dbo_key_type', dbo_class)) key_type = dbo_class.dbo_key_type if not set_key: set_key = dbo_class.dbo_set_key results = set() keys = deque() pipeline = self.redis.pipeline() for key in self.fetch_set_keys(set_key): dbo_key = ':'.join([key_type, key]) try: results.add(self._object_map[dbo_key]) except KeyError: keys.append(key) pipeline.get(dbo_key) for dbo_id, json_str in zip(keys, pipeline.execute()): if json_str: obj = self._json_to_obj(json_str, key_type, dbo_id) if obj: results.add(obj) continue log.warn("Removing missing object from set {}", set_key) self.delete_set_key(set_key, dbo_id) return results
def initialize(self, key_type, imm_level='builder', create_level=None): self.key_type = key_type self.dbo_class = get_dbo_class(key_type) self.imm_level = imm_level self.create_level = create_level if create_level else imm_level if hasattr(self.dbo_class, 'dbo_children_types'): self.children_types = self.dbo_class.dbo_children_types
def __init__(self, key_type, imm_level='builder', create_level=None): super().__init__('editor/{}'.format(key_type), imm_level) self.key_type = key_type self.dbo_class = get_dbo_class(key_type) self.imm_level = imm_level self.create_level = create_level if create_level else imm_level if hasattr(self.dbo_class, 'dbo_children_types'): self.children_types = self.dbo_class.dbo_children_types
def update(update_cls, set_key=None): nonlocal updated for dbo in db.load_object_set(update_cls, set_key): db.save_object(dbo) updated += 1 for child_type in getattr(dbo_cls, 'dbo_children_types', ()): update( get_dbo_class(child_type), '{}_{}s:{}'.format(dbo_key_type, child_type, dbo.dbo_id))
def load_any(class_id, dbo_owner, dto_repr): if not dto_repr: return dbo_ref_id = None try: # The class_id passed in is what the field thinks it should hold # This can be overridden in the actual stored dictionary class_id = dto_repr['class_id'] except TypeError: # A dto_repr is either a string or a dictionary. If it's a string, # it must be reference, so capture the reference id dbo_ref_id = dto_repr except KeyError: pass dbo_class = get_dbo_class(class_id) if not dbo_class: log.error('Unable to load reference for {}', class_id) return None # If this class has a key_type, it should always be a reference and we should load it from the database # The dto_representation in this case should always be a dbo_id if hasattr(dbo_class, 'dbo_key_type'): return db.load_object(dbo_ref_id, dbo_class) # If we still have a dbo_ref_id, this must be part of an untyped collection, so the dbo_ref_id includes # both the class name and dbo_id and we should be able to load it if dbo_ref_id: return db.load_object(dbo_ref_id) # If this is a template, it should have a template key, so we load the template from the database using # the full key, then hydrate any non-template fields from the dictionary template_key = dto_repr.get('tk') if template_key: template = db.load_object(template_key) if template: instance = template.get_instance().hydrate(dto_repr) template.config_instance(instance, dbo_owner) return instance else: log.warn("Missing template for template_key {} owner {}", template_key, dbo_owner.dbo_id) return # Finally, it's not a template and it is not a reference to an independent DB object, it must be a pure child # object of this class, just set the owner and hydrate it instance = dbo_class() instance.dbo_owner = dbo_owner return instance.hydrate(dto_repr)
def _init(): global attributes global resource_pools global pool_keys global attr_list attributes = config_value('attributes') attr_list = [attr['dbo_id'] for attr in attributes] resource_pools = config_value('resource_pools') pool_keys = [(pool['dbo_id'], "base_{}".format(pool['dbo_id'])) for pool in resource_pools] player_cls = get_dbo_class('player') player_cls.add_dbo_fields({attr['dbo_id']: DBOField(0) for attr in attributes}) player_cls.add_dbo_fields({pool['dbo_id']: DBOField(0) for pool in resource_pools})
def rebuild_indexes(class_id): dbo_cls = get_dbo_class(class_id) if not dbo_cls: raise DataError("Class not found") for ix_name in dbo_cls.dbo_indexes: db.delete_key('ix:{}:{}'.format(dbo_cls.dbo_key_type, ix_name)) for dbo_id in db.fetch_set_keys(dbo_cls.dbo_set_key): try: dbo_key = '{}:{}'.format(dbo_cls.dbo_key_type, dbo_id) dbo_dict = db.load_value(dbo_key) for ix_name in dbo_cls.dbo_indexes: ix_value = dbo_dict.get(ix_name) if ix_value is not None and ix_value != '': db.set_index('ix:{}:{}'.format(dbo_cls.dbo_key_type, ix_name), ix_value, dbo_id) except (ValueError, TypeError): log.warn("Missing dbo object {} from set key {}", dbo_id, dbo_cls.dbo_set_key)
def delete_object(self, dbo): key = dbo.dbo_key dbo.db_deleted() self.delete_key(key) self._clear_old_refs(dbo) if dbo.dbo_set_key: self.redis.srem(dbo.dbo_set_key, dbo.dbo_id) for children_type in dbo.dbo_children_types: self.delete_object_set(get_dbo_class(children_type), "{}_{}s:{}".format(dbo.dbo_key_type, children_type, dbo.dbo_id)) for ix_name in dbo.dbo_indexes: ix_value = getattr(dbo, ix_name, None) if ix_value is not None and ix_value != '': self.delete_index('ix:{}:{}'.format(dbo.dbo_key_type, ix_name), ix_value) log.debug("object deleted: {}", key) self.evict_object(dbo)
def rebuild_indexes(class_id): dbo_cls = get_dbo_class(class_id) if not dbo_cls: raise DataError("Class not found") for ix_name in dbo_cls.dbo_indexes: db.delete_key('ix:{}:{}'.format(dbo_cls.dbo_key_type, ix_name)) for dbo_id in db.fetch_set_keys(dbo_cls.dbo_set_key): try: dbo_key = '{}:{}'.format(dbo_cls.dbo_key_type, dbo_id) dbo_dict = db.load_value(dbo_key) for ix_name in dbo_cls.dbo_indexes: ix_value = dbo_dict.get(ix_name) if ix_value is not None and ix_value != '': db.set_index( 'ix:{}:{}'.format(dbo_cls.dbo_key_type, ix_name), ix_value, dbo_id) except (ValueError, TypeError): log.warn("Missing dbo object {} from set key {}", dbo_id, dbo_cls.dbo_set_key)
def delete_object(self, dbo): key = dbo.dbo_key dbo.db_deleted() self.delete_key(key) self._clear_old_refs(dbo) if dbo.dbo_set_key: self.redis.srem(dbo.dbo_set_key, dbo.dbo_id) for children_type in dbo.dbo_children_types: self.delete_object_set( get_dbo_class(children_type), "{}_{}s:{}".format(dbo.dbo_key_type, children_type, dbo.dbo_id)) for ix_name in dbo.dbo_indexes: ix_value = getattr(dbo, ix_name, None) if ix_value is not None and ix_value != '': self.delete_index('ix:{}:{}'.format(dbo.dbo_key_type, ix_name), ix_value) log.debug("object deleted: {}", key) self.evict_object(dbo)
def main(self): constants = {key: config_value(key) for key in ['attributes', 'resource_pools', 'equip_types', 'equip_slots', 'weapon_types', 'damage_types', 'damage_delivery', 'damage_groups', 'affinities', 'imm_levels']} constants['weapon_options'] = constants['weapon_types'] + [{'dbo_id': 'unused'}, {'dbo_id': 'unarmed'}, {'dbo_id': 'any'}] constants['skill_calculation'] = constants['attributes'] + [{'dbo_id': 'roll', 'name': 'Dice Roll'}, {'dbo_id': 'skill', 'name': 'Skill Level'}] constants['defense_damage_types'] = constants['damage_types'] + constants['damage_groups'] constants['directions'] = Direction.ordered constants['article_load_types'] = ['equip', 'default'] constants['broadcast_types'] = broadcast_types constants['broadcast_tokens'] = broadcast_tokens constants['skill_types'] = [skill_template.dbo_key_type for skill_template in dbo_types(SkillTemplate)] constants['features'] = [get_dbo_class(feature_id)().edit_dto for feature_id in ['touchstone', 'entrance', 'store']] constants['action_args'] = action_keywords shadow_types = {} for class_id, cls in itertools.chain(implementors(Scriptable), instance_implementors(Scriptable)): shadows = [{'name': name, 'args': inspect.getargspec(member.func).args} for name, member in inspect.getmembers(cls) if isinstance(member, Shadow)] if shadows: shadow_types[class_id] = shadows constants['shadow_types'] = shadow_types constants['script_builders'] = list(builders.keys()) self._return(constants)
def purge(purge_cls, set_key=None): nonlocal purged, total for dbo_id in db.fetch_set_keys(set_key): total += 1 dbo_key = ':'.join((purge_cls.dbo_key_type, dbo_id)) dbo_dict = db.load_value(dbo_key) if dbo_dict is None: purged += 1 log.warn("Missing value for key {}", dbo_key) if execute: db.delete_set_key(set_key, dbo_id) else: dbo = get_mixed_type(purge_cls.dbo_key_type, dbo_dict.get('mixins'))() dbo.dbo_id = dbo_id if not dbo.hydrate(dbo_dict): purged += 1 if execute: db.delete_object(dbo) for child_type in getattr(dbo_cls, 'dbo_children_types', ()): purge(get_dbo_class(child_type), '{}_{}s:{}'.format(dbo_key_type, child_type, dbo_id))
def _mixin_init(cls, *_): template_id = getattr(cls, "template_id", None) if not template_id: return set_instance_class(template_id, cls) template_cls = get_dbo_class(template_id) old_class = getattr(template_cls, 'instance_cls', None) if old_class: log.info( "Overriding existing instance class {} with {} for template {}", old_class.__name__, cls.__name__, template_id) else: log.info("Initializing instance class {} for template {}", cls.__name__, template_id) new_dbo_fields = { name: DBOField(*field.args, **field.kwargs) for name, field in inspect.getmembers(cls) if isinstance(field, (DBOTField, DBOCField)) } template_cls.add_dbo_fields(new_dbo_fields) template_cls.instance_cls = cls cls.template_cls = template_cls
def create_object(self, dbo_class, dbo_dict, update_timestamp=True): dbo_class = get_dbo_class(getattr(dbo_class, 'dbo_key_type', dbo_class)) if not dbo_class: return try: dbo_id = dbo_dict['dbo_id'] except KeyError: dbo_id, dbo_dict = dbo_dict, {} if dbo_id is None or dbo_id == '': log.warn("create_object called with empty dbo_id") return dbo_id = str(dbo_id).lower() if self.object_exists(dbo_class.dbo_key_type, dbo_id): raise ObjectExistsError(dbo_id) dbo = dbo_class() dbo.dbo_id = dbo_id dbo.hydrate(dbo_dict) dbo.db_created() if dbo.dbo_set_key: self.redis.sadd(dbo.dbo_set_key, dbo.dbo_id) self.save_object(dbo, update_timestamp) return dbo
def dbo_child_keys(self, child_type): child_class = get_dbo_class(child_type) return sorted(db.fetch_set_keys("{}_{}s:{}".format(self.dbo_key_type, child_type, self.dbo_id)), key=child_class.dbo_key_sort)
def initialize(self, key_type): self.key_type = key_type self.dbo_class = get_dbo_class(key_type) self.parent_type = self.dbo_class.dbo_parent_type
def dbo_child_keys(self, child_type): child_class = get_dbo_class(child_type) return sorted(db.fetch_set_keys("{}_{}s:{}".format( self.dbo_key_type, child_type, self.dbo_id)), key=child_class.dbo_key_sort)