feat(multiplayer): WIP: download cato.

This commit is contained in:
huanghongxun 2021-09-09 22:08:25 +08:00
parent 8c3904cdcc
commit 3327899cf6
2 changed files with 87 additions and 5 deletions

View File

@ -17,7 +17,76 @@
*/ */
package org.jackhuang.hmcl.ui.multiplayer; package org.jackhuang.hmcl.ui.multiplayer;
import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.game.Artifact;
import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.task.TaskExecutor;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
import org.jackhuang.hmcl.util.io.NetworkUtils;
import org.jackhuang.hmcl.util.platform.ManagedProcess;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
/**
* Cato Management.
*/
public class MultiplayerManager { public class MultiplayerManager {
private static final String CATO_DOWNLOAD_URL = "https://hmcl.huangyuhui.net/maven/";
private static final String CATO_VERSION = "2021-09-01";
private static final Artifact CATO_ARTIFACT = new Artifact("cato", "cato", CATO_VERSION);
public static void fetchIdAndToken() {
// TODO
}
public static Task<Void> downloadCato() {
return new FileDownloadTask(
NetworkUtils.toURL(CATO_DOWNLOAD_URL + CATO_ARTIFACT.getPath()),
getCatoExecutable().toFile()
);
}
public static Path getCatoExecutable() {
return CATO_ARTIFACT.getPath(Metadata.HMCL_DIRECTORY);
}
public static ManagedProcess joinRoom(String token, String peer, String localAddress, String remoteAddress) throws IOException {
Path exe = getCatoExecutable();
if (!Files.isRegularFile(exe)) {
throw new IllegalStateException("Cato file not found");
}
String[] commands = new String[]{exe.toString(), "--peer", peer, "--from", localAddress, "--to", remoteAddress};
Process process = new ProcessBuilder()
.command(commands)
.inheritIO()
.start();
ManagedProcess managedProcess = new ManagedProcess(process, Arrays.asList(commands));
managedProcess.getProcess().getOutputStream().write(token.getBytes(StandardCharsets.UTF_8));
return managedProcess;
}
public static ManagedProcess createRoom(String token, String peer, String localAddress) throws IOException {
Path exe = getCatoExecutable();
if (!Files.isRegularFile(exe)) {
throw new IllegalStateException("Cato file not found");
}
String[] commands = new String[]{exe.toString(), "--peer", peer, "--from", localAddress};
Process process = new ProcessBuilder()
.command(commands)
.inheritIO()
.start();
ManagedProcess managedProcess = new ManagedProcess(process, Arrays.asList(commands));
managedProcess.getProcess().getOutputStream().write(token.getBytes(StandardCharsets.UTF_8));
return managedProcess;
}
enum State { enum State {
DISCONNECTED, DISCONNECTED,

View File

@ -19,14 +19,13 @@ package org.jackhuang.hmcl.ui.multiplayer;
import de.javawi.jstun.test.DiscoveryInfo; import de.javawi.jstun.test.DiscoveryInfo;
import de.javawi.jstun.test.DiscoveryTest; import de.javawi.jstun.test.DiscoveryTest;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.*;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.Control; import javafx.scene.control.Control;
import javafx.scene.control.Skin; import javafx.scene.control.Skin;
import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.task.TaskExecutor;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage; import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
@ -39,6 +38,7 @@ public class MultiplayerPage extends Control implements DecoratorPage {
public MultiplayerPage() { public MultiplayerPage() {
testNAT(); testNAT();
downloadCatoIfNecessary();
} }
@Override @Override
@ -66,7 +66,7 @@ public class MultiplayerPage extends Control implements DecoratorPage {
return natState.getReadOnlyProperty(); return natState.getReadOnlyProperty();
} }
public void testNAT() { private void testNAT() {
Task.supplyAsync(() -> { Task.supplyAsync(() -> {
DiscoveryTest tester = new DiscoveryTest(null, 0, "stun.qq.com", 3478); DiscoveryTest tester = new DiscoveryTest(null, 0, "stun.qq.com", 3478);
return tester.test(); return tester.test();
@ -79,6 +79,19 @@ public class MultiplayerPage extends Control implements DecoratorPage {
}).start(); }).start();
} }
private void downloadCatoIfNecessary() {
if (!MultiplayerManager.getCatoExecutable().toFile().exists()) {
setDisabled(true);
TaskExecutor executor = MultiplayerManager.downloadCato()
.thenRunAsync(Schedulers.javafx(), () -> {
setDisabled(false);
}).executor(false);
Controllers.taskDialog(executor, i18n("multiplayer.download"));
} else {
setDisabled(false);
}
}
@Override @Override
public ReadOnlyObjectProperty<State> stateProperty() { public ReadOnlyObjectProperty<State> stateProperty() {
return state; return state;