#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Minecraft Launcher – 中文无乱码版 """ import os import sys # ① 控制台也强制 UTF-8 sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") import urllib.request from pathlib import Path from PyQt5.QtCore import QThread, pyqtSignal from PyQt5.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QComboBox, QPushButton, QMessageBox ) # ---------- 下载线程 ---------- class Downloader(QThread): log = pyqtSignal(str) # 给主线程回传日志 done = pyqtSignal(bool) # True=成功 def __init__(self, url: str, save_path: Path): super().__init__() self.url, self.save_path = url, save_path def run(self): try: self.save_path.parent.mkdir(parents=True, exist_ok=True) # ② 加 Header,防止被 gzip 后乱码 req = urllib.request.Request( self.url, headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/122.0.0.0 Safari/537.36", "Accept-Encoding": "identity", # 不要 gzip "Accept-Language": "zh-CN,zh;q=0.9", }, ) urllib.request.urlretrieve(req, str(self.save_path)) self.log.emit(f"下载完成:{self.save_path}") self.done.emit(True) except Exception as e: self.log.emit(f"下载失败:{e}") self.done.emit(False) # ---------- 主窗口 ---------- class MainWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle(self.tr("Hey,That Minecraft Launcher beta v0.0.1")) self.resize(400, 250) # ---- 控件 ---- self.input_ver = QLineEdit() self.input_ver.setPlaceholderText(self.tr("输入版本号,如 1.20.1")) mirror_label = QLabel(self.tr("镜像源")) self.mirror_combo = QComboBox() self.mirror_combo.addItems([self.tr("官方源"), self.tr("混淆哈希源")]) self.btn_download = QPushButton(self.tr("下载")) self.btn_natapp = QPushButton(self.tr("联机")) self.btn_about = QPushButton(self.tr("关于")) # ---- 布局 ---- left = QVBoxLayout() left.addWidget(QLabel(self.tr("版本号"))) left.addWidget(self.input_ver) left.addWidget(mirror_label) left.addWidget(self.mirror_combo) left.addWidget(self.btn_download) left.addWidget(self.btn_natapp) left.addWidget(self.btn_about) left.addStretch() main = QHBoxLayout(self) main.addLayout(left) # ---- 信号 ---- self.btn_download.clicked.connect(self.on_download) self.btn_natapp.clicked.connect(self.on_natapp) self.btn_about.clicked.connect(self.on_about) self.downloader = None # -------- 下载 -------- def on_download(self): ver = self.input_ver.text().strip() if not ver: QMessageBox.warning(self, self.tr("提示"), self.tr("请先输入版本号")) return if self.mirror_combo.currentText() == self.tr("官方源"): url_map = { "1.20.1": "https://launcher.mojang.com/v1/objects/" "84194a2f286ef7c14ed7ce09e259152674ddb5e4/client.jar", "1.16.5": "https://launcher.mojang.com/v1/objects/" "1b557e7d033a977cce3f73b1a9497423bbc76da9/client.jar", "1.21.9": "https://launcher.mojang.com/v1/objects/" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/client.jar" } if ver not in url_map: self.show_beta_msg() return url = url_map[ver] else: # 混淆哈希源 url = f"https://bmclapidoc.bangbang93.com/version/{ver}/client" save_dir = Path(".minecraft/versions") / ver save_path = save_dir / f"{ver}.jar" self.start_download(url, save_path) # -------- 联机 -------- def on_natapp(self): url = ("https://download.natapp.cn/assets/downloads/clients/" "2_4_2/natapp_windows_amd64_2_4_2.zip") save_path = Path("natapp/natapp_windows_amd64_2_4_2.zip") self.start_download(url, save_path) # -------- 关于 -------- def on_about(self): import webbrowser webbrowser.open("https://dinoai001.neocities.org") # -------- 通用下载 -------- def start_download(self, url: str, save_path: Path): if self.downloader and self.downloader.isRunning(): QMessageBox.information(self, self.tr("提示"), self.tr("已有任务在下载,请稍候")) return self.downloader = Downloader(url, save_path) self.downloader.log.connect(lambda t: print(t)) # 控制台打印 self.downloader.done.connect( lambda ok: QMessageBox.information( self, self.tr("结果"), self.tr("下载成功!") if ok else self.tr("下载失败,请查看控制台"))) self.downloader.start() # -------- Beta 提示 -------- def show_beta_msg(self): QMessageBox.information(self, self.tr("Beta"), self.tr("没有找到版本")) # ---------- 入口 ---------- if __name__ == "__main__": # ③ 让 Qt 始终用 UTF-8 解析字符串 os.environ["QT_LOGGING_RULES"] = "qt5ct.debug=false" app = QApplication(sys.argv) w = MainWindow() w.show() sys.exit(app.exec_())