mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-01-30 14:39:56 +08:00
fix(multiplayer): show connection timeout instead of kicked.
This commit is contained in:
parent
fca78cf419
commit
0fd8a78972
@ -29,6 +29,7 @@ public final class MultiplayerChannel {
|
||||
@JsonType(
|
||||
property = "type",
|
||||
subtypes = {
|
||||
@JsonSubtype(clazz = HandshakeRequest.class, name = "handshake"),
|
||||
@JsonSubtype(clazz = JoinRequest.class, name = "join"),
|
||||
@JsonSubtype(clazz = KeepAliveRequest.class, name = "keepalive")
|
||||
}
|
||||
@ -36,6 +37,9 @@ public final class MultiplayerChannel {
|
||||
public static class Request {
|
||||
}
|
||||
|
||||
public static class HandshakeRequest extends Request {
|
||||
}
|
||||
|
||||
public static class JoinRequest extends Request {
|
||||
private final String clientVersion;
|
||||
private final String username;
|
||||
@ -69,6 +73,7 @@ public final class MultiplayerChannel {
|
||||
@JsonType(
|
||||
property = "type",
|
||||
subtypes = {
|
||||
@JsonSubtype(clazz = HandshakeResponse.class, name = "handshake"),
|
||||
@JsonSubtype(clazz = JoinResponse.class, name = "join"),
|
||||
@JsonSubtype(clazz = KeepAliveResponse.class, name = "keepalive"),
|
||||
@JsonSubtype(clazz = KickResponse.class, name = "kick")
|
||||
@ -78,6 +83,9 @@ public final class MultiplayerChannel {
|
||||
|
||||
}
|
||||
|
||||
public static class HandshakeResponse extends Response {
|
||||
}
|
||||
|
||||
public static class JoinResponse extends Response {
|
||||
private final int port;
|
||||
|
||||
|
@ -20,12 +20,14 @@ package org.jackhuang.hmcl.ui.multiplayer;
|
||||
import com.google.gson.JsonParseException;
|
||||
import org.jackhuang.hmcl.event.Event;
|
||||
import org.jackhuang.hmcl.event.EventManager;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.TimerTask;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static org.jackhuang.hmcl.ui.multiplayer.MultiplayerChannel.*;
|
||||
@ -36,10 +38,12 @@ public class MultiplayerClient extends Thread {
|
||||
private final int port;
|
||||
|
||||
private int gamePort;
|
||||
private boolean connected = false;
|
||||
|
||||
private final EventManager<ConnectedEvent> onConnected = new EventManager<>();
|
||||
private final EventManager<Event> onDisconnected = new EventManager<>();
|
||||
private final EventManager<Event> onKicked = new EventManager<>();
|
||||
private final EventManager<Event> onHandshake = new EventManager<>();
|
||||
|
||||
public MultiplayerClient(String id, int port) {
|
||||
this.id = id;
|
||||
@ -66,7 +70,11 @@ public class MultiplayerClient extends Thread {
|
||||
}
|
||||
|
||||
public EventManager<Event> onKicked() {
|
||||
return onDisconnected;
|
||||
return onKicked;
|
||||
}
|
||||
|
||||
public EventManager<Event> onHandshake() {
|
||||
return onHandshake;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,15 +88,25 @@ public class MultiplayerClient extends Thread {
|
||||
MultiplayerServer.Endpoint endpoint = new MultiplayerServer.Endpoint(socket, writer);
|
||||
LOG.info("Connected to 127.0.0.1:" + port);
|
||||
|
||||
writer.write(JsonUtils.UGLY_GSON.toJson(new JoinRequest(MultiplayerManager.CATO_VERSION, id)));
|
||||
writer.newLine();
|
||||
writer.flush();
|
||||
endpoint.write(new HandshakeRequest());
|
||||
endpoint.write(new JoinRequest(MultiplayerManager.CATO_VERSION, id));
|
||||
|
||||
LOG.fine("Sent join request with id=" + id);
|
||||
|
||||
keepAliveThread = new KeepAliveThread(endpoint);
|
||||
keepAliveThread.start();
|
||||
|
||||
TimerTask task = Lang.setTimeout(() -> {
|
||||
// If after 15 seconds, we didn't receive the HandshakeResponse,
|
||||
// We fail to establish the connection with server.
|
||||
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.WARNING, "Failed to close socket", e);
|
||||
}
|
||||
}, 15 * 1000);
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (isInterrupted()) {
|
||||
@ -102,14 +120,21 @@ public class MultiplayerClient extends Thread {
|
||||
if (response instanceof JoinResponse) {
|
||||
JoinResponse joinResponse = JsonUtils.fromNonNullJson(line, JoinResponse.class);
|
||||
setGamePort(joinResponse.getPort());
|
||||
|
||||
connected = true;
|
||||
|
||||
onConnected.fireEvent(new ConnectedEvent(this, joinResponse.getPort()));
|
||||
|
||||
LOG.fine("Received join response with port " + joinResponse.getPort());
|
||||
} else if (response instanceof KickResponse) {
|
||||
onKicked.fireEvent(new Event(this));
|
||||
|
||||
LOG.fine("Kicked by the server");
|
||||
onKicked.fireEvent(new Event(this));
|
||||
return;
|
||||
} else if (response instanceof KeepAliveResponse) {
|
||||
} else if (response instanceof HandshakeResponse) {
|
||||
LOG.fine("Established connection with server");
|
||||
onHandshake.fireEvent(new Event(this));
|
||||
task.cancel();
|
||||
} else {
|
||||
LOG.log(Level.WARNING, "Unrecognized packet from server:" + line);
|
||||
}
|
||||
@ -135,6 +160,10 @@ public class MultiplayerClient extends Thread {
|
||||
onDisconnected.fireEvent(new Event(this));
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
private static class KeepAliveThread extends Thread {
|
||||
|
||||
private final MultiplayerServer.Endpoint endpoint;
|
||||
|
@ -131,10 +131,6 @@ public final class MultiplayerManager {
|
||||
session.addRelatedThread(client);
|
||||
session.setClient(client);
|
||||
|
||||
if (handler != null) {
|
||||
handler.onWaitingForJoinResponse();
|
||||
}
|
||||
|
||||
TimerTask task = Lang.setTimeout(() -> {
|
||||
future.completeExceptionally(new JoinRequestTimeoutException());
|
||||
session.stop();
|
||||
@ -162,6 +158,17 @@ public final class MultiplayerManager {
|
||||
session.stop();
|
||||
task.cancel();
|
||||
});
|
||||
client.onDisconnected().register(disconnectedEvent -> {
|
||||
if (!client.isConnected()) {
|
||||
// We fail to establish connection with server
|
||||
future.completeExceptionally(new ConnectionErrorException());
|
||||
}
|
||||
});
|
||||
client.onHandshake().register(handshakeEvent -> {
|
||||
if (handler != null) {
|
||||
handler.onWaitingForJoinResponse();
|
||||
}
|
||||
});
|
||||
client.start();
|
||||
});
|
||||
|
||||
@ -464,4 +471,7 @@ public final class MultiplayerManager {
|
||||
|
||||
public static class JoinRequestTimeoutException extends RuntimeException {
|
||||
}
|
||||
|
||||
public static class ConnectionErrorException extends RuntimeException {
|
||||
}
|
||||
}
|
||||
|
@ -132,6 +132,7 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
||||
FastDiscoveryTest tester = new FastDiscoveryTest(null, 0, "stun.qq.com", 3478);
|
||||
return tester.test();
|
||||
}).whenComplete(Schedulers.javafx(), (info, exception) -> {
|
||||
LOG.log(Level.INFO, "Nat test result " + MultiplayerPageSkin.getNATType(info), exception);
|
||||
if (exception == null) {
|
||||
natState.set(info);
|
||||
} else {
|
||||
@ -292,7 +293,9 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
||||
localPort, new MultiplayerManager.JoinSessionHandler() {
|
||||
@Override
|
||||
public void onWaitingForJoinResponse() {
|
||||
hintQuestion.setQuestion(i18n("multiplayer.session.join.wait"));
|
||||
runInFX(() -> {
|
||||
hintQuestion.setQuestion(i18n("multiplayer.session.join.wait"));
|
||||
});
|
||||
}
|
||||
})
|
||||
.thenAcceptAsync(session -> {
|
||||
@ -338,6 +341,10 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
|
||||
LOG.info("Cato already started");
|
||||
reject.accept(i18n("multiplayer.session.join.wait_timeout"));
|
||||
return null;
|
||||
} else if (resolved instanceof MultiplayerManager.ConnectionErrorException) {
|
||||
LOG.info("Failed to establish connection with server");
|
||||
reject.accept(i18n("multiplayer.session.join.error.connection"));
|
||||
return null;
|
||||
} else {
|
||||
LOG.log(Level.WARNING, "Failed to join session", resolved);
|
||||
reject.accept(i18n("multiplayer.session.join.error"));
|
||||
|
@ -295,7 +295,7 @@ public class MultiplayerPageSkin extends DecoratorAnimatedPage.DecoratorAnimated
|
||||
}
|
||||
}
|
||||
|
||||
private static String getNATType(DiscoveryInfo info) {
|
||||
public static String getNATType(DiscoveryInfo info) {
|
||||
if (info == null) {
|
||||
return i18n("multiplayer.nat.testing");
|
||||
} else if (info.isBlockedUDP()) {
|
||||
|
@ -669,6 +669,7 @@ multiplayer.session.expired=Multiplayer session has expired. You should re-creat
|
||||
multiplayer.session.hint=You must click "Open LAN Server" in game in order to enable multiplayer functionality.
|
||||
multiplayer.session.join=Join Session
|
||||
multiplayer.session.join.error=Failed to join multiplayer session
|
||||
multiplayer.session.join.error.connection=Failed to join multiplayer session. Cannot establish connection.
|
||||
multiplayer.session.join.hint=You must obtain the invitation code from the gamer who has already created a multiplayer session.
|
||||
multiplayer.session.join.invitation_code=Invitation code
|
||||
multiplayer.session.join.invitation_code.error=Incorrect invitation code. Please obtain invitation code from the player who creates the multiplayer session.
|
||||
|
@ -668,6 +668,7 @@ multiplayer.session.error.file_not_found=找不到 cato。請檢查防毒軟體
|
||||
multiplayer.session.expired=聯機會話連續使用時間超過了 3 小時,你需要重新創建/加入房間以繼續聯機。
|
||||
multiplayer.session.join=加入房間
|
||||
multiplayer.session.join.error=加入房間失敗
|
||||
multiplayer.session.join.error.connection=加入房間失敗。無法與對方建立連接。如果你或對方的網路類型是差(對稱型),可能無法使用聯機功能。
|
||||
multiplayer.session.join.hint=你需要向已經創建好房間的玩家索要邀請碼以便加入多人聯機房間
|
||||
multiplayer.session.join.invitation_code=邀請碼
|
||||
multiplayer.session.join.invitation_code.error=邀請碼不正確,請向開服玩家獲取邀請碼
|
||||
|
@ -669,6 +669,7 @@ multiplayer.session.error.file_not_found=找不到 cato。请检查杀毒软件
|
||||
multiplayer.session.expired=联机会话连续使用时间超过了 3 小时,你需要重新创建/加入房间以继续联机。
|
||||
multiplayer.session.join=加入房间
|
||||
multiplayer.session.join.error=加入房间失败。如果你或对方的网络类型是差(对称型),可能无法使用联机功能。
|
||||
multiplayer.session.join.error.connection=加入房间失败。无法与对方建立连接。如果你或对方的网络类型是差(对称型),可能无法使用联机功能。
|
||||
multiplayer.session.join.hint=你需要向已经创建好房间的玩家索要邀请码以便加入多人联机房间
|
||||
multiplayer.session.join.invitation_code=邀请码
|
||||
multiplayer.session.join.invitation_code.error=邀请码不正确,请向开服玩家获取邀请码
|
||||
|
Loading…
Reference in New Issue
Block a user