mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-13 13:56:55 -04:00
feat(multiplayer): wip: hiper
This commit is contained in:
parent
03541a6f85
commit
99be810b5e
@ -29,9 +29,9 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|||||||
|
|
||||||
public class LocalServerBroadcaster implements Runnable {
|
public class LocalServerBroadcaster implements Runnable {
|
||||||
private final int port;
|
private final int port;
|
||||||
private final MultiplayerManager.CatoSession session;
|
private final MultiplayerManager.HiperSession session;
|
||||||
|
|
||||||
public LocalServerBroadcaster(int port, MultiplayerManager.CatoSession session) {
|
public LocalServerBroadcaster(int port, MultiplayerManager.HiperSession session) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ public class MultiplayerClient extends Thread {
|
|||||||
LOG.info("Connected to 127.0.0.1:" + port);
|
LOG.info("Connected to 127.0.0.1:" + port);
|
||||||
|
|
||||||
endpoint.write(new HandshakeRequest());
|
endpoint.write(new HandshakeRequest());
|
||||||
endpoint.write(new JoinRequest(MultiplayerManager.CATO_VERSION, id));
|
endpoint.write(new JoinRequest(MultiplayerManager.HIPER_VERSION, id));
|
||||||
|
|
||||||
LOG.fine("Sent join request with id=" + id);
|
LOG.fine("Sent join request with id=" + id);
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@ import org.jackhuang.hmcl.util.StringUtils;
|
|||||||
import org.jackhuang.hmcl.util.io.ChecksumMismatchException;
|
import org.jackhuang.hmcl.util.io.ChecksumMismatchException;
|
||||||
import org.jackhuang.hmcl.util.io.HttpRequest;
|
import org.jackhuang.hmcl.util.io.HttpRequest;
|
||||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
import org.jackhuang.hmcl.util.platform.Architecture;
|
|
||||||
import org.jackhuang.hmcl.util.platform.CommandBuilder;
|
import org.jackhuang.hmcl.util.platform.CommandBuilder;
|
||||||
import org.jackhuang.hmcl.util.platform.ManagedProcess;
|
import org.jackhuang.hmcl.util.platform.ManagedProcess;
|
||||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||||
@ -59,11 +58,12 @@ import static org.jackhuang.hmcl.util.Logging.LOG;
|
|||||||
* Cato Management.
|
* Cato Management.
|
||||||
*/
|
*/
|
||||||
public final class MultiplayerManager {
|
public final class MultiplayerManager {
|
||||||
static final String CATO_VERSION = "1.2.2";
|
static final String HIPER_VERSION = "1.2.2";
|
||||||
private static final String CATO_DOWNLOAD_URL = "https://gitcode.net/to/cato/-/raw/master/client/";
|
private static final String HIPER_DOWNLOAD_URL = "https://gitcode.net/to/hiper/-/raw/master/";
|
||||||
private static final String CATO_HASH_URL = CATO_DOWNLOAD_URL + "cato-all-files.sha1";
|
private static final String HIPER_PACKAGES_URL = HIPER_DOWNLOAD_URL + "packages.sha1";
|
||||||
private static final String CATO_PATH = getCatoPath();
|
private static final Path HIPER_CONFIG_PATH = Metadata.HMCL_DIRECTORY.resolve("hiper.yml");
|
||||||
public static final int CATO_AGREEMENT_VERSION = 2;
|
private static final String HIPER_PATH = getHiperPath();
|
||||||
|
public static final int HIPER_AGREEMENT_VERSION = 2;
|
||||||
private static final String REMOTE_ADDRESS = "127.0.0.1";
|
private static final String REMOTE_ADDRESS = "127.0.0.1";
|
||||||
private static final String LOCAL_ADDRESS = "0.0.0.0";
|
private static final String LOCAL_ADDRESS = "0.0.0.0";
|
||||||
|
|
||||||
@ -72,18 +72,18 @@ public final class MultiplayerManager {
|
|||||||
private MultiplayerManager() {
|
private MultiplayerManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CompletableFuture<Map<String, String>> getCatoHash() {
|
private static CompletableFuture<Map<String, String>> getPackagesHash() {
|
||||||
FXUtils.checkFxUserThread();
|
FXUtils.checkFxUserThread();
|
||||||
if (HASH == null) {
|
if (HASH == null) {
|
||||||
HASH = CompletableFuture.supplyAsync(wrap(() -> {
|
HASH = CompletableFuture.supplyAsync(wrap(() -> {
|
||||||
String hashList = HttpRequest.GET(CATO_HASH_URL).getString();
|
String hashList = HttpRequest.GET(HIPER_PACKAGES_URL).getString();
|
||||||
Map<String, String> hashes = new HashMap<>();
|
Map<String, String> hashes = new HashMap<>();
|
||||||
for (String line : hashList.split("\n")) {
|
for (String line : hashList.split("\n")) {
|
||||||
String[] items = line.trim().split(" ");
|
String[] items = line.trim().split(" {2}");
|
||||||
if (items.length == 2 && items[0].length() == 40) {
|
if (items.length == 2 && items[0].length() == 40) {
|
||||||
hashes.put(items[1], items[0]);
|
hashes.put(items[1], items[0]);
|
||||||
} else {
|
} else {
|
||||||
LOG.warning("Failed to parse cato hash file, hash line " + line);
|
LOG.warning("Failed to parse Hiper packages.sha1 file, line: " + line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hashes;
|
return hashes;
|
||||||
@ -92,38 +92,34 @@ public final class MultiplayerManager {
|
|||||||
return HASH;
|
return HASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<Void> downloadCato() {
|
public static Task<Void> downloadHiper() {
|
||||||
return Task.fromCompletableFuture(getCatoHash()).thenComposeAsync(catoHashes ->
|
return Task.fromCompletableFuture(getPackagesHash()).thenComposeAsync(packagesHash ->
|
||||||
new FileDownloadTask(
|
new FileDownloadTask(
|
||||||
NetworkUtils.toURL(CATO_DOWNLOAD_URL + getCatoFileName()),
|
NetworkUtils.toURL(HIPER_DOWNLOAD_URL + getHiperFileName()),
|
||||||
getCatoExecutable().toFile(),
|
getHiperExecutable().toFile(),
|
||||||
catoHashes.get(getCatoFileName()) == null ? null : new FileDownloadTask.IntegrityCheck("SHA-1", catoHashes.get(getCatoFileName()))
|
packagesHash.get(getHiperFileName()) == null ? null : new FileDownloadTask.IntegrityCheck("SHA-1", packagesHash.get(getHiperFileName()))
|
||||||
).thenRunAsync(() -> {
|
).thenRunAsync(() -> {
|
||||||
if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX || OperatingSystem.CURRENT_OS == OperatingSystem.OSX) {
|
if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX || OperatingSystem.CURRENT_OS == OperatingSystem.OSX) {
|
||||||
Set<PosixFilePermission> perm = Files.getPosixFilePermissions(getCatoExecutable());
|
Set<PosixFilePermission> perm = Files.getPosixFilePermissions(getHiperExecutable());
|
||||||
perm.add(PosixFilePermission.OWNER_EXECUTE);
|
perm.add(PosixFilePermission.OWNER_EXECUTE);
|
||||||
Files.setPosixFilePermissions(getCatoExecutable(), perm);
|
Files.setPosixFilePermissions(getHiperExecutable(), perm);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Path getCatoExecutable() {
|
public static Path getHiperExecutable() {
|
||||||
return Metadata.HMCL_DIRECTORY.resolve("libraries").resolve(CATO_PATH);
|
return Metadata.HMCL_DIRECTORY.resolve("libraries").resolve(HIPER_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CompletableFuture<CatoSession> startCato(String token, State state) {
|
private static CompletableFuture<HiperSession> startHiper(String token, State state) {
|
||||||
return getCatoHash().thenApplyAsync(wrap(catoHashes -> {
|
return getPackagesHash().thenApplyAsync(wrap(packagesHash -> {
|
||||||
Path exe = getCatoExecutable();
|
Path exe = getHiperExecutable();
|
||||||
if (!Files.isRegularFile(exe)) {
|
if (!Files.isRegularFile(exe)) {
|
||||||
throw new CatoNotExistsException(exe);
|
throw new HiperNotExistsException(exe);
|
||||||
}
|
|
||||||
|
|
||||||
if (!isPortAvailable(3478)) {
|
|
||||||
throw new CatoAlreadyStartedException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String hash = catoHashes.get(getCatoFileName());
|
String hash = packagesHash.get(getHiperFileName());
|
||||||
if (hash != null) {
|
if (hash != null) {
|
||||||
ChecksumMismatchException.verifyChecksum(exe, "SHA-1", hash);
|
ChecksumMismatchException.verifyChecksum(exe, "SHA-1", hash);
|
||||||
}
|
}
|
||||||
@ -139,28 +135,28 @@ public final class MultiplayerManager {
|
|||||||
.command(commands)
|
.command(commands)
|
||||||
.start();
|
.start();
|
||||||
|
|
||||||
return new CatoSession(state, process, Arrays.asList(commands));
|
return new HiperSession(state, process, Arrays.asList(commands));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompletableFuture<CatoSession> joinSession(String token, String peer, Mode mode, int remotePort, int localPort, JoinSessionHandler handler) throws IncompatibleCatoVersionException {
|
public static CompletableFuture<HiperSession> joinSession(String token, String peer, Mode mode, int remotePort, int localPort, JoinSessionHandler handler) throws IncompatibleHiperVersionException {
|
||||||
LOG.info(String.format("Joining session (token=%s,peer=%s,mode=%s,remotePort=%d,localPort=%d)", token, peer, mode, remotePort, localPort));
|
LOG.info(String.format("Joining session (token=%s,peer=%s,mode=%s,remotePort=%d,localPort=%d)", token, peer, mode, remotePort, localPort));
|
||||||
|
|
||||||
return startCato(token, State.SLAVE).thenComposeAsync(wrap(session -> {
|
return startHiper(token, State.SLAVE).thenComposeAsync(wrap(session -> {
|
||||||
CompletableFuture<CatoSession> future = new CompletableFuture<>();
|
CompletableFuture<HiperSession> future = new CompletableFuture<>();
|
||||||
|
|
||||||
session.forwardPort(peer, LOCAL_ADDRESS, localPort, REMOTE_ADDRESS, remotePort, mode);
|
session.forwardPort(peer, LOCAL_ADDRESS, localPort, REMOTE_ADDRESS, remotePort, mode);
|
||||||
|
|
||||||
Consumer<CatoExitEvent> onExit = event -> {
|
Consumer<HiperExitEvent> onExit = event -> {
|
||||||
boolean ready = session.isReady();
|
boolean ready = session.isReady();
|
||||||
switch (event.getExitCode()) {
|
switch (event.getExitCode()) {
|
||||||
case 1:
|
case 1:
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
future.completeExceptionally(new CatoExitTimeoutException());
|
future.completeExceptionally(new HiperExitTimeoutException());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
future.completeExceptionally(new CatoExitException(event.getExitCode(), ready));
|
future.completeExceptionally(new HiperExitException(event.getExitCode(), ready));
|
||||||
};
|
};
|
||||||
session.onExit.register(onExit);
|
session.onExit.register(onExit);
|
||||||
|
|
||||||
@ -225,11 +221,11 @@ public final class MultiplayerManager {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompletableFuture<CatoSession> createSession(String token, String sessionName, int gamePort, boolean allowAllJoinRequests) {
|
public static CompletableFuture<HiperSession> createSession(String token, String sessionName, int gamePort, boolean allowAllJoinRequests) {
|
||||||
LOG.info(String.format("Creating session (token=%s,sessionName=%s,gamePort=%d)", token, sessionName, gamePort));
|
LOG.info(String.format("Creating session (token=%s,sessionName=%s,gamePort=%d)", token, sessionName, gamePort));
|
||||||
|
|
||||||
return startCato(token, State.MASTER).thenComposeAsync(wrap(session -> {
|
return startHiper(token, State.MASTER).thenComposeAsync(wrap(session -> {
|
||||||
CompletableFuture<CatoSession> future = new CompletableFuture<>();
|
CompletableFuture<HiperSession> future = new CompletableFuture<>();
|
||||||
|
|
||||||
MultiplayerServer server = new MultiplayerServer(sessionName, gamePort, allowAllJoinRequests);
|
MultiplayerServer server = new MultiplayerServer(sessionName, gamePort, allowAllJoinRequests);
|
||||||
server.startServer();
|
server.startServer();
|
||||||
@ -239,16 +235,16 @@ public final class MultiplayerManager {
|
|||||||
session.allowForwardingAddress(REMOTE_ADDRESS, gamePort);
|
session.allowForwardingAddress(REMOTE_ADDRESS, gamePort);
|
||||||
session.showAllowedAddress();
|
session.showAllowedAddress();
|
||||||
|
|
||||||
Consumer<CatoExitEvent> onExit = event -> {
|
Consumer<HiperExitEvent> onExit = event -> {
|
||||||
boolean ready = session.isReady();
|
boolean ready = session.isReady();
|
||||||
switch (event.getExitCode()) {
|
switch (event.getExitCode()) {
|
||||||
case 1:
|
case 1:
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
future.completeExceptionally(new CatoExitTimeoutException());
|
future.completeExceptionally(new HiperExitTimeoutException());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
future.completeExceptionally(new CatoExitException(event.getExitCode(), ready));
|
future.completeExceptionally(new HiperExitException(event.getExitCode(), ready));
|
||||||
};
|
};
|
||||||
|
|
||||||
session.onExit.register(onExit);
|
session.onExit.register(onExit);
|
||||||
@ -294,49 +290,22 @@ public final class MultiplayerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getCatoFileName() {
|
private static String getHiperFileName() {
|
||||||
switch (OperatingSystem.CURRENT_OS) {
|
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
|
||||||
case WINDOWS:
|
return "hiper.exe";
|
||||||
if (Architecture.SYSTEM_ARCH == Architecture.X86_64) {
|
} else {
|
||||||
return "cato-client-windows-amd64.exe";
|
return "hiper";
|
||||||
} else if (Architecture.SYSTEM_ARCH == Architecture.ARM64) {
|
|
||||||
return "cato-client-windows-arm64.exe";
|
|
||||||
} else if (Architecture.SYSTEM_ARCH == Architecture.X86) {
|
|
||||||
return "cato-client-windows-i386.exe";
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
case OSX:
|
|
||||||
if (Architecture.SYSTEM_ARCH == Architecture.X86_64) {
|
|
||||||
return "cato-client-darwin-amd64";
|
|
||||||
} else if (Architecture.SYSTEM_ARCH == Architecture.ARM64) {
|
|
||||||
return "cato-client-darwin-arm64";
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
case LINUX:
|
|
||||||
if (Architecture.SYSTEM_ARCH == Architecture.X86_64) {
|
|
||||||
return "cato-client-linux-amd64";
|
|
||||||
} else if (Architecture.SYSTEM_ARCH == Architecture.ARM32) {
|
|
||||||
return "cato-client-linux-arm7";
|
|
||||||
} else if (Architecture.SYSTEM_ARCH == Architecture.ARM64) {
|
|
||||||
return "cato-client-linux-arm64";
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getCatoPath() {
|
public static String getHiperPath() {
|
||||||
String name = getCatoFileName();
|
String name = getHiperFileName();
|
||||||
if (StringUtils.isBlank(name)) return "";
|
if (StringUtils.isBlank(name)) return "";
|
||||||
return "cato/cato/" + MultiplayerManager.CATO_VERSION + "/" + name;
|
return "hiper/hiper/" + MultiplayerManager.HIPER_VERSION + "/" + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CatoSession extends ManagedProcess {
|
public static class HiperSession extends ManagedProcess {
|
||||||
private final EventManager<CatoExitEvent> onExit = new EventManager<>();
|
private final EventManager<HiperExitEvent> onExit = new EventManager<>();
|
||||||
private final EventManager<CatoIdEvent> onIdGenerated = new EventManager<>();
|
private final EventManager<CatoIdEvent> onIdGenerated = new EventManager<>();
|
||||||
private final EventManager<Event> onPeerConnected = new EventManager<>();
|
private final EventManager<Event> onPeerConnected = new EventManager<>();
|
||||||
|
|
||||||
@ -348,15 +317,15 @@ public final class MultiplayerManager {
|
|||||||
private MultiplayerServer server;
|
private MultiplayerServer server;
|
||||||
private final BufferedWriter writer;
|
private final BufferedWriter writer;
|
||||||
|
|
||||||
CatoSession(State type, Process process, List<String> commands) {
|
HiperSession(State type, Process process, List<String> commands) {
|
||||||
super(process, commands);
|
super(process, commands);
|
||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(this::stop));
|
Runtime.getRuntime().addShutdownHook(new Thread(this::stop));
|
||||||
|
|
||||||
LOG.info("Started cato with command: " + new CommandBuilder().addAll(commands));
|
LOG.info("Started hiper with command: " + new CommandBuilder().addAll(commands));
|
||||||
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
addRelatedThread(Lang.thread(this::waitFor, "CatoExitWaiter", true));
|
addRelatedThread(Lang.thread(this::waitFor, "HiperExitWaiter", true));
|
||||||
pumpInputStream(this::checkCatoLog);
|
pumpInputStream(this::checkCatoLog);
|
||||||
pumpErrorStream(this::checkCatoLog);
|
pumpErrorStream(this::checkCatoLog);
|
||||||
|
|
||||||
@ -367,7 +336,7 @@ public final class MultiplayerManager {
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized CatoSession setClient(MultiplayerClient client) {
|
public synchronized HiperSession setClient(MultiplayerClient client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -376,13 +345,13 @@ public final class MultiplayerManager {
|
|||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CatoSession setServer(MultiplayerServer server) {
|
public HiperSession setServer(MultiplayerServer server) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkCatoLog(String log) {
|
private void checkCatoLog(String log) {
|
||||||
LOG.info("Cato: " + log);
|
LOG.info("[Hiper] " + log);
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
Matcher matcher = TEMP_TOKEN_PATTERN.matcher(log);
|
Matcher matcher = TEMP_TOKEN_PATTERN.matcher(log);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
@ -403,16 +372,16 @@ public final class MultiplayerManager {
|
|||||||
private void waitFor() {
|
private void waitFor() {
|
||||||
try {
|
try {
|
||||||
int exitCode = getProcess().waitFor();
|
int exitCode = getProcess().waitFor();
|
||||||
LOG.info("cato exited with exitcode " + exitCode);
|
LOG.info("Hiper exited with exitcode " + exitCode);
|
||||||
onExit.fireEvent(new CatoExitEvent(this, exitCode));
|
onExit.fireEvent(new HiperExitEvent(this, exitCode));
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
onExit.fireEvent(new CatoExitEvent(this, CatoExitEvent.EXIT_CODE_INTERRUPTED));
|
onExit.fireEvent(new HiperExitEvent(this, HiperExitEvent.EXIT_CODE_INTERRUPTED));
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (writer != null)
|
if (writer != null)
|
||||||
writer.close();
|
writer.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.log(Level.WARNING, "Failed to close cato stdin writer", e);
|
LOG.log(Level.WARNING, "Failed to close Hiper stdin writer", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
destroyRelatedThreads();
|
destroyRelatedThreads();
|
||||||
@ -447,7 +416,7 @@ public final class MultiplayerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void invokeCommand(String command) throws IOException {
|
public synchronized void invokeCommand(String command) throws IOException {
|
||||||
LOG.info("Invoking cato: " + command);
|
LOG.info("Invoking hiper: " + command);
|
||||||
writer.write(command);
|
writer.write(command);
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
writer.flush();
|
writer.flush();
|
||||||
@ -465,7 +434,7 @@ public final class MultiplayerManager {
|
|||||||
invokeCommand("ufw net whitelist");
|
invokeCommand("ufw net whitelist");
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventManager<CatoExitEvent> onExit() {
|
public EventManager<HiperExitEvent> onExit() {
|
||||||
return onExit;
|
return onExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,10 +451,10 @@ public final class MultiplayerManager {
|
|||||||
private static final Pattern LOG_PATTERN = Pattern.compile("(\\[\\d+])\\s+(\\w+)\\s+(\\w+-{0,1}\\w+):\\s(.*)");
|
private static final Pattern LOG_PATTERN = Pattern.compile("(\\[\\d+])\\s+(\\w+)\\s+(\\w+-{0,1}\\w+):\\s(.*)");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CatoExitEvent extends Event {
|
public static class HiperExitEvent extends Event {
|
||||||
private final int exitCode;
|
private final int exitCode;
|
||||||
|
|
||||||
public CatoExitEvent(Object source, int exitCode) {
|
public HiperExitEvent(Object source, int exitCode) {
|
||||||
super(source);
|
super(source);
|
||||||
this.exitCode = exitCode;
|
this.exitCode = exitCode;
|
||||||
}
|
}
|
||||||
@ -541,11 +510,11 @@ public final class MultiplayerManager {
|
|||||||
void onWaitingForJoinResponse();
|
void onWaitingForJoinResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class IncompatibleCatoVersionException extends Exception {
|
public static class IncompatibleHiperVersionException extends Exception {
|
||||||
private final String expected;
|
private final String expected;
|
||||||
private final String actual;
|
private final String actual;
|
||||||
|
|
||||||
public IncompatibleCatoVersionException(String expected, String actual) {
|
public IncompatibleHiperVersionException(String expected, String actual) {
|
||||||
this.expected = expected;
|
this.expected = expected;
|
||||||
this.actual = actual;
|
this.actual = actual;
|
||||||
}
|
}
|
||||||
@ -568,11 +537,11 @@ public final class MultiplayerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CatoExitException extends RuntimeException {
|
public static class HiperExitException extends RuntimeException {
|
||||||
private final int exitCode;
|
private final int exitCode;
|
||||||
private final boolean ready;
|
private final boolean ready;
|
||||||
|
|
||||||
public CatoExitException(int exitCode, boolean ready) {
|
public HiperExitException(int exitCode, boolean ready) {
|
||||||
this.exitCode = exitCode;
|
this.exitCode = exitCode;
|
||||||
this.ready = ready;
|
this.ready = ready;
|
||||||
}
|
}
|
||||||
@ -586,13 +555,13 @@ public final class MultiplayerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CatoExitTimeoutException extends RuntimeException {
|
public static class HiperExitTimeoutException extends RuntimeException {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CatoSessionExpiredException extends RuntimeException {
|
public static class HiperSessionExpiredException extends RuntimeException {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CatoAlreadyStartedException extends RuntimeException {
|
public static class HiperAlreadyStartedException extends RuntimeException {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class JoinRequestTimeoutException extends RuntimeException {
|
public static class JoinRequestTimeoutException extends RuntimeException {
|
||||||
@ -616,10 +585,10 @@ public final class MultiplayerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CatoNotExistsException extends RuntimeException {
|
public static class HiperNotExistsException extends RuntimeException {
|
||||||
private final Path file;
|
private final Path file;
|
||||||
|
|
||||||
public CatoNotExistsException(Path file) {
|
public HiperNotExistsException(Path file) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,10 +64,10 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
private final ReadOnlyStringWrapper token = new ReadOnlyStringWrapper();
|
private final ReadOnlyStringWrapper token = new ReadOnlyStringWrapper();
|
||||||
private final ReadOnlyObjectWrapper<@Nullable Result<DiscoveryInfo>> natState = new ReadOnlyObjectWrapper<>();
|
private final ReadOnlyObjectWrapper<@Nullable Result<DiscoveryInfo>> natState = new ReadOnlyObjectWrapper<>();
|
||||||
private final ReadOnlyIntegerWrapper gamePort = new ReadOnlyIntegerWrapper(-1);
|
private final ReadOnlyIntegerWrapper gamePort = new ReadOnlyIntegerWrapper(-1);
|
||||||
private final ReadOnlyObjectWrapper<MultiplayerManager.CatoSession> session = new ReadOnlyObjectWrapper<>();
|
private final ReadOnlyObjectWrapper<MultiplayerManager.HiperSession> session = new ReadOnlyObjectWrapper<>();
|
||||||
private final ObservableList<MultiplayerChannel.CatoClient> clients = FXCollections.observableArrayList();
|
private final ObservableList<MultiplayerChannel.CatoClient> clients = FXCollections.observableArrayList();
|
||||||
|
|
||||||
private Consumer<MultiplayerManager.CatoExitEvent> onExit;
|
private Consumer<MultiplayerManager.HiperExitEvent> onExit;
|
||||||
private Consumer<MultiplayerManager.CatoIdEvent> onIdGenerated;
|
private Consumer<MultiplayerManager.CatoIdEvent> onIdGenerated;
|
||||||
private Consumer<Event> onPeerConnected;
|
private Consumer<Event> onPeerConnected;
|
||||||
|
|
||||||
@ -125,11 +125,11 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
return gamePort.getReadOnlyProperty();
|
return gamePort.getReadOnlyProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultiplayerManager.CatoSession getSession() {
|
public MultiplayerManager.HiperSession getSession() {
|
||||||
return session.get();
|
return session.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlyObjectProperty<MultiplayerManager.CatoSession> sessionProperty() {
|
public ReadOnlyObjectProperty<MultiplayerManager.HiperSession> sessionProperty() {
|
||||||
return session.getReadOnlyProperty();
|
return session.getReadOnlyProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkAgreement(Runnable runnable) {
|
private void checkAgreement(Runnable runnable) {
|
||||||
if (globalConfig().getMultiplayerAgreementVersion() < MultiplayerManager.CATO_AGREEMENT_VERSION) {
|
if (globalConfig().getMultiplayerAgreementVersion() < MultiplayerManager.HIPER_AGREEMENT_VERSION) {
|
||||||
JFXDialogLayout agreementPane = new JFXDialogLayout();
|
JFXDialogLayout agreementPane = new JFXDialogLayout();
|
||||||
agreementPane.setHeading(new Label(i18n("launcher.agreement")));
|
agreementPane.setHeading(new Label(i18n("launcher.agreement")));
|
||||||
agreementPane.setBody(new Label(i18n("multiplayer.agreement.prompt")));
|
agreementPane.setBody(new Label(i18n("multiplayer.agreement.prompt")));
|
||||||
@ -157,7 +157,7 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
JFXButton yesButton = new JFXButton(i18n("launcher.agreement.accept"));
|
JFXButton yesButton = new JFXButton(i18n("launcher.agreement.accept"));
|
||||||
yesButton.getStyleClass().add("dialog-accept");
|
yesButton.getStyleClass().add("dialog-accept");
|
||||||
yesButton.setOnAction(e -> {
|
yesButton.setOnAction(e -> {
|
||||||
globalConfig().setMultiplayerAgreementVersion(MultiplayerManager.CATO_AGREEMENT_VERSION);
|
globalConfig().setMultiplayerAgreementVersion(MultiplayerManager.HIPER_AGREEMENT_VERSION);
|
||||||
runnable.run();
|
runnable.run();
|
||||||
agreementPane.fireEvent(new DialogCloseEvent());
|
agreementPane.fireEvent(new DialogCloseEvent());
|
||||||
});
|
});
|
||||||
@ -175,15 +175,15 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void downloadCatoIfNecessary() {
|
private void downloadCatoIfNecessary() {
|
||||||
if (StringUtils.isBlank(MultiplayerManager.getCatoPath())) {
|
if (StringUtils.isBlank(MultiplayerManager.getHiperPath())) {
|
||||||
Controllers.dialog(i18n("multiplayer.download.unsupported"), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR);
|
Controllers.dialog(i18n("multiplayer.download.unsupported"), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR);
|
||||||
fireEvent(new PageCloseEvent());
|
fireEvent(new PageCloseEvent());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MultiplayerManager.getCatoExecutable().toFile().exists()) {
|
if (!MultiplayerManager.getHiperExecutable().toFile().exists()) {
|
||||||
setDisabled(true);
|
setDisabled(true);
|
||||||
TaskExecutor executor = MultiplayerManager.downloadCato()
|
TaskExecutor executor = MultiplayerManager.downloadHiper()
|
||||||
.whenComplete(Schedulers.javafx(), exception -> {
|
.whenComplete(Schedulers.javafx(), exception -> {
|
||||||
setDisabled(false);
|
setDisabled(false);
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
@ -325,7 +325,7 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
reject.accept(localizeJoinErrorMessage(throwable, isStaticToken));
|
reject.accept(localizeJoinErrorMessage(throwable, isStaticToken));
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
} catch (MultiplayerManager.IncompatibleCatoVersionException e) {
|
} catch (MultiplayerManager.IncompatibleHiperVersionException e) {
|
||||||
reject.accept(i18n("multiplayer.session.join.invitation_code.version"));
|
reject.accept(i18n("multiplayer.session.join.invitation_code.version"));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -353,11 +353,11 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
} else if (e instanceof MultiplayerManager.KickedException) {
|
} else if (e instanceof MultiplayerManager.KickedException) {
|
||||||
LOG.info("Kicked by server");
|
LOG.info("Kicked by server");
|
||||||
return i18n("multiplayer.session.join.kicked", localizeKickMessage(((MultiplayerManager.KickedException) e).getReason()));
|
return i18n("multiplayer.session.join.kicked", localizeKickMessage(((MultiplayerManager.KickedException) e).getReason()));
|
||||||
} else if (e instanceof MultiplayerManager.CatoAlreadyStartedException) {
|
} else if (e instanceof MultiplayerManager.HiperAlreadyStartedException) {
|
||||||
LOG.info("Cato already started");
|
LOG.info("Cato already started");
|
||||||
return i18n("multiplayer.session.error.already_started");
|
return i18n("multiplayer.session.error.already_started");
|
||||||
} else if (e instanceof MultiplayerManager.CatoNotExistsException) {
|
} else if (e instanceof MultiplayerManager.HiperNotExistsException) {
|
||||||
LOG.log(Level.WARNING, "Cato not found " + ((MultiplayerManager.CatoNotExistsException) e).getFile(), e);
|
LOG.log(Level.WARNING, "Cato not found " + ((MultiplayerManager.HiperNotExistsException) e).getFile(), e);
|
||||||
return i18n("multiplayer.session.error.file_not_found");
|
return i18n("multiplayer.session.error.file_not_found");
|
||||||
} else if (e instanceof MultiplayerManager.JoinRequestTimeoutException) {
|
} else if (e instanceof MultiplayerManager.JoinRequestTimeoutException) {
|
||||||
LOG.info("Cato already started");
|
LOG.info("Cato already started");
|
||||||
@ -365,17 +365,17 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
} else if (e instanceof MultiplayerManager.ConnectionErrorException) {
|
} else if (e instanceof MultiplayerManager.ConnectionErrorException) {
|
||||||
LOG.info("Failed to establish connection with server");
|
LOG.info("Failed to establish connection with server");
|
||||||
return i18n("multiplayer.session.join.error.connection");
|
return i18n("multiplayer.session.join.error.connection");
|
||||||
} else if (e instanceof MultiplayerManager.CatoExitTimeoutException) {
|
} else if (e instanceof MultiplayerManager.HiperExitTimeoutException) {
|
||||||
LOG.info("Cato failed to connect to main net");
|
LOG.info("Cato failed to connect to main net");
|
||||||
if (isStaticToken) {
|
if (isStaticToken) {
|
||||||
return i18n("multiplayer.exit.timeout.static_token");
|
return i18n("multiplayer.exit.timeout.static_token");
|
||||||
} else {
|
} else {
|
||||||
return i18n("multiplayer.exit.timeout.dynamic_token");
|
return i18n("multiplayer.exit.timeout.dynamic_token");
|
||||||
}
|
}
|
||||||
} else if (e instanceof MultiplayerManager.CatoExitException) {
|
} else if (e instanceof MultiplayerManager.HiperExitException) {
|
||||||
LOG.info("Cato exited accidentally");
|
LOG.info("Cato exited accidentally");
|
||||||
int exitCode = ((MultiplayerManager.CatoExitException) e).getExitCode();
|
int exitCode = ((MultiplayerManager.HiperExitException) e).getExitCode();
|
||||||
if (!((MultiplayerManager.CatoExitException) e).isReady()) {
|
if (!((MultiplayerManager.HiperExitException) e).isReady()) {
|
||||||
return i18n("multiplayer.exit.before_ready", exitCode);
|
return i18n("multiplayer.exit.before_ready", exitCode);
|
||||||
} else {
|
} else {
|
||||||
return i18n("multiplayer.exit.after_ready", exitCode);
|
return i18n("multiplayer.exit.after_ready", exitCode);
|
||||||
@ -442,7 +442,7 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
stopCatoSession();
|
stopCatoSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initCatoSession(MultiplayerManager.CatoSession session) {
|
private void initCatoSession(MultiplayerManager.HiperSession session) {
|
||||||
runInFX(() -> {
|
runInFX(() -> {
|
||||||
onExit = session.onExit().registerWeak(this::onCatoExit);
|
onExit = session.onExit().registerWeak(this::onCatoExit);
|
||||||
onIdGenerated = session.onIdGenerated().registerWeak(this::onCatoIdGenerated);
|
onIdGenerated = session.onIdGenerated().registerWeak(this::onCatoIdGenerated);
|
||||||
@ -467,13 +467,13 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
this.multiplayerState.set(MultiplayerManager.State.DISCONNECTED);
|
this.multiplayerState.set(MultiplayerManager.State.DISCONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onCatoExit(MultiplayerManager.CatoExitEvent event) {
|
private void onCatoExit(MultiplayerManager.HiperExitEvent event) {
|
||||||
runInFX(() -> {
|
runInFX(() -> {
|
||||||
boolean ready = ((MultiplayerManager.CatoSession) event.getSource()).isReady();
|
boolean ready = ((MultiplayerManager.HiperSession) event.getSource()).isReady();
|
||||||
switch (event.getExitCode()) {
|
switch (event.getExitCode()) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case MultiplayerManager.CatoExitEvent.EXIT_CODE_SESSION_EXPIRED:
|
case MultiplayerManager.HiperExitEvent.EXIT_CODE_SESSION_EXPIRED:
|
||||||
Controllers.dialog(i18n("multiplayer.session.expired"));
|
Controllers.dialog(i18n("multiplayer.session.expired"));
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
@ -485,7 +485,7 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
// do nothing
|
// do nothing
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!((MultiplayerManager.CatoSession) event.getSource()).isReady()) {
|
if (!((MultiplayerManager.HiperSession) event.getSource()).isReady()) {
|
||||||
Controllers.dialog(i18n("multiplayer.exit.before_ready", event.getExitCode()));
|
Controllers.dialog(i18n("multiplayer.exit.before_ready", event.getExitCode()));
|
||||||
} else {
|
} else {
|
||||||
Controllers.dialog(i18n("multiplayer.exit.after_ready", event.getExitCode()));
|
Controllers.dialog(i18n("multiplayer.exit.after_ready", event.getExitCode()));
|
||||||
@ -505,7 +505,7 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
|||||||
private void onCatoIdGenerated(MultiplayerManager.CatoIdEvent event) {
|
private void onCatoIdGenerated(MultiplayerManager.CatoIdEvent event) {
|
||||||
runInFX(() -> {
|
runInFX(() -> {
|
||||||
token.set(event.getId());
|
token.set(event.getId());
|
||||||
setMultiplayerState(((MultiplayerManager.CatoSession) event.getSource()).getType());
|
setMultiplayerState(((MultiplayerManager.HiperSession) event.getSource()).getType());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ public class MultiplayerServer extends Thread {
|
|||||||
LOG.info("Received join request with clientVersion=" + joinRequest.getClientVersion() + ", id=" + joinRequest.getUsername());
|
LOG.info("Received join request with clientVersion=" + joinRequest.getClientVersion() + ", id=" + joinRequest.getUsername());
|
||||||
clientName = joinRequest.getUsername();
|
clientName = joinRequest.getUsername();
|
||||||
|
|
||||||
if (!Objects.equals(MultiplayerManager.CATO_VERSION, joinRequest.getClientVersion())) {
|
if (!Objects.equals(MultiplayerManager.HIPER_VERSION, joinRequest.getClientVersion())) {
|
||||||
try {
|
try {
|
||||||
endpoint.write(new KickResponse(KickResponse.VERSION_NOT_MATCHED));
|
endpoint.write(new KickResponse(KickResponse.VERSION_NOT_MATCHED));
|
||||||
LOG.info("Rejected join request from id=" + joinRequest.getUsername());
|
LOG.info("Rejected join request from id=" + joinRequest.getUsername());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user