feat: 新的资源包加载逻辑

feat: 主题商店支持
This commit is contained in:
2024-04-06 08:48:21 +08:00
parent be0b5e6de1
commit a76bc3de92
14 changed files with 153 additions and 31 deletions

View File

@ -1,4 +1,5 @@
import os
import shutil
import nonebot
import yaml
@ -6,8 +7,8 @@ from typing import Any
from liteyuki.utils.data import LiteModel
_resource_data = {}
_loaded_resource_packs = [] # 按照加载顺序排序
_loaded_resource_packs: list["ResourceMetadata"] = [] # 按照加载顺序排序
temp_resource_root = "data/liteyuki/resources"
class ResourceMetadata(LiteModel):
@ -19,24 +20,21 @@ class ResourceMetadata(LiteModel):
def load_resource_from_dir(path: str):
"""
把资源包按照文件相对路径加载到资源包中,后加载的优先级更高,顺便加载语言
把资源包按照文件相对路径复制到运行临时文件夹data/liteyuki/resources
Args:
path: 资源文件夹
Returns:
"""
for root, dirs, files in os.walk(path):
for file in files:
relative_path = os.path.relpath(os.path.join(root, file), path).replace("\\", "/")
abs_path = os.path.join(root, file).replace("\\", "/")
_resource_data[relative_path] = abs_path
if os.path.exists(os.path.join(path, "metadata.yml")):
with open(os.path.join(path, "metadata.yml"), "r", encoding="utf-8") as f:
metadata = yaml.safe_load(f)
else:
# 没有metadata.yml文件不是一个资源包
return
for root, dirs, files in os.walk(path):
for file in files:
relative_path = os.path.relpath(os.path.join(root, file), path)
copy_file(os.path.join(root, file), os.path.join(temp_resource_root, relative_path))
metadata["path"] = path
if os.path.exists(os.path.join(path, "lang")):
from liteyuki.utils.language import load_from_dir
@ -53,7 +51,11 @@ def get_path(path: str, abs_path: bool = False, default: Any = None) -> str | An
path: 文件相对路径
Returns: 文件绝对路径
"""
return _resource_data.get(path, default) if not abs_path else os.path.abspath(_resource_data.get(path, default))
resource_relative_path = os.path.join(temp_resource_root, path)
if os.path.exists(resource_relative_path):
return os.path.abspath(resource_relative_path) if abs_path else resource_relative_path
else:
return default
def get_files(path: str, abs_path: bool = False) -> list[str]:
@ -64,5 +66,46 @@ def get_files(path: str, abs_path: bool = False) -> list[str]:
path: 文件夹相对路径
Returns: 文件绝对路径
"""
return [os.path.abspath(file) for file in _resource_data if file.startswith(path)] if abs_path else [
file for file in _resource_data if file.startswith(path)]
resource_relative_path = os.path.join(temp_resource_root, path)
if os.path.exists(resource_relative_path):
return [os.path.abspath(os.path.join(resource_relative_path, file)) if abs_path else os.path.join(resource_relative_path, file) for file in
os.listdir(resource_relative_path)]
else:
return []
def get_loaded_resource_packs() -> list[ResourceMetadata]:
"""
获取已加载的资源包
Returns: 资源包列表
"""
return _loaded_resource_packs
def copy_file(src, dst):
# 获取目标文件的目录
dst_dir = os.path.dirname(dst)
# 如果目标目录不存在,创建它
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
# 复制文件
shutil.copy(src, dst)
def load_resources():
"""用于外部主程序调用的资源加载函数
Returns:
"""
# 加载默认资源和语言
# 清空临时资源包路径data/liteyuki/resources
_loaded_resource_packs.clear()
if os.path.exists(temp_resource_root):
shutil.rmtree(temp_resource_root)
os.makedirs(temp_resource_root, exist_ok=True)
standard_resource_path = "liteyuki/resources"
load_resource_from_dir(standard_resource_path)
# 加载其他资源包
if os.path.exists("resources"):
for resource in os.listdir("resources"):
load_resource_from_dir(os.path.join("resources", resource))