fix(multiplayer): show "failed to test" instead of "testing".

This commit is contained in:
huanghongxun 2021-10-30 22:40:44 +08:00
parent 7380423eee
commit c4941a01d6
6 changed files with 91 additions and 14 deletions

View File

@ -38,7 +38,9 @@ import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.ui.decorator.DecoratorAnimatedPage;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.util.HMCLService;
import org.jackhuang.hmcl.util.Result;
import org.jackhuang.hmcl.util.StringUtils;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.atomic.AtomicBoolean;
@ -58,7 +60,7 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
private final ObjectProperty<MultiplayerManager.State> multiplayerState = new SimpleObjectProperty<>(MultiplayerManager.State.DISCONNECTED);
private final ReadOnlyStringWrapper token = new ReadOnlyStringWrapper();
private final ReadOnlyObjectWrapper<DiscoveryInfo> natState = new ReadOnlyObjectWrapper<>();
private final ReadOnlyObjectWrapper<@Nullable Result<DiscoveryInfo>> natState = new ReadOnlyObjectWrapper<>();
private final ReadOnlyIntegerWrapper gamePort = new ReadOnlyIntegerWrapper(-1);
private final ReadOnlyObjectWrapper<MultiplayerManager.CatoSession> session = new ReadOnlyObjectWrapper<>();
private final ObservableList<MultiplayerChannel.CatoClient> clients = FXCollections.observableArrayList();
@ -97,11 +99,11 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
this.multiplayerState.set(multiplayerState);
}
public DiscoveryInfo getNatState() {
public Result<DiscoveryInfo> getNatState() {
return natState.get();
}
public ReadOnlyObjectProperty<DiscoveryInfo> natStateProperty() {
public ReadOnlyObjectProperty<Result<DiscoveryInfo>> natStateProperty() {
return natState.getReadOnlyProperty();
}
@ -134,12 +136,12 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
DiscoveryTest tester = new DiscoveryTest(null, 0, "stun.stunprotocol.org", 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);
natState.set(Result.ok(info));
} else {
natState.set(null);
natState.set(Result.error());
}
LOG.log(Level.INFO, "Nat test result " + MultiplayerPageSkin.getNATType(natState.get()), exception);
}).start();
}
@ -506,4 +508,5 @@ public class MultiplayerPage extends DecoratorAnimatedPage implements DecoratorP
public ReadOnlyObjectProperty<State> stateProperty() {
return state;
}
}

View File

@ -41,8 +41,10 @@ import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.ui.decorator.DecoratorAnimatedPage;
import org.jackhuang.hmcl.ui.versions.Versions;
import org.jackhuang.hmcl.util.HMCLService;
import org.jackhuang.hmcl.util.Result;
import org.jackhuang.hmcl.util.javafx.BindingMapping;
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
import org.jetbrains.annotations.Nullable;
import static org.jackhuang.hmcl.setting.ConfigHolder.globalConfig;
import static org.jackhuang.hmcl.ui.versions.VersionPage.wrap;
@ -295,22 +297,24 @@ public class MultiplayerPageSkin extends DecoratorAnimatedPage.DecoratorAnimated
}
}
public static String getNATType(DiscoveryInfo info) {
public static String getNATType(@Nullable Result<DiscoveryInfo> info) {
if (info == null) {
return i18n("multiplayer.nat.testing");
} else if (info.isBlockedUDP()) {
} else if (info.isError()) {
return i18n("multiplayer.nat.failed");
} else if (info.get().isBlockedUDP()) {
return i18n("multiplayer.nat.type.blocked_udp");
} else if (info.isFullCone()) {
} else if (info.get().isFullCone()) {
return i18n("multiplayer.nat.type.full_cone");
} else if (info.isOpenAccess()) {
} else if (info.get().isOpenAccess()) {
return i18n("multiplayer.nat.type.open_access");
} else if (info.isPortRestrictedCone()) {
} else if (info.get().isPortRestrictedCone()) {
return i18n("multiplayer.nat.type.port_restricted_cone");
} else if (info.isRestrictedCone()) {
} else if (info.get().isRestrictedCone()) {
return i18n("multiplayer.nat.type.restricted_cone");
} else if (info.isSymmetric()) {
} else if (info.get().isSymmetric()) {
return i18n("multiplayer.nat.type.symmetric");
} else if (info.isSymmetricUDPFirewall()) {
} else if (info.get().isSymmetricUDPFirewall()) {
return i18n("multiplayer.nat.type.symmetric_udp_firewall");
} else {
return i18n("multiplayer.nat.type.unknown");

View File

@ -654,6 +654,7 @@ multiplayer.exit.timeout.static_token=Failed to connect to multiplayer server. P
multiplayer.exit.timeout.dynamic_token=Failed to connect to multiplayer server.
multiplayer.hint=Multiplayer functionality is experimental. Please give feedback.
multiplayer.nat=Network Type Detection
multiplayer.nat.failed=Failed to detect network type.
multiplayer.nat.hint=Network type detection will make it clear whether your network fulfills our requirement for multiplayer mode.
multiplayer.nat.latency=Latency
multiplayer.nat.not_yet_tested=Not yet testsed

View File

@ -654,6 +654,7 @@ multiplayer.exit.timeout.static_token=無法連接多人聯機服務,請你切
multiplayer.exit.timeout.dynamic_token=無法連接多人聯機服務,你可以在多人聯機頁面的回饋中回饋問題。
multiplayer.hint=多人聯機功能處於實驗階段,如果有問題請回饋。
multiplayer.nat=網路檢測
multiplayer.nat.failed=檢測失敗,但你仍然可以繼續使用聯機功能。
multiplayer.nat.hint=執行網路檢測可以讓你更清楚你的網路狀況是否符合聯機功能的需求。不符合聯機功能運行條件的網路狀況將可能導致聯機失敗。
multiplayer.nat.latency=延遲
multiplayer.nat.not_yet_tested=尚未檢測

View File

@ -654,6 +654,7 @@ multiplayer.exit.timeout.static_token=无法连接多人联机服务,请你切
multiplayer.exit.timeout.dynamic_token=无法连接多人联机服务,你可以在多人联机页面的反馈中反馈问题。
multiplayer.hint=多人联机功能处于实验阶段,如果有问题请反馈。
multiplayer.nat=网络检测
multiplayer.nat.failed=检测失败,但你仍然可以继续使用联机功能。
multiplayer.nat.hint=执行网络检测可以让你更清楚你的网络状况是否符合联机功能的需求。检测结果为差的网络可能导致联机失败。
multiplayer.nat.latency=延迟
multiplayer.nat.not_yet_tested=尚未检测

View File

@ -0,0 +1,67 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util;
import java.util.Objects;
public abstract class Result<T> {
public T get() {
throw new IllegalStateException("TriState not ok");
}
public boolean isOK() {
return false;
}
public boolean isError() {
return false;
}
public static <T> Result<T> ok(T result) {
return new OK<>(Objects.requireNonNull(result));
}
@SuppressWarnings("unchecked")
public static <T> Result<T> error() {
return (Result<T>) Error.INSTANCE;
}
private static class OK<T> extends Result<T> {
private final T result;
public OK(T result) {
this.result = result;
}
@Override
public T get() {
return result;
}
}
private static class Error<T> extends Result<T> {
public static final Error<Void> INSTANCE = new Error<>();
@Override
public boolean isError() {
return true;
}
}
}