"""Tomie-specific parts of the Unity reader: ResourceManager actors and original variables.""" import json from app.converter.compatibility import Issue from app.games.hooks import ReaderHooks from app.games.tomie.profile import PROFILE, extract_tables class TomieHooks(ReaderHooks): def begin(self, package, root): package.profile = PROFILE package.function_data = extract_tables(root) def accept_duplicate_script(self, name): # This pinned build contains an editor/addressable Init alongside the main # corpus. The recovered port uses the main ResourceManager copy; it is read first. return name == "Init" def scan_object(self, package, obj, ctx): kind = obj.type.name if kind == "ResourceManager" and ctx.media: self._actors(package, obj, ctx) return True if kind == "MonoBehaviour" and obj.peek_name() == "CustomVariablesConfiguration": self._defaults(package, obj, ctx) return True return False @staticmethod def _actors(package, obj, ctx): from UnityPy.classes import PPtr actor_keys = set() for key, pointer in obj.read_typetree()["m_Container"]: if not key.lower().startswith("characters/"): continue name = key.lower().removeprefix("characters/") actor_keys.add(name) actor = PPtr(assetsfile=obj.assets_file, **pointer).deref() # Unity exposes both the complete texture and its Sprite under the same # Resources key. Naninovel's texture actor uses the complete texture, # as does the recovered Godot port. if actor.type.name == "Sprite": continue if actor.type.name != "Texture2D": package.issues.append(Issue("unsupported_actor", "Не поддерживается тип персонажа Tomie", key)) continue identity = f"{ctx.source.relative_to(ctx.root).as_posix()}:{actor.assets_file.name}:{actor.path_id}" previous = package.actor_resources.get(name) if previous and previous != identity: package.issues.append(Issue("conflicting_actor", "Различающиеся изображения персонажа Tomie", key)) package.actor_resources[name] = identity package.resources.append((ctx.source, actor)) for name in actor_keys - package.actor_resources.keys(): package.issues.append(Issue("missing_actor_texture", "Не найдена полная текстура персонажа Tomie", name)) @staticmethod def _defaults(package, obj, ctx): codec = ctx.codec(str(obj.assets_file.unity_version)) node = obj.serialized_type.node or codec.node("Elringus.Naninovel.Runtime", "Naninovel.CustomVariablesConfiguration") config = obj.read_typetree(nodes=node) defaults = {entry["name"]: json.loads(entry["value"]) for entry in config["PredefinedVariables"]} if package.defaults and package.defaults != defaults: package.issues.append(Issue("conflicting_defaults", "Различающиеся исходные переменные Naninovel")) else: package.defaults = defaults