from ..files import ObjectReader from ..streams import EndianBinaryWriter from ..helpers import ImportHelper from .. import files from ..enums import FileType, ClassIDType import os from .. import environment def save_ptr(obj, writer: EndianBinaryWriter): if isinstance(obj, PPtr): writer.write_int(obj.file_id) else: writer.write_int(0) # it's usually 0...... if obj._version < 14: writer.write_int(obj.path_id) else: writer.write_long(obj.path_id) cached_managers = dict() class PPtr: def __init__(self, reader: ObjectReader): self._version = reader.version2 self.index = -2 self.file_id = reader.read_int() self.path_id = reader.read_int() if self._version < 14 else reader.read_long() self.assets_file = reader.assets_file self._obj = None def save(self, writer: EndianBinaryWriter): save_ptr(self, writer) def get_obj(self): if self._obj != None: return self._obj manager = None if self.file_id == 0: manager = self.assets_file elif self.file_id > 0 and self.file_id - 1 < len(self.assets_file.externals): if self.index == -2: external_name = self.assets_file.externals[self.file_id - 1].name parent = self.assets_file.parent if parent is not None: if external_name in parent.files: manager = parent.files[external_name] elif external_name.upper() in parent.files: manager = parent.files[external_name.upper()] else: while not isinstance(parent, environment.Environment): parent = parent.parent if parent.path: path = parent.path files = os.listdir(path) if external_name in files: parent.load_files([os.path.join(path, external_name)]) manager = parent.files[external_name] else: if external_name not in cached_managers: typ, reader = ImportHelper.check_file_type(external_name) if typ == FileType.AssetsFile: cached_managers[external_name] = files.SerializedFile(reader) if external_name in cached_managers: manager = cached_managers[external_name] if manager and self.path_id in manager.objects: self._obj = manager.objects[self.path_id] else: self._obj = None return self._obj def __getattr__(self, key): obj = self.get_obj() if obj is None: if key == "type": return ClassIDType.UnknownType raise AttributeError(key) return getattr(obj, key) def __repr__(self): return "<%s %s>" % (self.__class__.__name__, self._obj.__class__.__repr__(self.get_obj()) if self.get_obj() else "Not Found") def __bool__(self): return True if self.get_obj() else False