fix: критичные баги — отсутствие auth на pack файлах, сломанный proxy fallback, race condition installInProgress, JSON парсинг, падение loadMetadata
This commit is contained in:
@@ -130,7 +130,9 @@ public class Instance {
|
||||
this.isServerPack = meta.isServerPack;
|
||||
this.serverVersion = meta.serverVersion;
|
||||
this.serverPackName = meta.serverPackName;
|
||||
} catch (Exception ignored) {}
|
||||
} catch (Exception e) {
|
||||
System.err.println("[Instance] Failed to load metadata for " + name + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void saveMetadata() {
|
||||
|
||||
@@ -44,6 +44,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.Headers;
|
||||
@@ -51,7 +52,7 @@ import com.sun.net.httpserver.Headers;
|
||||
public class JFXLauncher extends Application {
|
||||
private static int PORT = 8080;
|
||||
private static final String APP_TITLE = "ZernMC Launcher";
|
||||
private static final String LAUNCHER_SERVER = System.getProperty("launcher.server", "http://87.120.187.36:1582");
|
||||
private static final String LAUNCHER_SERVER = System.getProperty("launcher.server", "https://api.zernmc.ru");
|
||||
private final LauncherAPI api = new LauncherAPI();
|
||||
private final Gson gson = new Gson();
|
||||
private HttpServer server;
|
||||
@@ -64,7 +65,7 @@ public class JFXLauncher extends Application {
|
||||
private static volatile String installProgressLabel = "";
|
||||
private static volatile int installProgressCurrent = 0;
|
||||
private static volatile int installProgressTotal = 100;
|
||||
private static volatile boolean installInProgress = false;
|
||||
private static final AtomicBoolean installInProgress = new AtomicBoolean(false);
|
||||
private static volatile String installStageName = "";
|
||||
private static volatile int installStageIndex = 0;
|
||||
private static volatile int installStageCount = 1;
|
||||
@@ -114,11 +115,11 @@ public class JFXLauncher extends Application {
|
||||
}
|
||||
|
||||
public static void setInstallInProgress(boolean inProgress) {
|
||||
installInProgress = inProgress;
|
||||
installInProgress.set(inProgress);
|
||||
}
|
||||
|
||||
public static boolean isInstallInProgress() {
|
||||
return installInProgress;
|
||||
return installInProgress.get();
|
||||
}
|
||||
|
||||
public static void appendLauncherLog(String msg) {
|
||||
@@ -243,14 +244,9 @@ public class JFXLauncher extends Application {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) sb.append(line);
|
||||
String response = sb.toString();
|
||||
int versionStart = response.indexOf("\"version\":\"");
|
||||
if (versionStart >= 0) {
|
||||
int afterVersion = versionStart + 11;
|
||||
int versionEnd = response.indexOf("\"", afterVersion);
|
||||
if (versionEnd > afterVersion) {
|
||||
return response.substring(afterVersion, versionEnd);
|
||||
}
|
||||
org.json.JSONObject obj = new org.json.JSONObject(sb.toString());
|
||||
if (obj.has("version")) {
|
||||
return obj.getString("version");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -669,13 +665,14 @@ public class JFXLauncher extends Application {
|
||||
}
|
||||
|
||||
private void handleInstall(HttpExchange exchange) {
|
||||
if (installInProgress) {
|
||||
if (!installInProgress.compareAndSet(false, true)) {
|
||||
sendJson(exchange, Map.of("success", false, "error", "Installation already in progress"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!api.isLoggedIn()) {
|
||||
installInProgress.set(false);
|
||||
sendJson(exchange, Map.of("success", false, "error", "Not authenticated"));
|
||||
return;
|
||||
}
|
||||
@@ -690,6 +687,7 @@ public class JFXLauncher extends Application {
|
||||
|
||||
var createResult = api.instances().createInstance(name);
|
||||
if (!createResult.isSuccess()) {
|
||||
installInProgress.set(false);
|
||||
sendJson(exchange, Map.of("success", false, "error", createResult.getError()));
|
||||
return;
|
||||
}
|
||||
@@ -706,7 +704,6 @@ public class JFXLauncher extends Application {
|
||||
|
||||
sendJson(exchange, Map.of("success", true, "message", "Installation started"));
|
||||
|
||||
setInstallInProgress(true);
|
||||
setInstallProgressWithStage("Preparing...", 0, 100, "Preparing", 0, 4);
|
||||
|
||||
Thread installThread = new Thread(() -> {
|
||||
@@ -777,15 +774,15 @@ public class JFXLauncher extends Application {
|
||||
progress.put("label", installProgressLabel);
|
||||
progress.put("current", installProgressCurrent);
|
||||
progress.put("total", installProgressTotal);
|
||||
progress.put("inProgress", installInProgress);
|
||||
progress.put("inProgress", installInProgress.get());
|
||||
progress.put("stageName", installStageName);
|
||||
progress.put("stageIndex", installStageIndex);
|
||||
progress.put("stageCount", Math.max(installStageCount, 1));
|
||||
|
||||
if (installInProgress && installProgressTotal > 0) {
|
||||
if (installInProgress.get() && installProgressTotal > 0) {
|
||||
progress.put("percent", (int) ((installProgressCurrent * 100.0) / installProgressTotal));
|
||||
} else {
|
||||
progress.put("percent", installInProgress ? 0 : 100);
|
||||
progress.put("percent", installInProgress.get() ? 0 : 100);
|
||||
}
|
||||
|
||||
sendJson(exchange, Map.of("success", true, "data", progress));
|
||||
|
||||
@@ -15,7 +15,7 @@ public class Config {
|
||||
private static final Properties props = new Properties();
|
||||
|
||||
private static volatile int maxMemory = 4096;
|
||||
private static volatile String serverUrl = "http://87.120.187.36:1582";
|
||||
private static volatile String serverUrl = "https://api.zernmc.ru";
|
||||
private static volatile String lastUsername = "Player";
|
||||
private static volatile int windowWidth = 1280;
|
||||
private static volatile int windowHeight = 720;
|
||||
@@ -238,7 +238,14 @@ public class Config {
|
||||
public static long getSystemTotalRamMB() {
|
||||
long totalMb = getTotalSystemRamMB();
|
||||
if (totalMb > 0) return totalMb;
|
||||
return Runtime.getRuntime().maxMemory() / (1024 * 1024);
|
||||
try {
|
||||
java.lang.management.OperatingSystemMXBean osBean = java.lang.management.ManagementFactory.getOperatingSystemMXBean();
|
||||
if (osBean instanceof com.sun.management.OperatingSystemMXBean sunBean) {
|
||||
return sunBean.getTotalMemorySize() / (1024 * 1024);
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
long jvmMax = Runtime.getRuntime().maxMemory() / (1024 * 1024);
|
||||
return Math.max(jvmMax, 4096);
|
||||
}
|
||||
|
||||
public static String getSystemJvmFlags() {
|
||||
|
||||
@@ -27,7 +27,7 @@ public class ZHttpClient {
|
||||
.version(HttpClient.Version.HTTP_1_1)
|
||||
.build();
|
||||
|
||||
private static String BASE_URL = "http://87.120.187.36:1582";
|
||||
private static String BASE_URL = "https://api.zernmc.ru";
|
||||
|
||||
private static final AtomicBoolean useProxyMode = new AtomicBoolean(false);
|
||||
private static final AtomicBoolean proxyTested = new AtomicBoolean(false);
|
||||
@@ -41,7 +41,7 @@ public class ZHttpClient {
|
||||
}
|
||||
|
||||
public enum ServiceType {
|
||||
ZERN_SERVER("http://87.120.187.36:1582", true),
|
||||
ZERN_SERVER("https://api.zernmc.ru", true),
|
||||
FABRIC_META("https://meta.fabricmc.net", false),
|
||||
FABRIC_MAVEN("https://maven.fabricmc.net", false),
|
||||
MOJANG_META("https://piston-meta.mojang.com", false),
|
||||
@@ -306,7 +306,7 @@ public class ZHttpClient {
|
||||
|
||||
try {
|
||||
String encodedUrl = URLEncoder.encode(url, StandardCharsets.UTF_8);
|
||||
String proxyUrl = BASE_URL + "/download?url=" + encodedUrl;
|
||||
String proxyUrl = BASE_URL + "/proxy/download?url=" + encodedUrl;
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(proxyUrl))
|
||||
@@ -373,10 +373,6 @@ public class ZHttpClient {
|
||||
}
|
||||
|
||||
public static String get(String endpoint) throws IOException, InterruptedException {
|
||||
if (useProxyMode.get()) {
|
||||
return proxyGet(endpoint);
|
||||
}
|
||||
|
||||
try {
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
|
||||
.uri(URI.create(BASE_URL + endpoint))
|
||||
@@ -402,33 +398,6 @@ public class ZHttpClient {
|
||||
}
|
||||
}
|
||||
|
||||
private static String proxyGet(String endpoint) throws IOException {
|
||||
try {
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
|
||||
.uri(URI.create(BASE_URL + "/proxy" + endpoint))
|
||||
.timeout(Duration.ofSeconds(30))
|
||||
.header("User-Agent", "ZernMC-Launcher/1.0")
|
||||
.GET();
|
||||
|
||||
String accessToken = AuthManager.getAccessToken();
|
||||
if (accessToken != null && !accessToken.equals("0")) {
|
||||
requestBuilder.header("Authorization", "Bearer " + accessToken);
|
||||
}
|
||||
|
||||
HttpRequest request = requestBuilder.build();
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
if (response.statusCode() != 200) {
|
||||
throw new IOException("HTTP " + response.statusCode());
|
||||
}
|
||||
|
||||
proxySuccessCount++;
|
||||
return response.body();
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Proxy error: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getFabricLoaderVersions() throws IOException, InterruptedException {
|
||||
String url = "https://meta.fabricmc.net/v2/versions/loader";
|
||||
return parseFabricVersionsFromJson(getWithSmartProxy(url));
|
||||
|
||||
Reference in New Issue
Block a user