Files
PixelLauncher/launcher/config.py
T

158 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Пути и настройки лаунчера (settings.json рядом с main.py)."""
import json
import os
APP_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SETTINGS_PATH = os.path.join(APP_DIR, "settings.json")
DEFAULT_GAME_DIR = os.path.join(APP_DIR, ".minecraft")
DEFAULTS = {
"username": "Player",
"version": "latest-release",
"ram": 2048,
"auto_ram": False,
"java_path": "",
"jvm_args": "",
"jvm_preset": "",
"game_dir": DEFAULT_GAME_DIR,
# аккаунты (оффлайн-ники) и активный
"accounts": ["Player"],
"active_account": "Player",
# интерфейс
"lang": "ru",
"theme": "dark", # "dark" | "light"
"accent": "#6fae4a",
"ui_scale": 1.0,
"scene": "day",
# запуск игры
"win_w": 0, # 0 = значение игры по умолчанию
"win_h": 0,
"fullscreen": False,
"auto_backup": False, # резервная копия мира перед запуском
"autostart": False, # ярлык в автозагрузке Windows
"minimize_to_tray_on_launch": False, # прятать окно при запуске игры
# прокси: {"type": "http"|"socks5", "host", "port", "user", "pass"}
"proxy": {"enabled": False, "type": "http", "host": "", "port": 1080,
"user": "", "pass": ""},
# зеркала скачивания (пустые списки = официальные серверы Mojang)
"asset_mirrors": [],
"lib_mirrors": [],
# ключ CurseForge API (необязателен: есть зеркало без ключа)
"cf_api_key": "",
# третья волна
"fav_versions": [], # закреплённые версии (id)
"profiles": [], # профили запуска (см. ui._open_profiles)
"active_profile": "", # имя применённого профиля ("" — без профиля)
"world_backups": 5, # сколько последних копий мира хранить
# мастер первоначальной настройки (False — показать при первом запуске;
# апгрейд со старой версии считается настроенным, см. load_settings)
"onboarding_done": False,
}
def load_settings():
s = dict(DEFAULTS)
try:
with open(SETTINGS_PATH, encoding="utf-8") as f:
data = json.load(f)
except Exception:
data = None
if isinstance(data, dict):
s.update(data)
if "onboarding_done" not in data:
# апгрейд со старой версии: мастер первого запуска не показываем
s["onboarding_done"] = True
_migrate(s)
return s
def _migrate(s):
"""Приводит старые настройки к новой структуре."""
nick = (s.get("username") or "Player").strip() or "Player"
accounts = s.get("accounts")
if not isinstance(accounts, list) or not accounts:
accounts = [nick]
accounts = [str(a).strip() for a in accounts if str(a).strip()]
if nick not in accounts:
accounts.insert(0, nick)
s["accounts"] = accounts
active = s.get("active_account")
if not isinstance(active, str) or active not in accounts:
s["active_account"] = nick if nick in accounts else accounts[0]
s["username"] = s["active_account"]
for key in ("asset_mirrors", "lib_mirrors"):
v = s.get(key)
if not isinstance(v, list):
s[key] = []
if not isinstance(s.get("accent"), str) or not s["accent"].startswith("#"):
s["accent"] = DEFAULTS["accent"]
if not isinstance(s.get("cf_api_key"), str):
s["cf_api_key"] = ""
if s.get("theme") not in ("dark", "light"):
s["theme"] = "dark"
proxy = s.get("proxy")
if not isinstance(proxy, dict):
proxy = dict(DEFAULTS["proxy"])
for k, dv in DEFAULTS["proxy"].items():
if k not in proxy:
proxy[k] = dv
s["proxy"] = proxy
if s.get("scene") not in ("day", "night", "nether", "cave", "random"):
s["scene"] = "day"
if s.get("ui_scale") not in (1.0, 1.25, 1.5):
try:
sc = float(s.get("ui_scale"))
s["ui_scale"] = sc if sc in (1.0, 1.25, 1.5) else 1.0
except (TypeError, ValueError):
s["ui_scale"] = 1.0
for k in ("win_w", "win_h"):
try:
s[k] = max(0, int(s.get(k, 0)))
except (TypeError, ValueError):
s[k] = 0
s["fullscreen"] = bool(s.get("fullscreen"))
s["auto_backup"] = bool(s.get("auto_backup"))
s["autostart"] = bool(s.get("autostart"))
s["minimize_to_tray_on_launch"] = bool(
s.get("minimize_to_tray_on_launch"))
fav = s.get("fav_versions")
if isinstance(fav, list):
seen_f, out_f = set(), []
for v in fav[:200]:
v = str(v).strip()
if v and v not in seen_f:
seen_f.add(v)
out_f.append(v)
s["fav_versions"] = out_f
else:
s["fav_versions"] = []
profs, names = [], set()
if isinstance(s.get("profiles"), list):
for p in s["profiles"][:100]:
name = str((p or {}).get("name", "")).strip() if isinstance(
p, dict) else ""
if name and name not in names:
names.add(name)
profs.append(p)
s["profiles"] = profs
ap = s.get("active_profile")
s["active_profile"] = ap if isinstance(ap, str) and ap in names else ""
try:
s["world_backups"] = min(50, max(1, int(s.get("world_backups", 5))))
except (TypeError, ValueError):
s["world_backups"] = 5
def save_settings(s):
try:
with open(SETTINGS_PATH, "w", encoding="utf-8") as f:
json.dump(s, f, indent=2, ensure_ascii=False)
except Exception:
pass