DevBlog №4 | массовый фикс JFX и фиксы связанные с самим лаунчером, добавление админ меню
This commit is contained in:
+63
-25
@@ -43,6 +43,7 @@ manifest_cache = TTLCache(maxsize=100, ttl=300)
|
||||
|
||||
BUILDS_DIR = Path("builds")
|
||||
VERSIONS_DIR = BUILDS_DIR / "versions"
|
||||
WHITELIST_DIR = Path(__file__).parent / "whitelist"
|
||||
|
||||
# Mirror configuration
|
||||
LAUNCHER_MIRRORS = {
|
||||
@@ -1256,36 +1257,42 @@ def generate_launcher_builds_meta():
|
||||
|
||||
meta_path = BUILDS_DIR / "meta.json"
|
||||
|
||||
# Check if meta exists and is fresh
|
||||
if meta_path.exists():
|
||||
try:
|
||||
with open(meta_path, 'r', encoding='utf-8') as f:
|
||||
existing = json.load(f)
|
||||
if existing.get("version") == version:
|
||||
logger.debug("Launcher meta.json already exists and is current")
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
# Always regenerate to pick up file changes (new JS, CSS, etc.)
|
||||
# The version check alone is insufficient — same version can have different files
|
||||
|
||||
|
||||
# Generate new meta
|
||||
files = []
|
||||
try:
|
||||
for file_path in BUILDS_DIR.rglob("*"):
|
||||
if file_path.is_file() and file_path.name not in ["meta.json"]:
|
||||
rel_path = str(file_path.relative_to(BUILDS_DIR))
|
||||
stat = file_path.stat()
|
||||
|
||||
# Calculate hash
|
||||
sha256_hash = hashlib.sha256()
|
||||
with open(file_path, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(8192), b""):
|
||||
sha256_hash.update(chunk)
|
||||
|
||||
files.append({
|
||||
"path": rel_path,
|
||||
"size": stat.st_size,
|
||||
"hash": f"sha256:{sha256_hash.hexdigest()}"
|
||||
})
|
||||
if not file_path.is_file():
|
||||
continue
|
||||
rel_path = str(file_path.relative_to(BUILDS_DIR))
|
||||
|
||||
# Only include runtime files needed for launcher updates
|
||||
# Skip: JRE, JavaFX, old ZIPs, extracted versions, docs, root JARs
|
||||
if rel_path.startswith(("jre21/", "lib/", "lib-javafx/", "versions/", "libs/")):
|
||||
continue
|
||||
if rel_path.endswith(".zip") or rel_path in ("README.txt", "build.version"):
|
||||
continue
|
||||
if file_path.name in ("meta.json",):
|
||||
continue
|
||||
# Skip root-level JARs — only bin/*.jar is needed at runtime
|
||||
if rel_path in ("zernmclauncher.jar", "zernmc-bootstrap.jar"):
|
||||
continue
|
||||
stat = file_path.stat()
|
||||
|
||||
# Calculate hash
|
||||
sha256_hash = hashlib.sha256()
|
||||
with open(file_path, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(8192), b""):
|
||||
sha256_hash.update(chunk)
|
||||
|
||||
files.append({
|
||||
"path": rel_path,
|
||||
"size": stat.st_size,
|
||||
"hash": f"sha256:{sha256_hash.hexdigest()}"
|
||||
})
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to generate launcher meta: {e}")
|
||||
return
|
||||
@@ -1905,6 +1912,37 @@ async def get_news(news_id: str):
|
||||
}
|
||||
|
||||
|
||||
# ====================== WHITELIST MODS ======================
|
||||
|
||||
WHITELIST_MODS_FILE = WHITELIST_DIR / "mods.txt"
|
||||
|
||||
|
||||
@app.get("/whitelist/mods")
|
||||
async def list_whitelist_mods(current_user: dict = Depends(get_current_user)):
|
||||
"""Return whitelist mods list as name :: size :: hash lines"""
|
||||
if not WHITELIST_MODS_FILE.exists():
|
||||
return Response(content="", media_type="text/plain")
|
||||
|
||||
content = WHITELIST_MODS_FILE.read_text(encoding="utf-8").strip()
|
||||
if not content:
|
||||
return Response(content="", media_type="text/plain")
|
||||
|
||||
return Response(content=content, media_type="text/plain")
|
||||
|
||||
|
||||
@app.get("/whitelist/mods/{mod_hash}/{filename:path}")
|
||||
async def download_whitelist_mod(mod_hash: str, filename: str, request: Request, current_user: dict = Depends(get_current_user)):
|
||||
"""Download whitelist mod file by hash"""
|
||||
if ".." in mod_hash or ".." in filename:
|
||||
raise HTTPException(400, "Invalid path")
|
||||
|
||||
mod_path = WHITELIST_DIR / mod_hash
|
||||
if not mod_path.exists() or not mod_path.is_file():
|
||||
raise HTTPException(404, "Mod not found")
|
||||
|
||||
return await send_file_async(mod_path, request, cache=True)
|
||||
|
||||
|
||||
# ====================== ПРОКСИ ЭНДПОИНТЫ ======================
|
||||
# Эти эндпоинты позволяют клиентам с сетевыми проблемами
|
||||
# скачивать файлы через сервер Zern
|
||||
|
||||
Reference in New Issue
Block a user