2026-08-03 00:16:12 +08:00
|
|
|
# Nuitka build configuration. The output mode is selected on the command line
|
|
|
|
|
# so the same configuration can be used for both standalone and onefile builds.
|
|
|
|
|
# nuitka-project: --enable-plugin=pyside6
|
|
|
|
|
# nuitka-project: --include-data-dir={MAIN_DIRECTORY}/resources=resources
|
|
|
|
|
# nuitka-project: --output-dir={MAIN_DIRECTORY}/build
|
2026-08-03 21:48:00 +08:00
|
|
|
# nuitka-project: --output-filename=launcher
|
|
|
|
|
# nuitka-project: --product-name=TapLauncher
|
|
|
|
|
# nuitka-project: --file-description=A Minecraft Launcher
|
|
|
|
|
# nuitka-project: --copyright=Copyright (c) Wei's Garage
|
2026-08-03 00:16:12 +08:00
|
|
|
# nuitka-project: --assume-yes-for-downloads
|
|
|
|
|
# nuitka-project-if: {OS} == "Windows":
|
|
|
|
|
# nuitka-project: --windows-console-mode=disable
|
|
|
|
|
# nuitka-project: --windows-icon-from-ico={MAIN_DIRECTORY}/resources/icons/icon.png
|
2026-08-04 19:34:53 +08:00
|
|
|
# nuitka-project-if: {OS} == "Darwin":
|
|
|
|
|
# nuitka-project: --macos-create-app-bundle
|
|
|
|
|
# nuitka-project: --macos-app-icon={MAIN_DIRECTORY}/resources/icons/apple-app-icon.icon
|
|
|
|
|
# nuitka-project: --macos-app-name="TapLauncher"
|
2026-08-03 00:16:12 +08:00
|
|
|
|
2026-07-12 00:06:11 +08:00
|
|
|
import os
|
2026-07-10 20:57:31 +08:00
|
|
|
import sys
|
|
|
|
|
import argparse
|
|
|
|
|
import logging
|
2026-08-03 16:02:45 +08:00
|
|
|
|
|
|
|
|
from PySide6.QtWidgets import QApplication, QMainWindow
|
2026-08-03 18:04:40 +08:00
|
|
|
from platformdirs import (
|
|
|
|
|
user_data_dir,
|
|
|
|
|
)
|
2026-08-03 16:02:45 +08:00
|
|
|
|
2026-07-10 20:57:31 +08:00
|
|
|
from app import Launcher
|
2026-08-03 18:04:40 +08:00
|
|
|
from constant import LAUNCHER_DIR_NAME
|
2026-07-10 20:57:31 +08:00
|
|
|
|
2026-07-10 23:27:21 +08:00
|
|
|
from core_lib.log.default import DEFAULT_FORMAT, DEFAULT_DATE_FORMAT, get_colorful_handler
|
2026-08-03 16:02:45 +08:00
|
|
|
from core_lib.qt import messagebox
|
2026-07-10 20:57:31 +08:00
|
|
|
|
2026-08-03 18:04:40 +08:00
|
|
|
def show_error(message):
|
|
|
|
|
app = QApplication(sys.argv)
|
|
|
|
|
app.setApplicationName("Launcher Bootstrapper")
|
|
|
|
|
window = QMainWindow()
|
|
|
|
|
messagebox.error(window, "Error", message)
|
|
|
|
|
app.exit()
|
|
|
|
|
|
2026-07-10 20:57:31 +08:00
|
|
|
def main():
|
2026-07-10 23:27:21 +08:00
|
|
|
root_logger = logging.getLogger()
|
2026-07-10 20:57:31 +08:00
|
|
|
logger = logging.getLogger("Launcher.Main")
|
|
|
|
|
|
2026-07-10 23:27:21 +08:00
|
|
|
# parse arguments
|
2026-07-10 20:57:31 +08:00
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
|
parser.add_argument("-m", "--mode", choices=['lightweight', 'full', 'choice'], default='choice',
|
2026-08-03 00:40:16 +08:00
|
|
|
help="Select a mode (lightweight for TUI, full for GUI, or choice to open a mode-selection window). "
|
2026-08-04 19:34:53 +08:00
|
|
|
"TUI is not implemented yet.", required=False)
|
2026-07-10 23:27:21 +08:00
|
|
|
parser.add_argument("-d", "--debug", action="store_true",
|
|
|
|
|
help="Enable debug mode", default=False)
|
2026-08-03 18:04:40 +08:00
|
|
|
parser.add_argument("-wd", "--work-dir", default=None, help="Work directory")
|
2026-07-10 20:57:31 +08:00
|
|
|
|
|
|
|
|
args, unknown = parser.parse_known_args()
|
|
|
|
|
for arg in unknown:
|
2026-07-10 23:27:21 +08:00
|
|
|
logger.warning("Unknown argument '%s'" % arg)
|
2026-07-10 20:57:31 +08:00
|
|
|
|
2026-07-10 23:27:21 +08:00
|
|
|
debug = args.debug
|
|
|
|
|
|
2026-08-03 18:04:40 +08:00
|
|
|
work_dir = args.work_dir
|
|
|
|
|
|
|
|
|
|
if work_dir is None:
|
|
|
|
|
if debug:
|
|
|
|
|
# Use working directory if launcher is in debug mode
|
|
|
|
|
work_dir = os.getcwd()
|
|
|
|
|
else:
|
|
|
|
|
try:
|
|
|
|
|
# Use user application data directory
|
2026-08-03 21:48:00 +08:00
|
|
|
work_dir = user_data_dir(LAUNCHER_DIR_NAME, appauthor=False, roaming=True)
|
2026-08-03 18:04:40 +08:00
|
|
|
os.makedirs(work_dir, exist_ok=True)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.warning("Failed to get application directory: %s", e)
|
|
|
|
|
show_error("Unable to get application directory. Try specifying 'work_dir' argument.")
|
|
|
|
|
sys.exit(-1)
|
|
|
|
|
else:
|
|
|
|
|
# check workdir
|
2026-08-03 20:55:37 +08:00
|
|
|
if not os.path.exists(work_dir) or not os.path.isdir(work_dir):
|
|
|
|
|
logger.error("Work directory '%s' does not exist." % work_dir)
|
|
|
|
|
show_error(f"Specified work directory \"{work_dir}\" does not exist or is not a directory.")
|
|
|
|
|
sys.exit(-1)
|
2026-07-12 00:06:11 +08:00
|
|
|
|
|
|
|
|
if os.getcwd() != args.work_dir:
|
2026-08-03 18:04:40 +08:00
|
|
|
os.chdir(work_dir)
|
2026-07-12 00:06:11 +08:00
|
|
|
|
2026-08-03 18:04:40 +08:00
|
|
|
logger.info("Current working directory is {}".format(work_dir))
|
2026-07-12 00:06:11 +08:00
|
|
|
|
2026-07-10 23:27:21 +08:00
|
|
|
# Init lib
|
|
|
|
|
level = logging.DEBUG if debug else logging.INFO
|
|
|
|
|
|
|
|
|
|
# Set root logger level and configure handler for colorful log (not sure why I added this)
|
|
|
|
|
root_logger.setLevel(level)
|
|
|
|
|
root_logger.addHandler(get_colorful_handler())
|
|
|
|
|
|
|
|
|
|
# Logger configure
|
|
|
|
|
logging.basicConfig(format=DEFAULT_FORMAT, datefmt=DEFAULT_DATE_FORMAT, level=level)
|
|
|
|
|
|
|
|
|
|
# Start (the real) launcher
|
2026-08-03 00:16:12 +08:00
|
|
|
app = Launcher(logger, debug=debug)
|
2026-07-14 01:13:36 +08:00
|
|
|
sys.exit(app.exec())
|
2026-07-10 20:57:31 +08:00
|
|
|
|
2026-07-12 00:06:11 +08:00
|
|
|
|
2026-07-10 20:57:31 +08:00
|
|
|
if __name__ == '__main__':
|
|
|
|
|
main()
|