PixelLauncher 2.1.0 — стабильная сборка
Офлайн-лаунчер Minecraft: аккаунты без Microsoft, установка версий и лоадеров (Fabric, Quilt, Forge, NeoForge), каталог модпаков Modrinth, поиск и обновление модов, разбор вылетов, системный трей, автозагрузка, плагины, прокси и зеркала.
This commit is contained in:
commit
ec6f13ddcc
33 files changed
+10445
No files matched your search
@@ -0,0 +1,175 @@
|
||||
"""Поиск и выбор Java."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
CREATE_NO_WINDOW = 0x08000000 if os.name == "nt" else 0
|
||||
|
||||
|
||||
def is64():
|
||||
return struct.calcsize("P") * 8 == 64
|
||||
|
||||
|
||||
def _exe(name="java"):
|
||||
return name + (".exe" if os.name == "nt" else "")
|
||||
|
||||
|
||||
def java_major(path):
|
||||
"""Версия Java в виде числа (8, 11, 17, 21...), 0 если не определилась."""
|
||||
try:
|
||||
p = subprocess.run(
|
||||
[path, "-version"],
|
||||
capture_output=True, text=True, timeout=20,
|
||||
creationflags=CREATE_NO_WINDOW,
|
||||
)
|
||||
text = (p.stderr or "") + (p.stdout or "")
|
||||
except Exception:
|
||||
return 0
|
||||
m = re.search(r'version\s+"(\d+)(?:\.(\d+))?(?:_(\d+))?', text)
|
||||
if not m:
|
||||
return 0
|
||||
major = int(m.group(1))
|
||||
if major == 1: # старый формат 1.8.0_382
|
||||
return int(m.group(2) or 0)
|
||||
return major
|
||||
|
||||
|
||||
def _add(cands, home):
|
||||
if not home:
|
||||
return
|
||||
exe = os.path.join(home, "bin", _exe())
|
||||
if os.path.isfile(exe) and exe not in cands:
|
||||
cands.append(exe)
|
||||
|
||||
|
||||
def find_javas():
|
||||
cands = []
|
||||
|
||||
# Переменные окружения
|
||||
_add(cands, os.environ.get("JAVA_HOME"))
|
||||
for k, v in os.environ.items():
|
||||
if k.upper().startswith("JAVA_HOME") and v:
|
||||
_add(cands, v)
|
||||
|
||||
# PATH
|
||||
w = shutil.which(_exe())
|
||||
if w:
|
||||
cands.append(w)
|
||||
|
||||
if os.name == "nt":
|
||||
pf = [
|
||||
r"C:\Program Files\Java",
|
||||
r"C:\Program Files (x86)\Java",
|
||||
r"C:\Program Files\Eclipse Adoptium",
|
||||
r"C:\Program Files\AdoptOpenJDK",
|
||||
r"C:\Program Files\Microsoft",
|
||||
r"C:\Program Files\Amazon Corretto",
|
||||
r"C:\Program Files\Zulu",
|
||||
r"C:\Program Files\BellSoft",
|
||||
r"C:\Program Files\GraalVM",
|
||||
r"C:\Program Files\JetBrains",
|
||||
]
|
||||
home_jdks = os.path.join(os.path.expanduser("~"), ".jdks")
|
||||
pf.append(home_jdks)
|
||||
for root in pf:
|
||||
if not os.path.isdir(root):
|
||||
continue
|
||||
try:
|
||||
for name in os.listdir(root):
|
||||
_add(cands, os.path.join(root, name))
|
||||
except OSError:
|
||||
pass
|
||||
elif sys.platform == "darwin":
|
||||
for root in ("/Library/Java/JavaVirtualMachines",
|
||||
os.path.expanduser("~/Library/Java/JavaVirtualMachines")):
|
||||
if not os.path.isdir(root):
|
||||
continue
|
||||
try:
|
||||
for name in os.listdir(root):
|
||||
_add(cands, os.path.join(root, name, "Contents", "Home"))
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
jvm_dir = "/usr/lib/jvm"
|
||||
if os.path.isdir(jvm_dir):
|
||||
try:
|
||||
for name in os.listdir(jvm_dir):
|
||||
_add(cands, os.path.join(jvm_dir, name))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
return cands
|
||||
|
||||
|
||||
def pick_java(required=8, preferred="", cache_path=""):
|
||||
"""Выбирает Java: (путь, major, подходит_ли).
|
||||
|
||||
Из подходящих (major >= required) берётся самая старая — максимальная
|
||||
совместимость со старыми версиями Minecraft.
|
||||
|
||||
cache_path — файл кэша с результатами определения версии. Пока файл
|
||||
java.exe не менялся, `java -version` повторно не запускается.
|
||||
"""
|
||||
if preferred and os.path.isfile(preferred):
|
||||
major = java_major(preferred)
|
||||
return preferred, major, (major == 0 or major >= required)
|
||||
|
||||
cache = {}
|
||||
if cache_path:
|
||||
try:
|
||||
with open(cache_path, encoding="utf-8") as f:
|
||||
cache = json.load(f)
|
||||
if not isinstance(cache, dict):
|
||||
cache = {}
|
||||
except Exception: # noqa: BLE001
|
||||
cache = {}
|
||||
|
||||
changed = False
|
||||
cands = find_javas()
|
||||
scored = []
|
||||
for exe in cands:
|
||||
try:
|
||||
mtime = int(os.path.getmtime(exe))
|
||||
except OSError:
|
||||
continue
|
||||
ent = cache.get(exe)
|
||||
if isinstance(ent, list) and len(ent) == 2 and ent[1] == mtime:
|
||||
major = int(ent[0]) # кэш валиден: файл не менялся
|
||||
else:
|
||||
major = java_major(exe)
|
||||
cache[exe] = [major, mtime]
|
||||
changed = True
|
||||
if major > 0:
|
||||
scored.append((exe, major))
|
||||
|
||||
# выбывшие установки — убрать из кэша
|
||||
alive = set(cands)
|
||||
for exe in [e for e in cache if e not in alive]:
|
||||
del cache[exe]
|
||||
changed = True
|
||||
|
||||
if cache_path and changed:
|
||||
try:
|
||||
os.makedirs(os.path.dirname(cache_path), exist_ok=True)
|
||||
with open(cache_path, "w", encoding="utf-8") as f:
|
||||
json.dump(cache, f)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if not scored:
|
||||
return "", 0, False
|
||||
|
||||
suitable = [s for s in scored if s[1] >= required]
|
||||
if suitable:
|
||||
suitable.sort(key=lambda s: s[1])
|
||||
exe, major = suitable[0]
|
||||
return exe, major, True
|
||||
# Ничего подходящего — берём самую новую и предупредим
|
||||
scored.sort(key=lambda s: s[1])
|
||||
exe, major = scored[-1]
|
||||
return exe, major, False
|
||||
Reference in new issue
Block a user