Source code for wow_wtf_manager.exp.e03_wotlk_backup.wtf

# -*- coding: utf-8 -*-

"""
该模块主要实现了对 WTF 中的各种配置文件的抽象.

``BaseConfig`` 是所有配置文件对象的基类. 每一个具体的配置文件就是一个 ``BaseConfig`` 子类
的的实例. 这个实例是除了包含具体的配置文件引用自哪个文本文件, 同时也包含了 Wow dir,
Account, Server, Character 的信息. 有了这些信息, 程序就知道将这些配置应用拷贝到哪个客户端
文件的位置.
"""

import typing as T

import attr
from attrs_mate import AttrsClass
from pathlib_mate import Path

if T.TYPE_CHECKING:  # pragma: no cover
    from .group import Account, Character


# ------------------------------------------------------------------------------
# 为各种具体的配置进行数据建模
# ------------------------------------------------------------------------------
# --- Per GameClient Level
[docs]@attr.s class BaseConfig(AttrsClass): """ 各种具体配置的基类. 配置有很多种, 例如: - 游戏客户端启动配置 - 插件配置 - 快捷键配置 - 宏命令 - 插件的 SavedVariables """
[docs]@attr.s class BaseGameClientConfig(BaseConfig): """ 游戏客户端级的配置的基类 """ dir_wow: Path = attr.ib(default=None) @property def dir_wtf(self) -> Path: return self.dir_wow / "WTF"
[docs]@attr.s class GameClientConfig(BaseGameClientConfig): """ 客户端设定, 图像质量, 声音等. 对应 ``WTF/Config.wtf`` """ input_path: Path = attr.ib(default=None) _file = "Config.wtf" @property def output_path(self) -> Path: return self.dir_wtf / self._file
# --- Per Account Level
[docs]@attr.s class BaseAccountConfig(BaseGameClientConfig): account: str = attr.ib(default=None) @property def dir_account(self) -> Path: return self.dir_wtf / "Account" / uppercase(self.account)
[docs]@attr.s class AccountKeybindingConfig(BaseAccountConfig): """ 快捷键绑定设置. 对应: - 账户下所有角色: ``WTF/Account/${AccountName}/bindings-cache.wtf`` """ input_path: Path = attr.ib(default=None) _file = "bindings-cache.wtf" @property def output_path(self) -> Path: return self.dir_account / self._file
[docs]@attr.s class AccountMacroConfig(BaseAccountConfig): """ 账号下所有服务器所有角色的宏命令设置. 对应: ``WTF/Account/${AccountName}/macros-cache.txt`` """ input_path: Path = attr.ib(default=None) _file = "macros-cache.txt" @property def output_path(self) -> Path: return self.dir_account / self._file
[docs]@attr.s class AccountUserInterfaceConfig(BaseAccountConfig): """ 用户界面设置, 例如自动拾取, 显示血量百分比等. 对应: - 账户下所有角色: ``WTF/Account/${AccountName}/config-cache.txt`` """ input_path: Path = attr.ib(default=None) _file = "config-cache.wtf" @property def output_path(self) -> Path: return self.dir_account / self._file
[docs]@attr.s class AccountCacheConfig(BaseAccountConfig): """ 所有缓存文件的 MD5 指纹, 如果跟服务器端的不一样则重新读取. - 账户下所有角色: ``WTF/Account/${AccountName}/cache.md5`` """ input_path: Path = attr.ib(default=None) _file = "cache.md5" @property def output_path(self) -> Path: return self.dir_account / self._file
[docs]@attr.s class AccountSavedVariablesConfig(BaseAccountConfig): """ 全账号级别的插件配置: 对应: ``WTF/Account/${AccountName}/SavedVariables/`` """ input_path: Path = attr.ib(default=None) include_list: T.List[str] = attr.ib(factory=list) exclude_list: T.List[str] = attr.ib(factory=list) _file = "SavedVariables" @property def output_path(self) -> Path: return self.dir_account / self._file def evolve( self, include_list: T.Optional[T.List[str]] = None, exclude_list: T.Optional[T.List[str]] = None, ): config = attr.evolve(self) if include_list: config.include_list = include_list if exclude_list: config.exclude_list = exclude_list return config @property def lua_file_list(self) -> T.List[Path]: if self.include_list: include_list = list(self.include_list) else: include_list = [ p.fname for p in self.input_path.select_by_ext(".lua") ] for addon in self.exclude_list: try: include_list.remove(addon) except ValueError: pass return [ self.input_path / f"{addon}.lua" for addon in include_list ]
# --- Per Character Level
[docs]@attr.s class BaseCharacterConfig(BaseAccountConfig): server: str = attr.ib(default=None) character: str = attr.ib(default=None) @property def dir_char(self) -> Path: return self.dir_account / self.server / self.character
[docs]@attr.s class CharacterKeybindingConfig(BaseCharacterConfig): """ 单个角色的快捷键设置. 对应: ``WTF/Account/${AccountName}/${ServerName}/${CharName}/binding-cache.wtf`` """ input_path: Path = attr.ib(default=None) _file = "bindings-cache.wtf" @property def output_path(self) -> Path: return self.dir_char / self._file
[docs]@attr.s class CharacterAddonConfig(BaseCharacterConfig): """ 单个角色的插件设置. 对应: ``WTF/Account/${AccountName}/${ServerName}/${CharName}/AddOns.txt`` """ input_path: Path = attr.ib(default=None) _file = "AddOns.txt" @property def output_path(self) -> Path: return self.dir_char / self._file
[docs]@attr.s class CharacterMacroConfig(BaseCharacterConfig): """ 单个角色的宏命令设置. 对应: ``WTF/Account/${AccountName}/${ServerName}/${CharName}/macros-cache.txt`` """ input_path: Path = attr.ib(default=None) _file = "macros-cache.txt" @property def output_path(self) -> Path: return self.dir_char / self._file
[docs]@attr.s class CharacterUserInterfaceConfig(BaseCharacterConfig): """ 用户界面设置, 例如自动拾取, 显示血量百分比等. 对应: - 单个角色: ``WTF/Account/${AccountName}/${ServerName}/${CharName}/config-cache.txt`` """ input_path: Path = attr.ib(default=None) _file = "config-cache.wtf" @property def output_path(self) -> Path: return self.dir_char / self._file
[docs]@attr.s class CharacterLayoutConfig(BaseCharacterConfig): """ 用户界面窗口布局. 例如人物窗口, 背包窗口, 天赋窗口, 动作条的位置. 对应: - 单个角色: ``WTF/Account/${AccountName}/${ServerName}/${CharName}/layout-local.txt`` """ input_path: Path = attr.ib(default=None) _file = "layout-local.txt" @property def output_path(self) -> Path: return self.dir_char / self._file
[docs]@attr.s class CharacterChatConfig(BaseCharacterConfig): """ 聊天窗口的配置. 对应: - 单个角色: ``WTF/Account/${AccountName}/${ServerName}/${CharName}/chat-cache.txt`` """ input_path: Path = attr.ib(default=None) _file = "chat-cache.txt" @property def output_path(self) -> Path: return self.dir_char / self._file
[docs]@attr.s class CharacterSavedVariablesConfig(BaseCharacterConfig): """ 全账号级别的插件配置: 对应: ``WTF/Account/${AccountName}/${ServerName}/${CharName}/SavedVariables/`` """ input_path: Path = attr.ib(default=None) include_list: T.List[str] = attr.ib(factory=list) exclude_list: T.List[str] = attr.ib(factory=list) _file = "SavedVariables" @property def output_path(self) -> Path: return self.dir_char / self._file def evolve( self, include_list: T.Optional[T.List[str]] = None, exclude_list: T.Optional[T.List[str]] = None, ): config = attr.evolve(self) if include_list: config.include_list = include_list if exclude_list: config.exclude_list = exclude_list return config @property def lua_file_list(self) -> T.List[Path]: if self.include_list: include_list = list(self.include_list) else: include_list = [ p.fname for p in self.input_path.select_by_ext(".lua") ] for addon in self.exclude_list: try: include_list.remove(addon) except ValueError: pass return [ self.input_path / f"{addon}.lua" for addon in include_list ]
def uppercase(s: str) -> str: return s.upper() def titleize(s: str) -> str: return s[0].upper() + s[1:].lower()
[docs]def evolve_from_account( config: BaseAccountConfig, account: 'Account', ) -> BaseAccountConfig: """ 从 Account 对象中获得 账号 信息, 并对 Config 对象进行更新. """ config = attr.evolve(config) config.account = account.account return config
[docs]def evolve_from_character( config: BaseCharacterConfig, character: 'Character', ) -> BaseCharacterConfig: """ 从 Character 对象中获得 账号, 服务器, 角色名 等信息, 并对 Config 对象进行更新. **重要** 该函数不是修改已有的 ``BaseCharacterConfig`` 实例, 而是创建一个新的实例. """ config = attr.evolve(config) config.account = character.account config.server = character.server config.character = character.character return config