Files
2025-05-22 19:02:56 +08:00

206 lines
8.1 KiB
Python

import os
import json
import shutil
import zipfile
from datetime import datetime
from typing import List, Dict, Optional
from config.settings import Config
from .utils import verify_folder, get_file_hash, download_file
class ResourcePackError(Exception):
"""TODO: 资源包相关错误处理"""
print(f"ResourcePackError: {str(Exception)}")
pass
class ResourcePackService:
def __init__(self):
self.export_dir = os.path.abspath("export")
print(f"Export directory: {self.export_dir}")
verify_folder(self.export_dir)
def create_resource_pack(self,
name: str,
version: str,
author: str,
description: str,
image_paths: List[str],
cover_image: Optional[str] = None,
tags: Optional[List[str]] = None) -> str:
if not name or not version or not author:
raise ResourcePackError("资源包名称、版本号和作者不能为空")
if not image_paths:
raise ResourcePackError("图片列表不能为空")
valid_images = []
for img_path in image_paths:
if not os.path.exists(img_path):
print(f"文件不存在: {img_path}")
continue
if not os.access(img_path, os.R_OK):
print(f"文件无法访问: {img_path}")
continue
valid_images.append(img_path)
if not valid_images:
raise ResourcePackError("没有有效的图片文件可以打包")
pack_dir = os.path.join(self.export_dir, f"{name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}")
print(f"Creating resource pack directory: {pack_dir}")
try:
verify_folder(pack_dir)
except Exception as e:
raise ResourcePackError(f"创建资源包目录失败: {str(e)}")
images_dir = os.path.join(pack_dir, "images")
try:
verify_folder(images_dir)
except Exception as e:
raise ResourcePackError(f"创建图片目录失败: {str(e)}")
# 处理封面图片
cover_info = None
if cover_image and os.path.exists(cover_image):
try:
cover_name = os.path.basename(cover_image)
name_without_ext, ext = os.path.splitext(cover_name)
ext = ext.lower()
file_hash = get_file_hash(cover_image)
if file_hash:
new_cover_name = f"cover{ext}"
new_cover_path = os.path.join(pack_dir, new_cover_name)
shutil.copy2(cover_image, new_cover_path)
print(f"复制封面: {cover_image} -> {new_cover_path}")
cover_info = {
"filename": new_cover_name,
"original_name": cover_name,
"hash": file_hash
}
except Exception as e:
print(str(e))
copied_files = []
file_mapping = {}
for img_path in valid_images:
try:
original_name = os.path.basename(img_path)
name_without_ext, ext = os.path.splitext(original_name)
ext = ext.lower()
file_hash = get_file_hash(img_path)
if not file_hash:
print(f"获取文件hash失败: {img_path}")
continue
# 处理文件名重复问题
new_name = original_name
new_path = os.path.join(images_dir, new_name)
if os.path.exists(new_path):
new_name = f"{name_without_ext}_{file_hash[:8]}{ext}"
new_path = os.path.join(images_dir, new_name)
shutil.copy2(img_path, new_path)
print(f"复制文件: {img_path} -> {new_path}")
copied_files.append(new_path)
file_mapping[new_name] = {
"filepath": os.path.join("images/", new_name),
"hash": file_hash
}
except Exception as e:
print(f"复制文件 {img_path} 失败: {str(e)}")
continue
if not copied_files:
raise ResourcePackError("没有成功复制任何图片文件")
manifest = {
"name": name,
"version": version,
"author": author,
"description": description,
"created_at": datetime.now().strftime("%Y-%m-%d"),
"tags": tags or [],
"cover": cover_info,
"contents": {
"images": {
"description": "图像资源目录",
"files": file_mapping
}
}
}
manifest_path = os.path.join(pack_dir, "manifest.json")
try:
with open(manifest_path, "w", encoding="utf-8") as f:
json.dump(manifest, f, ensure_ascii=False, indent=4)
print(f"Created manifest.json: {manifest_path}")
except Exception as e:
raise ResourcePackError(f"创建manifest.json失败: {str(e)}")
return pack_dir
def export_resource_pack(self, pack_dir: str) -> str:
if not os.path.exists(pack_dir):
raise ResourcePackError(f"资源包目录不存在: {pack_dir}")
if not os.path.isdir(pack_dir):
raise ResourcePackError(f"指定的路径不是目录: {pack_dir}")
if not os.path.exists(os.path.join(pack_dir, "manifest.json")):
raise ResourcePackError("资源包目录中缺少manifest.json")
images_dir = os.path.join(pack_dir, "images")
if not os.path.exists(images_dir) or not os.path.isdir(images_dir):
raise ResourcePackError("资源包目录中缺少images目录")
if not os.listdir(images_dir):
raise ResourcePackError("images目录为空")
zip_name = os.path.basename(pack_dir)
zip_path = os.path.join(os.path.dirname(pack_dir), f"{zip_name}.zip")
print(f"Creating zip file: {zip_path}")
try:
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
for root, _, files in os.walk(pack_dir):
for file in files:
# 使用绝对路径
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, pack_dir)
print(f"Adding to zip: {arcname}")
zf.write(file_path, arcname)
except Exception as e:
if os.path.exists(zip_path):
os.remove(zip_path)
raise ResourcePackError(f"创建zip文件失败: {str(e)}")
return zip_path
def import_resource_pack(self, zip_file):
target_dir = Config().paths.resource_packs_dir
verify_folder(target_dir)
target_dir = os.path.join(target_dir, os.path.splitext(os.path.basename(zip_file.name))[0])
try:
with zipfile.ZipFile(zip_file) as zip_ref:
zip_ref.extractall(target_dir)
print(f"成功解压 {zip_file.name} 到 {target_dir}")
except Exception as e:
raise ResourcePackError(f"解压ZIP文件失败: {str(e)}")
def import_resource_pack_from_url(self, url, uuid=None):
if uuid is None:
target_file = url.replace("https://", "").replace("http://", "").replace("/", "_").replace("\\", "_")
else:
target_file = f"{uuid}.json"
target_dir = os.path.join(Config().paths.resource_packs_dir, os.path.splitext(target_file)[0])
verify_folder(target_dir)
return download_file(url, os.path.join(target_dir, "manifest.json"))
RESOURCE_PACK_SERVICE = ResourcePackService()