feat: add NeoForge support, fix Forge installPack bug, update server proxy

- Fix MinecraftLib.installPack() returning false for Forge (was dead code)
- Add NeoForgeInstaller.java with installer download and execution
- Update LaunchCommandBuilder with NeoForge JVM args, classpath, launch args
- Update LaunchMenu with NeoForge option, version selector, support check
- Update Instance.java loader type comment (vanilla, fabric, forge, neoforge)
- Update PackDownloader to handle neoforge loader type
- Update ZHttpClient with NEOFORGE_MAVEN service type and detection
- Add NeoForge proxy endpoints (/proxy/neoforge/versions, /proxy/neoforge/maven)
- Add maven.neoforged.net to proxy allowed_domains
- Add asset_index to PackMeta model and pack_manager scanning
- Include asset_index in /packs list endpoint response
This commit is contained in:
SashegDev
2026-05-04 22:53:22 +00:00
parent cd2cf44d9c
commit b4431702dc
10 changed files with 641 additions and 18 deletions
+58 -3
View File
@@ -520,7 +520,8 @@ async def list_packs(current_user: dict = Depends(get_current_user)):
"updated_at": updated_at,
"minecraft_version": meta.get("minecraft_version", "unknown"),
"loader_type": meta.get("loader_type", "vanilla"),
"loader_version": meta.get("loader_version")
"loader_version": meta.get("loader_version"),
"asset_index": meta.get("asset_index")
})
except Exception as e:
logger.error(f"Failed to load pack meta for {pack_dir.name}: {e}")
@@ -1079,6 +1080,58 @@ async def proxy_forge_maven(path: str, request: Request):
raise HTTPException(502, f"Bad Gateway: {str(e)}")
@app.get("/proxy/neoforge/versions")
async def proxy_neoforge_versions(request: Request):
"""Прокси для списка версий NeoForge"""
client_ip = request.client.host if request.client else "unknown"
logger.info(f"Proxy request: NeoForge versions from {client_ip}")
url = "https://maven.neoforged.net/releases/net/neoforged/neoforge/maven-metadata.xml"
try:
response = await proxy_client.get(url)
response.raise_for_status()
return Response(
content=response.content,
media_type="application/xml",
headers={"X-Proxied-By": "ZernMC"}
)
except httpx.HTTPError as e:
logger.error(f"Proxy error for NeoForge versions: {e}")
raise HTTPException(502, f"Bad Gateway: {str(e)}")
@app.get("/proxy/neoforge/maven/{path:path}")
async def proxy_neoforge_maven(path: str, request: Request):
"""Прокси для NeoForge Maven файлов"""
client_ip = request.client.host if request.client else "unknown"
logger.info(f"Proxy request: NeoForge Maven {path} from {client_ip}")
full_url = f"https://maven.neoforged.net/{path}"
try:
response = await proxy_client.get(full_url)
response.raise_for_status()
content_type = "application/octet-stream"
if path.endswith(".jar"):
content_type = "application/java-archive"
elif path.endswith(".pom"):
content_type = "application/xml"
return Response(
content=response.content,
media_type=content_type,
headers={"X-Proxied-By": "ZernMC"}
)
except httpx.HTTPError as e:
logger.error(f"Proxy error for NeoForge Maven {path}: {e}")
raise HTTPException(502, f"Bad Gateway: {str(e)}")
@app.get("/proxy/download")
async def proxy_download(request: Request):
"""Универсальный прокси для скачивания файлов"""
@@ -1096,7 +1149,8 @@ async def proxy_download(request: Request):
"launchermeta.mojang.com",
"resources.download.minecraft.net",
"maven.minecraftforge.net",
"files.minecraftforge.net"
"files.minecraftforge.net",
"maven.neoforged.net"
]
# Проверяем, что URL ведет на разрешенный домен
@@ -1172,7 +1226,8 @@ async def proxy_status():
"piston-meta.mojang.com",
"launchermeta.mojang.com",
"resources.download.minecraft.net",
"maven.minecraftforge.net"
"maven.minecraftforge.net",
"maven.neoforged.net"
],
"note": "Use this proxy if you have network issues connecting to Fabric/Mojang/Forge"
}
+2 -1
View File
@@ -27,4 +27,5 @@ class PackMeta(BaseModel):
minecraft_version: str
loader_type: str
loader_version: Optional[str] = None
loader_version: Optional[str] = None
asset_index: Optional[str] = None
+4 -1
View File
@@ -109,6 +109,7 @@ async def scan_pack(pack_name: str, force_rescan: bool = False) -> PackMeta:
minecraft_version = "1.20.4"
loader_type = "vanilla"
loader_version = None
asset_index = None
pack_config_path = pack_path / "instance.json"
if pack_config_path.exists():
@@ -119,6 +120,7 @@ async def scan_pack(pack_name: str, force_rescan: bool = False) -> PackMeta:
minecraft_version = config.get("minecraftVersion", minecraft_version)
loader_type = config.get("loaderType", loader_type)
loader_version = config.get("loaderVersion")
asset_index = config.get("assetIndex")
except Exception as e:
logger.warning(f"Failed to load instance.json for {pack_name}: {e}")
@@ -131,7 +133,8 @@ async def scan_pack(pack_name: str, force_rescan: bool = False) -> PackMeta:
ignored_dirs=ignored_dirs,
minecraft_version=minecraft_version,
loader_type=loader_type,
loader_version=loader_version
loader_version=loader_version,
asset_index=asset_index
)
# Save to disk (синхронно)