mirror of
https://github.com/hyb-oyqq/FRAISEMOE-Addons-Installer-NEXT.git
synced 2025-12-20 22:08:36 +00:00
feat(core): 优化解压和哈希验证流程
- 在解压线程中添加已解压文件路径参数,支持直接使用已解压的补丁文件,提升解压效率。 - 更新下载管理器,简化下载成功后的处理逻辑,直接进入解压阶段,去除冗余的哈希验证步骤。 - 在离线模式管理器中增强哈希验证功能,确保在解压后进行哈希校验,提升补丁文件的完整性检查。 - 增强日志记录,确保在关键操作中提供详细的调试信息,便于后续排查和用户反馈。
This commit is contained in:
@@ -763,91 +763,21 @@ class DownloadManager:
|
||||
self.on_download_stopped()
|
||||
return
|
||||
|
||||
# 下载成功后,使用与离线模式相同的哈希校验机制
|
||||
# 下载成功后,直接进入解压阶段
|
||||
debug_mode = self.is_debug_mode()
|
||||
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 下载完成,开始验证补丁文件哈希: {_7z_path}")
|
||||
|
||||
# 关闭进度窗口
|
||||
if hasattr(self.main_window, 'progress_window') and self.main_window.progress_window:
|
||||
if self.main_window.progress_window.isVisible():
|
||||
self.main_window.progress_window.accept()
|
||||
self.main_window.progress_window = None
|
||||
|
||||
# 使用与离线模式相同的哈希校验机制
|
||||
from utils.helpers import ProgressHashVerifyDialog
|
||||
from data.config import PLUGIN_HASH
|
||||
from workers.hash_thread import OfflineHashVerifyThread
|
||||
|
||||
# 创建并显示进度对话框
|
||||
progress_dialog = ProgressHashVerifyDialog(
|
||||
f"验证补丁文件 - {APP_NAME}",
|
||||
f"正在验证 {game_version} 的补丁文件完整性...",
|
||||
self.main_window
|
||||
)
|
||||
|
||||
# 创建哈希验证线程
|
||||
hash_thread = OfflineHashVerifyThread(game_version, _7z_path, PLUGIN_HASH, self.main_window)
|
||||
|
||||
# 连接信号
|
||||
hash_thread.progress.connect(progress_dialog.update_progress)
|
||||
hash_thread.finished.connect(lambda result, error: self._on_hash_verify_finished(
|
||||
result, error, progress_dialog, _7z_path, game_folder, plugin_path, game_version
|
||||
))
|
||||
|
||||
# 启动线程
|
||||
hash_thread.start()
|
||||
|
||||
# 显示对话框,阻塞直到对话框关闭
|
||||
result = progress_dialog.exec()
|
||||
|
||||
# 如果用户取消了验证,停止线程
|
||||
if result == ProgressHashVerifyDialog.Rejected and hash_thread.isRunning():
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 用户取消了哈希验证")
|
||||
hash_thread.terminate()
|
||||
hash_thread.wait()
|
||||
# 取消后继续下一个任务
|
||||
self.next_download_task()
|
||||
logger.debug(f"DEBUG: 下载完成,直接进入解压阶段")
|
||||
|
||||
def _on_hash_verify_finished(self, result, error, dialog, _7z_path, game_folder, plugin_path, game_version):
|
||||
"""哈希验证线程完成后的回调
|
||||
|
||||
Args:
|
||||
result: 验证结果
|
||||
error: 错误信息
|
||||
dialog: 进度对话框
|
||||
_7z_path: 7z文件保存路径
|
||||
game_folder: 游戏文件夹路径
|
||||
plugin_path: 插件路径
|
||||
game_version: 游戏版本
|
||||
"""
|
||||
debug_mode = self.is_debug_mode()
|
||||
|
||||
# 存储结果到对话框,以便在exec()返回后获取
|
||||
dialog.hash_result = result
|
||||
|
||||
if result:
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 哈希验证成功")
|
||||
dialog.set_status("验证成功")
|
||||
# 短暂延时后关闭对话框
|
||||
QTimer.singleShot(500, dialog.accept)
|
||||
|
||||
# 验证成功,进入解压阶段
|
||||
# 直接进入解压阶段
|
||||
self.extraction_handler.start_extraction(_7z_path, game_folder, plugin_path, game_version)
|
||||
else:
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 哈希验证失败: {error}")
|
||||
dialog.set_status(f"验证失败: {error}")
|
||||
dialog.set_message("补丁文件验证失败,可能已损坏或被篡改。")
|
||||
# 将取消按钮改为关闭按钮
|
||||
dialog.cancel_button.setText("关闭")
|
||||
# 不自动关闭,让用户查看错误信息
|
||||
|
||||
# 在用户关闭对话框后,继续下一个任务
|
||||
dialog.rejected.connect(lambda: self.next_download_task())
|
||||
self.main_window.extraction_handler.extraction_finished.connect(self.on_extraction_finished)
|
||||
|
||||
def on_extraction_finished(self, continue_download):
|
||||
"""解压完成后的回调,决定是否继续下载队列
|
||||
@@ -896,3 +826,124 @@ class DownloadManager:
|
||||
def show_download_thread_settings(self):
|
||||
"""显示下载线程设置对话框"""
|
||||
return self.download_task_manager.show_download_thread_settings()
|
||||
|
||||
def direct_download_action(self, games_to_download):
|
||||
"""直接下载指定游戏的补丁,绕过补丁判断,用于从离线模式转接过来的任务
|
||||
|
||||
Args:
|
||||
games_to_download: 要下载的游戏列表
|
||||
"""
|
||||
debug_mode = self.is_debug_mode()
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 直接下载模式,绕过补丁判断,游戏列表: {games_to_download}")
|
||||
|
||||
if not self.selected_folder:
|
||||
QtWidgets.QMessageBox.warning(
|
||||
self.main_window, f"通知 - {APP_NAME}", "\n未选择任何目录,请重新选择\n"
|
||||
)
|
||||
return
|
||||
|
||||
# 识别游戏目录
|
||||
game_dirs = self.main_window.game_detector.identify_game_directories_improved(self.selected_folder)
|
||||
|
||||
if not game_dirs:
|
||||
QtWidgets.QMessageBox.warning(
|
||||
self.main_window, f"通知 - {APP_NAME}", "\n未在选择的目录中找到支持的游戏\n"
|
||||
)
|
||||
self.main_window.setEnabled(True)
|
||||
self.main_window.ui.start_install_text.setText("开始安装")
|
||||
return
|
||||
|
||||
# 过滤出存在的游戏目录
|
||||
selected_game_dirs = {game: game_dirs[game] for game in games_to_download if game in game_dirs}
|
||||
|
||||
if not selected_game_dirs:
|
||||
QtWidgets.QMessageBox.warning(
|
||||
self.main_window, f"通知 - {APP_NAME}", "\n未找到指定游戏的安装目录\n"
|
||||
)
|
||||
self.main_window.setEnabled(True)
|
||||
self.main_window.ui.start_install_text.setText("开始安装")
|
||||
return
|
||||
|
||||
self.main_window.setEnabled(False)
|
||||
|
||||
# 获取下载配置
|
||||
config = self.get_download_url()
|
||||
if not config:
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self.main_window, f"错误 - {APP_NAME}", "\n网络状态异常或服务器故障,请重试\n"
|
||||
)
|
||||
self.main_window.setEnabled(True)
|
||||
self.main_window.ui.start_install_text.setText("开始安装")
|
||||
return
|
||||
|
||||
# 填充下载队列
|
||||
self._fill_direct_download_queue(config, selected_game_dirs)
|
||||
|
||||
if not self.download_queue:
|
||||
# 所有下载任务都已完成,进行后检查
|
||||
if debug_mode:
|
||||
logger.debug("DEBUG: 所有下载任务完成,进行后检查")
|
||||
# 使用patch_detector进行安装后哈希比较
|
||||
self.main_window.patch_detector.after_hash_compare()
|
||||
return
|
||||
|
||||
# 显示Cloudflare优化选项
|
||||
self._show_cloudflare_option()
|
||||
|
||||
def _fill_direct_download_queue(self, config, game_dirs):
|
||||
"""直接填充下载队列,不检查补丁是否已安装
|
||||
|
||||
Args:
|
||||
config: 包含下载URL的配置字典
|
||||
game_dirs: 包含游戏文件夹路径的字典
|
||||
"""
|
||||
self.download_queue.clear()
|
||||
|
||||
if not hasattr(self.main_window, 'download_queue_history'):
|
||||
self.main_window.download_queue_history = []
|
||||
|
||||
debug_mode = self.is_debug_mode()
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 直接填充下载队列, 游戏目录: {game_dirs}")
|
||||
|
||||
# 记录要下载的游戏,用于历史记录
|
||||
games_to_download = list(game_dirs.keys())
|
||||
self.main_window.download_queue_history = games_to_download
|
||||
|
||||
for i in range(1, 5):
|
||||
game_version = f"NEKOPARA Vol.{i}"
|
||||
if game_version in game_dirs:
|
||||
# 从配置中获取下载URL
|
||||
url_key = f"vol.{i}.data"
|
||||
if url_key in config and "url" in config[url_key]:
|
||||
url = config[url_key]["url"]
|
||||
|
||||
game_folder = game_dirs[game_version]
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 添加下载任务 {game_version}: {game_folder}")
|
||||
|
||||
_7z_path = os.path.join(PLUGIN, f"vol.{i}.7z")
|
||||
plugin_path = os.path.join(PLUGIN, GAME_INFO[game_version]["plugin_path"])
|
||||
self.download_queue.append((url, game_folder, game_version, _7z_path, plugin_path))
|
||||
else:
|
||||
if debug_mode:
|
||||
logger.warning(f"DEBUG: 未找到 {game_version} 的下载URL")
|
||||
|
||||
game_version = "NEKOPARA After"
|
||||
if game_version in game_dirs:
|
||||
# 从配置中获取下载URL
|
||||
url_key = "after.data"
|
||||
if url_key in config and "url" in config[url_key]:
|
||||
url = config[url_key]["url"]
|
||||
|
||||
game_folder = game_dirs[game_version]
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 添加下载任务 {game_version}: {game_folder}")
|
||||
|
||||
_7z_path = os.path.join(PLUGIN, "after.7z")
|
||||
plugin_path = os.path.join(PLUGIN, GAME_INFO[game_version]["plugin_path"])
|
||||
self.download_queue.append((url, game_folder, game_version, _7z_path, plugin_path))
|
||||
else:
|
||||
if debug_mode:
|
||||
logger.warning(f"DEBUG: 未找到 {game_version} 的下载URL")
|
||||
@@ -1,7 +1,13 @@
|
||||
import os
|
||||
import shutil
|
||||
from PySide6 import QtWidgets
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
from PySide6.QtCore import QTimer
|
||||
|
||||
from utils.logger import setup_logger
|
||||
|
||||
# 初始化logger
|
||||
logger = setup_logger("extraction_handler")
|
||||
|
||||
class ExtractionHandler:
|
||||
"""解压处理器,负责管理解压任务和结果处理"""
|
||||
@@ -15,7 +21,7 @@ class ExtractionHandler:
|
||||
self.main_window = main_window
|
||||
self.APP_NAME = main_window.APP_NAME if hasattr(main_window, 'APP_NAME') else ""
|
||||
|
||||
def start_extraction(self, _7z_path, game_folder, plugin_path, game_version):
|
||||
def start_extraction(self, _7z_path, game_folder, plugin_path, game_version, extracted_path=None):
|
||||
"""开始解压任务
|
||||
|
||||
Args:
|
||||
@@ -23,6 +29,7 @@ class ExtractionHandler:
|
||||
game_folder: 游戏文件夹路径
|
||||
plugin_path: 插件路径
|
||||
game_version: 游戏版本名称
|
||||
extracted_path: 已解压的补丁文件路径,如果提供则直接使用它而不进行解压
|
||||
"""
|
||||
# 检查是否处于离线模式
|
||||
is_offline = False
|
||||
@@ -37,13 +44,13 @@ class ExtractionHandler:
|
||||
|
||||
# 创建并启动解压线程
|
||||
self.main_window.extraction_thread = self.main_window.create_extraction_thread(
|
||||
_7z_path, game_folder, plugin_path, game_version
|
||||
_7z_path, game_folder, plugin_path, game_version, extracted_path
|
||||
)
|
||||
self.main_window.extraction_thread.finished.connect(self.on_extraction_finished)
|
||||
self.main_window.extraction_thread.finished.connect(self.on_extraction_finished_with_hash_check)
|
||||
self.main_window.extraction_thread.start()
|
||||
|
||||
def on_extraction_finished(self, success, error_message, game_version):
|
||||
"""解压完成后的处理
|
||||
def on_extraction_finished_with_hash_check(self, success, error_message, game_version):
|
||||
"""解压完成后进行哈希校验
|
||||
|
||||
Args:
|
||||
success: 是否解压成功
|
||||
@@ -55,7 +62,7 @@ class ExtractionHandler:
|
||||
self.main_window.hash_msg_box.close()
|
||||
self.main_window.hash_msg_box = None
|
||||
|
||||
# 处理解压结果
|
||||
# 如果解压失败,显示错误并询问是否继续
|
||||
if not success:
|
||||
# 临时启用窗口以显示错误消息
|
||||
self.main_window.setEnabled(True)
|
||||
@@ -82,8 +89,137 @@ class ExtractionHandler:
|
||||
self.main_window.ui.start_install_text.setText("开始安装")
|
||||
# 通知DownloadManager停止下载队列
|
||||
self.main_window.download_manager.on_extraction_finished(False)
|
||||
return
|
||||
|
||||
# 解压成功,进行哈希校验
|
||||
self._perform_hash_check(game_version)
|
||||
|
||||
def _perform_hash_check(self, game_version):
|
||||
"""解压成功后进行哈希校验
|
||||
|
||||
Args:
|
||||
game_version: 游戏版本
|
||||
"""
|
||||
# 获取安装路径
|
||||
install_paths = {}
|
||||
if hasattr(self.main_window, 'game_detector') and hasattr(self.main_window, 'download_manager'):
|
||||
game_dirs = self.main_window.game_detector.identify_game_directories_improved(
|
||||
self.main_window.download_manager.selected_folder
|
||||
)
|
||||
|
||||
for game, info in self.main_window.GAME_INFO.items():
|
||||
if game in game_dirs and game == game_version:
|
||||
game_dir = game_dirs[game]
|
||||
install_path = os.path.join(game_dir, os.path.basename(info["install_path"]))
|
||||
install_paths[game] = install_path
|
||||
break
|
||||
|
||||
if not install_paths:
|
||||
# 如果找不到安装路径,直接认为安装成功
|
||||
logger.warning(f"未找到 {game_version} 的安装路径,跳过哈希校验")
|
||||
self.main_window.installed_status[game_version] = True
|
||||
self.main_window.download_manager.on_extraction_finished(True)
|
||||
return
|
||||
|
||||
# 显示哈希校验窗口
|
||||
self.main_window.hash_msg_box = self.main_window.hash_manager.hash_pop_window(check_type="post")
|
||||
|
||||
# 创建并启动哈希线程进行校验
|
||||
self.main_window.hash_thread = self.main_window.create_hash_thread(
|
||||
"after",
|
||||
install_paths,
|
||||
self.main_window.plugin_hash,
|
||||
self.main_window.installed_status
|
||||
)
|
||||
self.main_window.hash_thread.after_finished.connect(self.on_hash_check_finished)
|
||||
self.main_window.hash_thread.start()
|
||||
|
||||
def on_hash_check_finished(self, result):
|
||||
"""哈希校验完成后的处理
|
||||
|
||||
Args:
|
||||
result: 校验结果,包含通过状态、游戏版本和消息
|
||||
"""
|
||||
# 关闭哈希检查窗口
|
||||
if self.main_window.hash_msg_box and self.main_window.hash_msg_box.isVisible():
|
||||
self.main_window.hash_msg_box.close()
|
||||
self.main_window.hash_msg_box = None
|
||||
|
||||
if not result["passed"]:
|
||||
# 校验失败,删除已解压的文件并提示重新下载
|
||||
game_version = result["game"]
|
||||
error_message = result["message"]
|
||||
|
||||
# 临时启用窗口以显示错误消息
|
||||
self.main_window.setEnabled(True)
|
||||
|
||||
# 获取安装路径
|
||||
install_path = None
|
||||
if hasattr(self.main_window, 'game_detector') and hasattr(self.main_window, 'download_manager'):
|
||||
game_dirs = self.main_window.game_detector.identify_game_directories_improved(
|
||||
self.main_window.download_manager.selected_folder
|
||||
)
|
||||
|
||||
if game_version in game_dirs and game_version in self.main_window.GAME_INFO:
|
||||
game_dir = game_dirs[game_version]
|
||||
install_path = os.path.join(game_dir, os.path.basename(self.main_window.GAME_INFO[game_version]["install_path"]))
|
||||
|
||||
# 如果找到安装路径,尝试删除已解压的文件
|
||||
if install_path and os.path.exists(install_path):
|
||||
try:
|
||||
os.remove(install_path)
|
||||
logger.info(f"已删除校验失败的文件: {install_path}")
|
||||
except Exception as e:
|
||||
logger.error(f"删除文件失败: {e}")
|
||||
|
||||
# 显示错误消息并询问是否重试
|
||||
reply = QtWidgets.QMessageBox.question(
|
||||
self.main_window,
|
||||
f"校验失败 - {self.APP_NAME}",
|
||||
f"{error_message}\n\n是否重新下载并安装?",
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
QtWidgets.QMessageBox.StandardButton.Yes
|
||||
)
|
||||
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
# 重新下载,将游戏重新添加到下载队列
|
||||
self.main_window.setEnabled(False)
|
||||
self.main_window.installed_status[game_version] = False
|
||||
|
||||
# 获取游戏目录和下载URL
|
||||
if hasattr(self.main_window, 'download_manager') and hasattr(self.main_window, 'game_detector'):
|
||||
game_dirs = self.main_window.game_detector.identify_game_directories_improved(
|
||||
self.main_window.download_manager.selected_folder
|
||||
)
|
||||
|
||||
if game_version in game_dirs:
|
||||
# 重新将游戏添加到下载队列
|
||||
self.main_window.download_manager.download_queue.appendleft([game_version])
|
||||
# 继续下一个下载任务
|
||||
self.main_window.download_manager.next_download_task()
|
||||
else:
|
||||
# 更新安装状态
|
||||
# 如果找不到游戏目录,继续下一个
|
||||
self.main_window.download_manager.on_extraction_finished(True)
|
||||
else:
|
||||
# 如果无法重新下载,继续下一个
|
||||
self.main_window.download_manager.on_extraction_finished(True)
|
||||
else:
|
||||
# 用户选择不重试,继续下一个
|
||||
self.main_window.installed_status[game_version] = False
|
||||
self.main_window.download_manager.on_extraction_finished(True)
|
||||
else:
|
||||
# 校验通过,更新安装状态
|
||||
self.main_window.installed_status[game_version] = True
|
||||
# 通知DownloadManager继续下一个下载任务
|
||||
self.main_window.download_manager.on_extraction_finished(True)
|
||||
|
||||
def on_extraction_finished(self, success, error_message, game_version):
|
||||
"""兼容旧版本的回调函数
|
||||
|
||||
Args:
|
||||
success: 是否解压成功
|
||||
error_message: 错误信息
|
||||
game_version: 游戏版本
|
||||
"""
|
||||
# 调用新的带哈希校验的回调函数
|
||||
self.on_extraction_finished_with_hash_check(success, error_message, game_version)
|
||||
@@ -4,8 +4,9 @@ import shutil
|
||||
import tempfile
|
||||
import py7zr
|
||||
import traceback
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
from PySide6 import QtWidgets, QtCore
|
||||
from PySide6.QtCore import QTimer
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
|
||||
from data.config import PLUGIN, PLUGIN_HASH, GAME_INFO
|
||||
from utils import msgbox_frame
|
||||
@@ -254,7 +255,7 @@ class OfflineModeManager:
|
||||
|
||||
# 连接信号
|
||||
hash_thread.progress.connect(progress_dialog.update_progress)
|
||||
hash_thread.finished.connect(lambda result, error: self._on_hash_verify_finished(result, error, progress_dialog))
|
||||
hash_thread.finished.connect(lambda result, error, extracted_path: self._on_hash_verify_finished(result, error, extracted_path, progress_dialog))
|
||||
|
||||
# 启动线程
|
||||
hash_thread.start()
|
||||
@@ -273,12 +274,13 @@ class OfflineModeManager:
|
||||
# 返回对话框中存储的验证结果
|
||||
return hasattr(progress_dialog, 'hash_result') and progress_dialog.hash_result
|
||||
|
||||
def _on_hash_verify_finished(self, result, error, dialog):
|
||||
def _on_hash_verify_finished(self, result, error, extracted_path, dialog):
|
||||
"""哈希验证线程完成后的回调
|
||||
|
||||
Args:
|
||||
result: 验证结果
|
||||
error: 错误信息
|
||||
extracted_path: 解压后的补丁文件路径,如果哈希验证成功则包含此路径
|
||||
dialog: 进度对话框
|
||||
"""
|
||||
debug_mode = self._is_debug_mode()
|
||||
@@ -289,6 +291,8 @@ class OfflineModeManager:
|
||||
if result:
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 哈希验证成功")
|
||||
if extracted_path:
|
||||
logger.debug(f"DEBUG: 解压后的补丁文件路径: {extracted_path}")
|
||||
dialog.set_status("验证成功")
|
||||
# 短暂延时后关闭对话框
|
||||
QTimer.singleShot(500, dialog.accept)
|
||||
@@ -301,6 +305,173 @@ class OfflineModeManager:
|
||||
dialog.cancel_button.setText("关闭")
|
||||
# 不自动关闭,让用户查看错误信息
|
||||
|
||||
def _on_offline_install_hash_finished(self, result, error, extracted_path, dialog, game_version, _7z_path, game_folder, plugin_path, install_tasks):
|
||||
"""离线安装哈希验证线程完成后的回调
|
||||
|
||||
Args:
|
||||
result: 验证结果
|
||||
error: 错误信息
|
||||
extracted_path: 解压后的补丁文件路径
|
||||
dialog: 进度对话框
|
||||
game_version: 游戏版本
|
||||
_7z_path: 7z文件路径
|
||||
game_folder: 游戏文件夹路径
|
||||
plugin_path: 插件路径
|
||||
install_tasks: 剩余的安装任务列表
|
||||
"""
|
||||
debug_mode = self._is_debug_mode()
|
||||
|
||||
# 导入所需模块
|
||||
from data.config import GAME_INFO
|
||||
|
||||
# 存储结果到对话框,以便在exec()返回后获取
|
||||
dialog.hash_result = result
|
||||
|
||||
# 关闭哈希验证窗口
|
||||
if self.main_window.hash_msg_box and self.main_window.hash_msg_box.isVisible():
|
||||
self.main_window.hash_msg_box.close()
|
||||
self.main_window.hash_msg_box = None
|
||||
|
||||
if not result:
|
||||
# 哈希验证失败
|
||||
if debug_mode:
|
||||
logger.warning(f"DEBUG: 补丁文件哈希验证失败: {error}")
|
||||
|
||||
# 显示错误消息
|
||||
msgbox_frame(
|
||||
f"哈希验证失败 - {self.app_name}",
|
||||
f"\n{game_version} 的补丁文件哈希验证失败,可能已损坏或被篡改。\n\n跳过此游戏的安装。\n",
|
||||
QMessageBox.StandardButton.Ok
|
||||
).exec()
|
||||
|
||||
# 继续下一个任务
|
||||
self.process_next_offline_install_task(install_tasks)
|
||||
return
|
||||
|
||||
# 哈希验证成功,直接进行安装(复制文件)
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 哈希验证成功,直接进行安装")
|
||||
if extracted_path:
|
||||
logger.debug(f"DEBUG: 使用已解压的补丁文件: {extracted_path}")
|
||||
|
||||
# 显示安装进度窗口
|
||||
self.main_window.hash_msg_box = self.main_window.hash_manager.hash_pop_window(check_type="offline_installation", is_offline=True)
|
||||
|
||||
try:
|
||||
# 直接复制已解压的文件到游戏目录
|
||||
os.makedirs(game_folder, exist_ok=True)
|
||||
|
||||
# 获取目标文件路径
|
||||
target_file = None
|
||||
if "Vol.1" in game_version:
|
||||
target_file = os.path.join(game_folder, "adultsonly.xp3")
|
||||
elif "Vol.2" in game_version:
|
||||
target_file = os.path.join(game_folder, "adultsonly.xp3")
|
||||
elif "Vol.3" in game_version:
|
||||
target_file = os.path.join(game_folder, "update00.int")
|
||||
elif "Vol.4" in game_version:
|
||||
target_file = os.path.join(game_folder, "vol4adult.xp3")
|
||||
elif "After" in game_version:
|
||||
target_file = os.path.join(game_folder, "afteradult.xp3")
|
||||
|
||||
if not target_file:
|
||||
raise ValueError(f"未知的游戏版本: {game_version}")
|
||||
|
||||
# 复制文件
|
||||
shutil.copy2(extracted_path, target_file)
|
||||
|
||||
# 对于NEKOPARA After,还需要复制签名文件
|
||||
if game_version == "NEKOPARA After":
|
||||
# 从已解压文件的目录中获取签名文件
|
||||
extracted_dir = os.path.dirname(extracted_path)
|
||||
sig_filename = os.path.basename(GAME_INFO[game_version]["sig_path"])
|
||||
sig_path = os.path.join(extracted_dir, sig_filename)
|
||||
|
||||
# 如果签名文件存在,则复制它
|
||||
if os.path.exists(sig_path):
|
||||
shutil.copy(sig_path, game_folder)
|
||||
else:
|
||||
# 如果签名文件不存在,则使用原始路径
|
||||
sig_path = os.path.join(PLUGIN, GAME_INFO[game_version]["sig_path"])
|
||||
shutil.copy(sig_path, game_folder)
|
||||
|
||||
# 更新安装状态
|
||||
self.main_window.installed_status[game_version] = True
|
||||
|
||||
# 添加到已安装游戏列表
|
||||
if game_version not in self.installed_games:
|
||||
self.installed_games.append(game_version)
|
||||
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 成功安装 {game_version} 补丁文件")
|
||||
|
||||
# 关闭安装进度窗口
|
||||
if self.main_window.hash_msg_box and self.main_window.hash_msg_box.isVisible():
|
||||
self.main_window.hash_msg_box.close()
|
||||
self.main_window.hash_msg_box = None
|
||||
|
||||
# 继续下一个任务
|
||||
self.process_next_offline_install_task(install_tasks)
|
||||
except Exception as e:
|
||||
if debug_mode:
|
||||
logger.error(f"DEBUG: 安装补丁文件失败: {e}")
|
||||
|
||||
# 关闭安装进度窗口
|
||||
if self.main_window.hash_msg_box and self.main_window.hash_msg_box.isVisible():
|
||||
self.main_window.hash_msg_box.close()
|
||||
self.main_window.hash_msg_box = None
|
||||
|
||||
# 显示错误消息
|
||||
msgbox_frame(
|
||||
f"安装错误 - {self.app_name}",
|
||||
f"\n{game_version} 的安装过程中发生错误: {str(e)}\n\n跳过此游戏的安装。\n",
|
||||
QMessageBox.StandardButton.Ok
|
||||
).exec()
|
||||
|
||||
# 继续下一个任务
|
||||
self.process_next_offline_install_task(install_tasks)
|
||||
|
||||
def _on_extraction_finished_with_hash_check(self, success, error_message, game_version, install_tasks):
|
||||
"""解压完成后进行哈希校验
|
||||
|
||||
Args:
|
||||
success: 是否解压成功
|
||||
error_message: 错误信息
|
||||
game_version: 游戏版本
|
||||
install_tasks: 剩余的安装任务列表
|
||||
"""
|
||||
# 这个方法已不再使用,保留为空以兼容旧版本调用
|
||||
pass
|
||||
|
||||
def on_extraction_thread_finished(self, success, error_message, game_version, install_tasks):
|
||||
"""解压线程完成后的处理(兼容旧版本)
|
||||
|
||||
Args:
|
||||
success: 是否解压成功
|
||||
error_message: 错误信息
|
||||
game_version: 游戏版本
|
||||
install_tasks: 剩余的安装任务列表
|
||||
"""
|
||||
# 这个方法已不再使用,但为了兼容性,我们直接处理下一个任务
|
||||
if success:
|
||||
# 更新安装状态
|
||||
self.main_window.installed_status[game_version] = True
|
||||
|
||||
# 添加到已安装游戏列表
|
||||
if game_version not in self.installed_games:
|
||||
self.installed_games.append(game_version)
|
||||
else:
|
||||
# 更新安装状态
|
||||
self.main_window.installed_status[game_version] = False
|
||||
|
||||
# 显示错误消息
|
||||
debug_mode = self._is_debug_mode()
|
||||
if debug_mode:
|
||||
logger.error(f"DEBUG: 解压失败: {error_message}")
|
||||
|
||||
# 继续下一个任务
|
||||
self.process_next_offline_install_task(install_tasks)
|
||||
|
||||
def install_offline_patches(self, selected_games):
|
||||
"""直接安装离线补丁,完全绕过下载模块
|
||||
|
||||
@@ -406,6 +577,43 @@ class OfflineModeManager:
|
||||
else:
|
||||
if debug_mode:
|
||||
logger.warning("DEBUG: 没有可安装的游戏,安装流程结束")
|
||||
|
||||
# 检查是否有未找到离线补丁文件的游戏
|
||||
if self.missing_offline_patches:
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 有未找到离线补丁文件的游戏: {self.missing_offline_patches}")
|
||||
|
||||
# 询问用户是否切换到在线模式
|
||||
msg_box = msgbox_frame(
|
||||
f"离线安装信息 - {self.app_name}",
|
||||
f"\n本地未发现对应离线文件,是否切换为在线模式安装?\n\n以下游戏未找到对应的离线补丁文件:\n\n{chr(10).join(self.missing_offline_patches)}\n",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
||||
)
|
||||
result = msg_box.exec()
|
||||
|
||||
if result == QMessageBox.StandardButton.Yes:
|
||||
if debug_mode:
|
||||
logger.debug("DEBUG: 用户选择切换到在线模式")
|
||||
|
||||
# 切换到在线模式
|
||||
if hasattr(self.main_window, 'ui_manager'):
|
||||
self.main_window.ui_manager.switch_work_mode("online")
|
||||
|
||||
# 直接启动下载流程
|
||||
self.main_window.setEnabled(True)
|
||||
# 保存当前选择的游戏列表,以便在线模式使用
|
||||
missing_games = self.missing_offline_patches.copy()
|
||||
# 启动下载流程
|
||||
QTimer.singleShot(500, lambda: self._start_online_download(missing_games))
|
||||
else:
|
||||
if debug_mode:
|
||||
logger.debug("DEBUG: 用户选择不切换到在线模式")
|
||||
|
||||
# 恢复UI状态
|
||||
self.main_window.setEnabled(True)
|
||||
self.main_window.ui.start_install_text.setText("开始安装")
|
||||
else:
|
||||
# 没有缺少离线补丁的游戏,显示一般消息
|
||||
msgbox_frame(
|
||||
f"离线安装信息 - {self.app_name}",
|
||||
"\n没有可安装的游戏或未找到对应的离线补丁文件。\n",
|
||||
@@ -416,6 +624,30 @@ class OfflineModeManager:
|
||||
|
||||
return True
|
||||
|
||||
def _start_online_download(self, games_to_download):
|
||||
"""启动在线下载流程
|
||||
|
||||
Args:
|
||||
games_to_download: 要下载的游戏列表
|
||||
"""
|
||||
debug_mode = self._is_debug_mode()
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 启动在线下载流程,游戏列表: {games_to_download}")
|
||||
|
||||
# 确保下载管理器已初始化
|
||||
if hasattr(self.main_window, 'download_manager'):
|
||||
# 使用直接下载方法,绕过补丁判断
|
||||
self.main_window.download_manager.direct_download_action(games_to_download)
|
||||
else:
|
||||
if debug_mode:
|
||||
logger.error("DEBUG: 下载管理器未初始化,无法启动下载流程")
|
||||
# 显示错误消息
|
||||
msgbox_frame(
|
||||
f"错误 - {self.app_name}",
|
||||
"\n下载管理器未初始化,无法启动下载流程。\n",
|
||||
QMessageBox.StandardButton.Ok
|
||||
).exec()
|
||||
|
||||
def process_next_offline_install_task(self, install_tasks):
|
||||
"""处理下一个离线安装任务
|
||||
|
||||
@@ -437,32 +669,14 @@ class OfflineModeManager:
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 有未找到离线补丁文件的游戏: {self.missing_offline_patches}")
|
||||
|
||||
# 在安装完成后询问用户是否切换到在线模式
|
||||
msg_box = msgbox_frame(
|
||||
f"离线安装完成 - {self.app_name}",
|
||||
f"\n以下游戏未找到对应的离线补丁文件:\n\n{chr(10).join(self.missing_offline_patches)}\n\n是否切换到在线模式继续安装?\n",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
||||
)
|
||||
result = msg_box.exec()
|
||||
|
||||
if result == QMessageBox.StandardButton.Yes:
|
||||
if debug_mode:
|
||||
logger.debug("DEBUG: 用户选择切换到在线模式")
|
||||
|
||||
# 切换到在线模式
|
||||
if hasattr(self.main_window, 'ui_manager'):
|
||||
self.main_window.ui_manager.switch_work_mode("online")
|
||||
|
||||
# 重置UI状态
|
||||
self.main_window.setEnabled(True)
|
||||
self.main_window.ui.start_install_text.setText("开始安装")
|
||||
# 先显示已安装的结果
|
||||
if self.installed_games:
|
||||
installed_msg = f"已成功安装以下补丁:\n\n{chr(10).join(self.installed_games)}\n\n"
|
||||
else:
|
||||
if debug_mode:
|
||||
logger.debug("DEBUG: 用户选择不切换到在线模式")
|
||||
installed_msg = ""
|
||||
|
||||
# 恢复UI状态
|
||||
self.main_window.setEnabled(True)
|
||||
self.main_window.ui.start_install_text.setText("开始安装")
|
||||
# 使用QTimer延迟显示询问对话框,确保安装结果窗口先显示并关闭
|
||||
QTimer.singleShot(500, lambda: self._show_missing_patches_dialog(installed_msg))
|
||||
else:
|
||||
# 恢复UI状态
|
||||
self.main_window.setEnabled(True)
|
||||
@@ -489,70 +703,53 @@ class OfflineModeManager:
|
||||
logger.debug(f"DEBUG: 已复制补丁文件到缓存目录: {_7z_path}")
|
||||
logger.debug(f"DEBUG: 开始验证补丁文件哈希值")
|
||||
|
||||
# 验证补丁文件哈希
|
||||
hash_valid = False
|
||||
extracted_path = None
|
||||
|
||||
# 显示哈希验证窗口 - 使用离线特定消息
|
||||
self.main_window.hash_msg_box = self.main_window.hash_manager.hash_pop_window(check_type="offline_verify", is_offline=True)
|
||||
|
||||
# 验证补丁文件哈希
|
||||
hash_valid = self.verify_patch_hash(game_version, _7z_path)
|
||||
# 使用特殊版本的verify_patch_hash方法,它会返回哈希验证结果和解压后的文件路径
|
||||
from utils.helpers import ProgressHashVerifyDialog
|
||||
from data.config import PLUGIN_HASH
|
||||
from workers.hash_thread import OfflineHashVerifyThread
|
||||
|
||||
# 关闭哈希验证窗口
|
||||
if self.main_window.hash_msg_box and self.main_window.hash_msg_box.isVisible():
|
||||
self.main_window.hash_msg_box.close()
|
||||
self.main_window.hash_msg_box = None
|
||||
|
||||
if hash_valid:
|
||||
if debug_mode:
|
||||
logger.info(f"DEBUG: 补丁文件哈希验证成功,开始解压")
|
||||
|
||||
# 显示解压窗口 - 使用离线特定消息
|
||||
self.main_window.hash_msg_box = self.main_window.hash_manager.hash_pop_window(check_type="offline_extraction", is_offline=True)
|
||||
|
||||
try:
|
||||
# 创建解压线程
|
||||
extraction_thread = self.main_window.create_extraction_thread(
|
||||
_7z_path, game_folder, plugin_path, game_version
|
||||
# 创建并显示进度对话框
|
||||
progress_dialog = ProgressHashVerifyDialog(
|
||||
f"验证补丁文件 - {self.app_name}",
|
||||
f"正在验证 {game_version} 的补丁文件完整性...",
|
||||
self.main_window
|
||||
)
|
||||
|
||||
# 正确连接信号
|
||||
extraction_thread.finished.connect(
|
||||
lambda success, error, game_ver: self.on_extraction_thread_finished(
|
||||
success, error, game_ver, install_tasks
|
||||
# 创建哈希验证线程
|
||||
hash_thread = OfflineHashVerifyThread(game_version, _7z_path, PLUGIN_HASH, self.main_window)
|
||||
|
||||
# 存储解压后的文件路径
|
||||
extracted_file_path = ""
|
||||
|
||||
# 连接信号
|
||||
hash_thread.progress.connect(progress_dialog.update_progress)
|
||||
hash_thread.finished.connect(
|
||||
lambda result, error, path: self._on_offline_install_hash_finished(
|
||||
result, error, path, progress_dialog, game_version, _7z_path, game_folder, plugin_path, install_tasks
|
||||
)
|
||||
)
|
||||
|
||||
# 启动解压线程
|
||||
extraction_thread.start()
|
||||
except Exception as e:
|
||||
if debug_mode:
|
||||
logger.error(f"DEBUG: 创建或启动解压线程失败: {e}")
|
||||
# 启动线程
|
||||
hash_thread.start()
|
||||
|
||||
# 关闭解压窗口
|
||||
if self.main_window.hash_msg_box and self.main_window.hash_msg_box.isVisible():
|
||||
self.main_window.hash_msg_box.close()
|
||||
self.main_window.hash_msg_box = None
|
||||
# 显示对话框,阻塞直到对话框关闭
|
||||
progress_dialog.exec()
|
||||
|
||||
# 显示错误消息
|
||||
msgbox_frame(
|
||||
f"解压错误 - {self.app_name}",
|
||||
f"\n{game_version} 的解压过程中发生错误: {str(e)}\n\n跳过此游戏的安装。\n",
|
||||
QMessageBox.StandardButton.Ok
|
||||
).exec()
|
||||
|
||||
# 继续下一个任务
|
||||
# 如果用户取消了验证,停止线程并继续下一个任务
|
||||
if hash_thread.isRunning():
|
||||
hash_thread.terminate()
|
||||
hash_thread.wait()
|
||||
self.process_next_offline_install_task(install_tasks)
|
||||
else:
|
||||
if debug_mode:
|
||||
logger.warning(f"DEBUG: 补丁文件哈希验证失败")
|
||||
return
|
||||
|
||||
# 显示错误消息
|
||||
msgbox_frame(
|
||||
f"哈希验证失败 - {self.app_name}",
|
||||
f"\n{game_version} 的补丁文件哈希验证失败,可能已损坏或被篡改。\n\n跳过此游戏的安装。\n",
|
||||
QMessageBox.StandardButton.Ok
|
||||
).exec()
|
||||
|
||||
# 继续下一个任务
|
||||
self.process_next_offline_install_task(install_tasks)
|
||||
except Exception as e:
|
||||
if debug_mode:
|
||||
logger.error(f"DEBUG: 离线安装任务处理失败: {e}")
|
||||
@@ -567,48 +764,6 @@ class OfflineModeManager:
|
||||
# 继续下一个任务
|
||||
self.process_next_offline_install_task(install_tasks)
|
||||
|
||||
def on_extraction_thread_finished(self, success, error_message, game_version, remaining_tasks):
|
||||
"""解压线程完成后的处理
|
||||
|
||||
Args:
|
||||
success: 是否解压成功
|
||||
error_message: 错误信息
|
||||
game_version: 游戏版本
|
||||
remaining_tasks: 剩余的安装任务列表
|
||||
"""
|
||||
debug_mode = self._is_debug_mode()
|
||||
|
||||
# 关闭解压窗口
|
||||
if self.main_window.hash_msg_box and self.main_window.hash_msg_box.isVisible():
|
||||
self.main_window.hash_msg_box.close()
|
||||
self.main_window.hash_msg_box = None
|
||||
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 离线解压完成,状态: {'成功' if success else '失败'}")
|
||||
if not success:
|
||||
logger.error(f"DEBUG: 错误信息: {error_message}")
|
||||
|
||||
if not success:
|
||||
# 显示错误消息
|
||||
msgbox_frame(
|
||||
f"解压失败 - {self.app_name}",
|
||||
f"\n{game_version} 的补丁解压失败。\n\n错误信息: {error_message}\n\n跳过此游戏的安装。\n",
|
||||
QMessageBox.StandardButton.Ok
|
||||
).exec()
|
||||
|
||||
# 更新安装状态
|
||||
self.main_window.installed_status[game_version] = False
|
||||
else:
|
||||
# 更新安装状态
|
||||
self.main_window.installed_status[game_version] = True
|
||||
|
||||
# 添加到已安装游戏列表
|
||||
if game_version not in self.installed_games:
|
||||
self.installed_games.append(game_version)
|
||||
|
||||
# 处理下一个任务
|
||||
self.process_next_offline_install_task(remaining_tasks)
|
||||
|
||||
def is_offline_mode_available(self):
|
||||
"""检查是否可以使用离线模式
|
||||
|
||||
@@ -629,3 +784,41 @@ class OfflineModeManager:
|
||||
bool: 是否处于离线模式
|
||||
"""
|
||||
return self.is_offline_mode
|
||||
|
||||
def _show_missing_patches_dialog(self, installed_msg):
|
||||
"""显示缺少离线补丁文件的对话框
|
||||
|
||||
Args:
|
||||
installed_msg: 已安装的补丁信息
|
||||
"""
|
||||
debug_mode = self._is_debug_mode()
|
||||
|
||||
# 在安装完成后询问用户是否切换到在线模式
|
||||
msg_box = msgbox_frame(
|
||||
f"离线安装完成 - {self.app_name}",
|
||||
f"\n{installed_msg}以下游戏未找到对应的离线补丁文件:\n\n{chr(10).join(self.missing_offline_patches)}\n\n是否切换到在线模式继续安装?\n",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
||||
)
|
||||
result = msg_box.exec()
|
||||
|
||||
if result == QMessageBox.StandardButton.Yes:
|
||||
if debug_mode:
|
||||
logger.debug("DEBUG: 用户选择切换到在线模式")
|
||||
|
||||
# 切换到在线模式
|
||||
if hasattr(self.main_window, 'ui_manager'):
|
||||
self.main_window.ui_manager.switch_work_mode("online")
|
||||
|
||||
# 直接启动下载流程
|
||||
self.main_window.setEnabled(True)
|
||||
# 保存当前选择的游戏列表,以便在线模式使用
|
||||
missing_games = self.missing_offline_patches.copy()
|
||||
# 启动下载流程
|
||||
QTimer.singleShot(500, lambda: self._start_online_download(missing_games))
|
||||
else:
|
||||
if debug_mode:
|
||||
logger.debug("DEBUG: 用户选择不切换到在线模式")
|
||||
|
||||
# 恢复UI状态
|
||||
self.main_window.setEnabled(True)
|
||||
self.main_window.ui.start_install_text.setText("开始安装")
|
||||
@@ -367,7 +367,7 @@ class MainWindow(QMainWindow):
|
||||
|
||||
return progress_window
|
||||
|
||||
def create_extraction_thread(self, _7z_path, game_folder, plugin_path, game_version):
|
||||
def create_extraction_thread(self, _7z_path, game_folder, plugin_path, game_version, extracted_path=None):
|
||||
"""创建解压线程
|
||||
|
||||
Args:
|
||||
@@ -375,11 +375,12 @@ class MainWindow(QMainWindow):
|
||||
game_folder: 游戏文件夹路径
|
||||
plugin_path: 插件路径
|
||||
game_version: 游戏版本
|
||||
extracted_path: 已解压的补丁文件路径,如果提供则直接使用它而不进行解压
|
||||
|
||||
Returns:
|
||||
ExtractionThread: 解压线程实例
|
||||
"""
|
||||
return ExtractionThread(_7z_path, game_folder, plugin_path, game_version, self)
|
||||
return ExtractionThread(_7z_path, game_folder, plugin_path, game_version, self, extracted_path)
|
||||
|
||||
def show_result(self):
|
||||
"""显示安装结果,调用patch_manager的show_result方法"""
|
||||
|
||||
@@ -7,15 +7,38 @@ from data.config import PLUGIN, GAME_INFO
|
||||
class ExtractionThread(QThread):
|
||||
finished = Signal(bool, str, str) # success, error_message, game_version
|
||||
|
||||
def __init__(self, _7z_path, game_folder, plugin_path, game_version, parent=None):
|
||||
def __init__(self, _7z_path, game_folder, plugin_path, game_version, parent=None, extracted_path=None):
|
||||
super().__init__(parent)
|
||||
self._7z_path = _7z_path
|
||||
self.game_folder = game_folder
|
||||
self.plugin_path = plugin_path
|
||||
self.game_version = game_version
|
||||
self.extracted_path = extracted_path # 添加已解压文件路径参数
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
# 如果提供了已解压文件路径,直接使用它
|
||||
if self.extracted_path and os.path.exists(self.extracted_path):
|
||||
# 直接复制已解压的文件到游戏目录
|
||||
os.makedirs(self.game_folder, exist_ok=True)
|
||||
shutil.copy(self.extracted_path, self.game_folder)
|
||||
|
||||
# 对于NEKOPARA After,还需要复制签名文件
|
||||
if self.game_version == "NEKOPARA After":
|
||||
# 从已解压文件的目录中获取签名文件
|
||||
extracted_dir = os.path.dirname(self.extracted_path)
|
||||
sig_filename = os.path.basename(GAME_INFO[self.game_version]["sig_path"])
|
||||
sig_path = os.path.join(extracted_dir, sig_filename)
|
||||
|
||||
# 如果签名文件存在,则复制它
|
||||
if os.path.exists(sig_path):
|
||||
shutil.copy(sig_path, self.game_folder)
|
||||
else:
|
||||
# 如果签名文件不存在,则使用原始路径
|
||||
sig_path = os.path.join(PLUGIN, GAME_INFO[self.game_version]["sig_path"])
|
||||
shutil.copy(sig_path, self.game_folder)
|
||||
else:
|
||||
# 如果没有提供已解压文件路径,执行正常的解压流程
|
||||
with py7zr.SevenZipFile(self._7z_path, mode="r") as archive:
|
||||
archive.extractall(path=PLUGIN)
|
||||
|
||||
|
||||
@@ -132,22 +132,26 @@ class OfflineHashVerifyThread(QThread):
|
||||
"""离线模式下验证补丁文件哈希的线程,支持进度更新"""
|
||||
|
||||
progress = Signal(int) # 进度信号,0-100
|
||||
finished = Signal(bool, str) # 完成信号,(成功/失败, 错误信息)
|
||||
finished = Signal(bool, str, str) # 完成信号,(成功/失败, 错误信息, 解压后的补丁文件路径)
|
||||
|
||||
def __init__(self, game_version, file_path, plugin_hash, main_window=None):
|
||||
"""初始化离线哈希验证线程
|
||||
|
||||
Args:
|
||||
game_version: 游戏版本名称
|
||||
file_path: 补丁压缩包文件路径
|
||||
plugin_hash: 插件哈希值字典
|
||||
main_window: 主窗口实例,用于访问UI和状态
|
||||
"""
|
||||
super().__init__()
|
||||
self.game_version = game_version
|
||||
self.file_path = file_path
|
||||
self.plugin_hash = plugin_hash
|
||||
self.main_window = main_window
|
||||
self.extracted_patch_path = None # 添加解压后的补丁文件路径
|
||||
|
||||
# 获取预期的哈希值
|
||||
self.expected_hash = None
|
||||
|
||||
# 直接使用完整游戏名称作为键
|
||||
self.expected_hash = self.plugin_hash.get(game_version, "")
|
||||
|
||||
# 设置调试模式标志
|
||||
self.debug_mode = False
|
||||
if main_window and hasattr(main_window, 'debug_manager'):
|
||||
self.debug_mode = main_window.debug_manager._is_debug_mode()
|
||||
|
||||
def run(self):
|
||||
"""运行线程"""
|
||||
@@ -162,7 +166,7 @@ class OfflineHashVerifyThread(QThread):
|
||||
|
||||
if not expected_hash:
|
||||
logger.warning(f"DEBUG: 未找到 {self.game_version} 的预期哈希值")
|
||||
self.finished.emit(False, f"未找到 {self.game_version} 的预期哈希值")
|
||||
self.finished.emit(False, f"未找到 {self.game_version} 的预期哈希值", "")
|
||||
return
|
||||
|
||||
if debug_mode:
|
||||
@@ -175,7 +179,7 @@ class OfflineHashVerifyThread(QThread):
|
||||
if not os.path.exists(self.file_path):
|
||||
if debug_mode:
|
||||
logger.warning(f"DEBUG: 补丁文件不存在: {self.file_path}")
|
||||
self.finished.emit(False, f"补丁文件不存在: {self.file_path}")
|
||||
self.finished.emit(False, f"补丁文件不存在: {self.file_path}", "")
|
||||
return
|
||||
|
||||
# 检查文件大小
|
||||
@@ -186,7 +190,7 @@ class OfflineHashVerifyThread(QThread):
|
||||
if file_size == 0:
|
||||
if debug_mode:
|
||||
logger.warning(f"DEBUG: 补丁文件大小为0,无效文件")
|
||||
self.finished.emit(False, "补丁文件大小为0,无效文件")
|
||||
self.finished.emit(False, "补丁文件大小为0,无效文件", "")
|
||||
return
|
||||
|
||||
# 创建临时目录用于解压文件
|
||||
@@ -224,7 +228,7 @@ class OfflineHashVerifyThread(QThread):
|
||||
logger.error(f"DEBUG: 解压补丁文件失败: {e}")
|
||||
logger.error(f"DEBUG: 错误类型: {type(e).__name__}")
|
||||
logger.error(f"DEBUG: 错误堆栈: {traceback.format_exc()}")
|
||||
self.finished.emit(False, f"解压补丁文件失败: {str(e)}")
|
||||
self.finished.emit(False, f"解压补丁文件失败: {str(e)}", "")
|
||||
return
|
||||
|
||||
# 发送进度信号 - 50%
|
||||
@@ -261,7 +265,7 @@ class OfflineHashVerifyThread(QThread):
|
||||
logger.debug(f"DEBUG: 目录: {root}")
|
||||
logger.debug(f"DEBUG: 子目录: {dirs}")
|
||||
logger.debug(f"DEBUG: 文件: {files}")
|
||||
self.finished.emit(False, f"未找到解压后的补丁文件")
|
||||
self.finished.emit(False, f"未找到解压后的补丁文件", "")
|
||||
return
|
||||
|
||||
# 发送进度信号 - 70%
|
||||
@@ -299,15 +303,15 @@ class OfflineHashVerifyThread(QThread):
|
||||
logger.debug(f"DEBUG: 预期哈希值: {expected_hash}")
|
||||
logger.debug(f"DEBUG: 实际哈希值: {file_hash}")
|
||||
|
||||
self.finished.emit(result, "" if result else "补丁文件哈希验证失败,文件可能已损坏或被篡改")
|
||||
self.finished.emit(result, "" if result else "补丁文件哈希验证失败,文件可能已损坏或被篡改", patch_file)
|
||||
except Exception as e:
|
||||
if debug_mode:
|
||||
logger.error(f"DEBUG: 计算补丁文件哈希值失败: {e}")
|
||||
logger.error(f"DEBUG: 错误类型: {type(e).__name__}")
|
||||
self.finished.emit(False, f"计算补丁文件哈希值失败: {str(e)}")
|
||||
self.finished.emit(False, f"计算补丁文件哈希值失败: {str(e)}", "")
|
||||
except Exception as e:
|
||||
if debug_mode:
|
||||
logger.error(f"DEBUG: 验证补丁哈希值失败: {e}")
|
||||
logger.error(f"DEBUG: 错误类型: {type(e).__name__}")
|
||||
logger.error(f"DEBUG: 错误堆栈: {traceback.format_exc()}")
|
||||
self.finished.emit(False, f"验证补丁哈希值失败: {str(e)}")
|
||||
self.finished.emit(False, f"验证补丁哈希值失败: {str(e)}", "")
|
||||
Reference in New Issue
Block a user