mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Added a new Couldnt connect to server error message
Re wrote the URL parsing logic again, but due to increased complexity put it into a utility class Fixed desktop version opening up a lobby even when it did not connect to a server Wired up the new error message to mobile, and both error messages to Desktop
This commit is contained in:
@@ -3,6 +3,7 @@ package forge.screens.home.online;
|
|||||||
import java.net.BindException;
|
import java.net.BindException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -16,12 +17,14 @@ import forge.gui.error.BugReporter;
|
|||||||
import forge.gui.framework.EDocID;
|
import forge.gui.framework.EDocID;
|
||||||
import forge.gui.framework.ICDoc;
|
import forge.gui.framework.ICDoc;
|
||||||
import forge.gui.util.SOptionPane;
|
import forge.gui.util.SOptionPane;
|
||||||
|
import forge.localinstance.properties.ForgeConstants;
|
||||||
import forge.menus.IMenuProvider;
|
import forge.menus.IMenuProvider;
|
||||||
import forge.menus.MenuUtil;
|
import forge.menus.MenuUtil;
|
||||||
import forge.screens.home.CHomeUI;
|
import forge.screens.home.CHomeUI;
|
||||||
import forge.screens.home.CLobby;
|
import forge.screens.home.CLobby;
|
||||||
import forge.screens.home.VLobby;
|
import forge.screens.home.VLobby;
|
||||||
import forge.screens.home.sanctioned.ConstructedGameMenu;
|
import forge.screens.home.sanctioned.ConstructedGameMenu;
|
||||||
|
import forge.toolbox.FOptionPane;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
|
|
||||||
public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
||||||
@@ -39,7 +42,7 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
|||||||
if (url == null) { return; }
|
if (url == null) { return; }
|
||||||
|
|
||||||
FThreads.invokeInBackgroundThread(() -> {
|
FThreads.invokeInBackgroundThread(() -> {
|
||||||
if (url.length() > 0) {
|
if (!url.isEmpty()) {
|
||||||
join(url);
|
join(url);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -83,16 +86,23 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final ChatMessage result = NetConnectUtil.join(url, VSubmenuOnlineLobby.SINGLETON_INSTANCE, FNetOverlay.SINGLETON_INSTANCE);
|
final ChatMessage result = NetConnectUtil.join(url, VSubmenuOnlineLobby.SINGLETON_INSTANCE, FNetOverlay.SINGLETON_INSTANCE);
|
||||||
|
if(Objects.equals(result.getMessage(), ForgeConstants.CLOSE_CONN_COMMAND)) {
|
||||||
SwingUtilities.invokeLater(() -> {
|
FOptionPane.showErrorDialog(Localizer.getInstance().getMessage("UnableConnectToServer", url));
|
||||||
SOverlayUtils.hideOverlay();
|
SOverlayUtils.hideOverlay();
|
||||||
if (result instanceof ChatMessage) {
|
} else if (Objects.equals(result.getMessage(), ForgeConstants.INVALID_HOST_COMMAND)) {
|
||||||
FNetOverlay.SINGLETON_INSTANCE.show(result);
|
FOptionPane.showErrorDialog(Localizer.getInstance().getMessage("lblDetectedInvalidHostAddress", url));
|
||||||
if (CHomeUI.SINGLETON_INSTANCE.getCurrentDocID() == EDocID.HOME_NETWORK) {
|
SOverlayUtils.hideOverlay();
|
||||||
VSubmenuOnlineLobby.SINGLETON_INSTANCE.populate();
|
} else {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
SOverlayUtils.hideOverlay();
|
||||||
|
if (result instanceof ChatMessage) {
|
||||||
|
FNetOverlay.SINGLETON_INSTANCE.show(result);
|
||||||
|
if (CHomeUI.SINGLETON_INSTANCE.getCurrentDocID() == EDocID.HOME_NETWORK) {
|
||||||
|
VSubmenuOnlineLobby.SINGLETON_INSTANCE.populate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -108,6 +108,9 @@ public class OnlineLobbyScreen extends LobbyScreen implements IOnlineLobby {
|
|||||||
if (joinServer) {
|
if (joinServer) {
|
||||||
result[0] = NetConnectUtil.join(url, OnlineLobbyScreen.this, chatInterface);
|
result[0] = NetConnectUtil.join(url, OnlineLobbyScreen.this, chatInterface);
|
||||||
if (result[0].getMessage() == ForgeConstants.CLOSE_CONN_COMMAND) { //this message is returned via netconnectutil on exception
|
if (result[0].getMessage() == ForgeConstants.CLOSE_CONN_COMMAND) { //this message is returned via netconnectutil on exception
|
||||||
|
closeConn(Forge.getLocalizer().getMessage("UnableConnectToServer", url));
|
||||||
|
return;
|
||||||
|
} else if (result[0].getMessage() == ForgeConstants.INVALID_HOST_COMMAND) {
|
||||||
closeConn(Forge.getLocalizer().getMessage("lblDetectedInvalidHostAddress", url));
|
closeConn(Forge.getLocalizer().getMessage("lblDetectedInvalidHostAddress", url));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ OKresetWorkshopLayout=Workshop-Layout wurde zurückgesetzt.
|
|||||||
AresetMatchScreenLayout=Dies wird das Spielfeldlayout zurücksetzen.\nFalls du vorher noch das derzeitige Layout speichern möchtest, nutze bitte Forge->Layout->File->Save Current Layout in einem laufenden Spiel.\n\nSpielfeldlayout zurücksetzen?
|
AresetMatchScreenLayout=Dies wird das Spielfeldlayout zurücksetzen.\nFalls du vorher noch das derzeitige Layout speichern möchtest, nutze bitte Forge->Layout->File->Save Current Layout in einem laufenden Spiel.\n\nSpielfeldlayout zurücksetzen?
|
||||||
TresetMatchScreenLayout=Spielfeldlayout zurücksetzen
|
TresetMatchScreenLayout=Spielfeldlayout zurücksetzen
|
||||||
OKresetMatchScreenLayout=Spielfeldlayout wurde zurückgesetzt.
|
OKresetMatchScreenLayout=Spielfeldlayout wurde zurückgesetzt.
|
||||||
|
UnableConnectToServer=Unable to connect to server with host {0}.
|
||||||
#EMenuGroup.java
|
#EMenuGroup.java
|
||||||
lblSanctionedFormats=Gültige Spielformate
|
lblSanctionedFormats=Gültige Spielformate
|
||||||
lblOnlineMultiplayer=Mehrspieler (online)
|
lblOnlineMultiplayer=Mehrspieler (online)
|
||||||
|
|||||||
@@ -283,6 +283,7 @@ OKresetWorkshopLayout=Workshop layout has been reset.
|
|||||||
AresetMatchScreenLayout=This will reset the layout of the Match screen.\n If you want to save the current layout first, please use the Dock tab -> Save Layout option in the Match screen.\n\n Reset layout?
|
AresetMatchScreenLayout=This will reset the layout of the Match screen.\n If you want to save the current layout first, please use the Dock tab -> Save Layout option in the Match screen.\n\n Reset layout?
|
||||||
TresetMatchScreenLayout=Reset Match Screen Layout
|
TresetMatchScreenLayout=Reset Match Screen Layout
|
||||||
OKresetMatchScreenLayout=Match Screen layout has been reset.
|
OKresetMatchScreenLayout=Match Screen layout has been reset.
|
||||||
|
UnableConnectToServer=Unable to connect to server with host {0}.
|
||||||
#EMenuGroup.java
|
#EMenuGroup.java
|
||||||
lblSanctionedFormats=Sanctioned Formats
|
lblSanctionedFormats=Sanctioned Formats
|
||||||
lblOnlineMultiplayer=Online Multiplayer
|
lblOnlineMultiplayer=Online Multiplayer
|
||||||
|
|||||||
@@ -283,6 +283,7 @@ OKresetWorkshopLayout=El diseño del taller se ha restablecido.
|
|||||||
AresetMatchScreenLayout=Esto restablecerá el diseño de la pantalla de juego.\n Si desea guardar primero el diseño actual, use la pestaña Dock -> Guardar opción de diseño en la pantalla de Juego\n \n ¿Restablecer diseño?
|
AresetMatchScreenLayout=Esto restablecerá el diseño de la pantalla de juego.\n Si desea guardar primero el diseño actual, use la pestaña Dock -> Guardar opción de diseño en la pantalla de Juego\n \n ¿Restablecer diseño?
|
||||||
TresetMatchScreenLayout=Restablecer diseño de pantalla de juego
|
TresetMatchScreenLayout=Restablecer diseño de pantalla de juego
|
||||||
OKresetMatchScreenLayout=El diseño de la pantalla de juego se ha restablecido.
|
OKresetMatchScreenLayout=El diseño de la pantalla de juego se ha restablecido.
|
||||||
|
UnableConnectToServer=Unable to connect to server with host {0}.
|
||||||
#EMenuGroup.java
|
#EMenuGroup.java
|
||||||
lblSanctionedFormats=Formatos oficiales
|
lblSanctionedFormats=Formatos oficiales
|
||||||
lblOnlineMultiplayer=Multijugador online
|
lblOnlineMultiplayer=Multijugador online
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ OKresetWorkshopLayout=La disposition de l'atelier a été réinitialisée.
|
|||||||
AresetMatchScreenLayout=Ceci réinitialisera la mise en page de l'écran Match.\n Si vous souhaitez d'abord enregistrer la mise en page actuelle, veuillez utiliser l'onglet Dock -> Enregistrer la mise en page dans l'écran Match.\n\n Réinitialiser la mise en page ?
|
AresetMatchScreenLayout=Ceci réinitialisera la mise en page de l'écran Match.\n Si vous souhaitez d'abord enregistrer la mise en page actuelle, veuillez utiliser l'onglet Dock -> Enregistrer la mise en page dans l'écran Match.\n\n Réinitialiser la mise en page ?
|
||||||
TresetMatchScreenLayout=Réinitialiser la disposition de l'écran de correspondance
|
TresetMatchScreenLayout=Réinitialiser la disposition de l'écran de correspondance
|
||||||
OKresetMatchScreenLayout=La disposition de l'écran de correspondance a été réinitialisée.
|
OKresetMatchScreenLayout=La disposition de l'écran de correspondance a été réinitialisée.
|
||||||
|
UnableConnectToServer=Unable to connect to server with host {0}.
|
||||||
#EMenuGroup.java
|
#EMenuGroup.java
|
||||||
lblSanctionedFormats=Formats autorisés
|
lblSanctionedFormats=Formats autorisés
|
||||||
lblOnlineMultiplayer=Multijoueur en ligne
|
lblOnlineMultiplayer=Multijoueur en ligne
|
||||||
|
|||||||
@@ -280,6 +280,7 @@ OKresetWorkshopLayout=Il layout dell'officina è stato ripristinato.
|
|||||||
AresetMatchScreenLayout=Ciò ripristinerà il layout della schermata degli incontri. \n Se si desidera prima salvare il layout corrente, utilizzare la scheda Comandi -> opzione Salva layout della schermata di gioco. \n \n Ripristinare layout?
|
AresetMatchScreenLayout=Ciò ripristinerà il layout della schermata degli incontri. \n Se si desidera prima salvare il layout corrente, utilizzare la scheda Comandi -> opzione Salva layout della schermata di gioco. \n \n Ripristinare layout?
|
||||||
TresetMatchScreenLayout=Ripristina il layout della schermata degli incontri
|
TresetMatchScreenLayout=Ripristina il layout della schermata degli incontri
|
||||||
OKresetMatchScreenLayout=Il layout della schermata degli incontri è stato ripristinato.
|
OKresetMatchScreenLayout=Il layout della schermata degli incontri è stato ripristinato.
|
||||||
|
UnableConnectToServer=Unable to connect to server with host {0}.
|
||||||
#EMenuGroup.java
|
#EMenuGroup.java
|
||||||
lblSanctionedFormats=Formati sanzionati
|
lblSanctionedFormats=Formati sanzionati
|
||||||
lblOnlineMultiplayer=Multigiocatore online
|
lblOnlineMultiplayer=Multigiocatore online
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ OKresetWorkshopLayout=ワークショップレイアウトのリセットされ
|
|||||||
AresetMatchScreenLayout=これにより、試合画面のレイアウトがリセットされます。\n 現在のレイアウトを最初に保存する場合は、[Dock]タブ-> [レイアウトの保存]オプションを[一致]画面で使用してください。\n\n レイアウトをリセットしますか?
|
AresetMatchScreenLayout=これにより、試合画面のレイアウトがリセットされます。\n 現在のレイアウトを最初に保存する場合は、[Dock]タブ-> [レイアウトの保存]オプションを[一致]画面で使用してください。\n\n レイアウトをリセットしますか?
|
||||||
TresetMatchScreenLayout=試合画面レイアウトのリセット
|
TresetMatchScreenLayout=試合画面レイアウトのリセット
|
||||||
OKresetMatchScreenLayout=試合画面のレイアウトがリセットされました。
|
OKresetMatchScreenLayout=試合画面のレイアウトがリセットされました。
|
||||||
|
UnableConnectToServer=Unable to connect to server with host {0}.
|
||||||
#EMenuGroup.java
|
#EMenuGroup.java
|
||||||
lblSanctionedFormats=フォーマット
|
lblSanctionedFormats=フォーマット
|
||||||
lblOnlineMultiplayer=オンラインマルチプレイ
|
lblOnlineMultiplayer=オンラインマルチプレイ
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ AresetMatchScreenLayout=Isso irá redefinir o layout da tela da Partida.\n\
|
|||||||
Redefinir o layout?
|
Redefinir o layout?
|
||||||
TresetMatchScreenLayout=Redefinir Layout da Partida
|
TresetMatchScreenLayout=Redefinir Layout da Partida
|
||||||
OKresetMatchScreenLayout=O layout da Tela da Partida foi redefinido.
|
OKresetMatchScreenLayout=O layout da Tela da Partida foi redefinido.
|
||||||
|
UnableConnectToServer=Unable to connect to server with host {0}.
|
||||||
#EMenuGroup.java
|
#EMenuGroup.java
|
||||||
lblSanctionedFormats=Formatos Sancionados
|
lblSanctionedFormats=Formatos Sancionados
|
||||||
lblOnlineMultiplayer=Multijogador Online
|
lblOnlineMultiplayer=Multijogador Online
|
||||||
|
|||||||
@@ -283,6 +283,7 @@ OKresetWorkshopLayout=游戏界面已重置
|
|||||||
AresetMatchScreenLayout=这将重置匹配屏幕的布局。\n如果要保存当前的布局,请使用“匹配”屏幕中的“保存布局”选项。\n\n重置布局?
|
AresetMatchScreenLayout=这将重置匹配屏幕的布局。\n如果要保存当前的布局,请使用“匹配”屏幕中的“保存布局”选项。\n\n重置布局?
|
||||||
TresetMatchScreenLayout=重置匹配布局
|
TresetMatchScreenLayout=重置匹配布局
|
||||||
OKresetMatchScreenLayout=匹配布局已重置。
|
OKresetMatchScreenLayout=匹配布局已重置。
|
||||||
|
UnableConnectToServer=Unable to connect to server with host {0}.
|
||||||
#EMenuGroup.java
|
#EMenuGroup.java
|
||||||
lblSanctionedFormats=单人游戏
|
lblSanctionedFormats=单人游戏
|
||||||
lblOnlineMultiplayer=多人联机
|
lblOnlineMultiplayer=多人联机
|
||||||
|
|||||||
@@ -21,9 +21,10 @@ import forge.localinstance.properties.ForgePreferences.FPref;
|
|||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.player.GamePlayerUtil;
|
import forge.player.GamePlayerUtil;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
|
import forge.util.URLValidator;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.net.URI;
|
import static forge.util.URLValidator.parseURL;
|
||||||
|
|
||||||
public class NetConnectUtil {
|
public class NetConnectUtil {
|
||||||
private NetConnectUtil() { }
|
private NetConnectUtil() { }
|
||||||
@@ -125,21 +126,17 @@ public class NetConnectUtil {
|
|||||||
public static ChatMessage join(final String url, final IOnlineLobby onlineLobby, final IOnlineChatInterface chatInterface) {
|
public static ChatMessage join(final String url, final IOnlineLobby onlineLobby, final IOnlineChatInterface chatInterface) {
|
||||||
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
||||||
String hostname;
|
String hostname;
|
||||||
int port = ForgeConstants.DEFAULT_SERVER_CONNECTION_PORT;
|
int port;
|
||||||
|
|
||||||
try {
|
URLValidator.HostPort hostPort = parseURL(url);
|
||||||
// Check if the URL already has a protocol
|
if(hostPort == null) {
|
||||||
String formattedUrl = url.matches("^[a-zA-Z][a-zA-Z0-9+.-]*://.*") ? url : "http://" + url;
|
return new ChatMessage(null, ForgeConstants.INVALID_HOST_COMMAND);
|
||||||
// Parse the URI
|
|
||||||
URI uri = new URI(formattedUrl);
|
|
||||||
hostname = uri.getHost();
|
|
||||||
if (uri.getPort() != -1) { // If a port is specified in the URL
|
|
||||||
port = uri.getPort();
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
hostname = url; // Fallback to original URL if parsing fails
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hostname = hostPort.host();
|
||||||
|
port = hostPort.port();
|
||||||
|
if(port == -1) port = ForgeConstants.DEFAULT_SERVER_CONNECTION_PORT;
|
||||||
|
|
||||||
|
|
||||||
final FGameClient client = new FGameClient(FModel.getPreferences().getPref(FPref.PLAYER_NAME), "0", gui, hostname, port);
|
final FGameClient client = new FGameClient(FModel.getPreferences().getPref(FPref.PLAYER_NAME), "0", gui, hostname, port);
|
||||||
onlineLobby.setClient(client);
|
onlineLobby.setClient(client);
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ public final class ForgeConstants {
|
|||||||
public static final String CONQUEST_PREFS_FILE = USER_PREFS_DIR + "conquest.preferences";
|
public static final String CONQUEST_PREFS_FILE = USER_PREFS_DIR + "conquest.preferences";
|
||||||
public static final String ITEM_VIEW_PREFS_FILE = USER_PREFS_DIR + "item_view.preferences";
|
public static final String ITEM_VIEW_PREFS_FILE = USER_PREFS_DIR + "item_view.preferences";
|
||||||
public static final String CLOSE_CONN_COMMAND = "<<_EM_ESOLC_<<";
|
public static final String CLOSE_CONN_COMMAND = "<<_EM_ESOLC_<<";
|
||||||
|
public static final String INVALID_HOST_COMMAND = "<<_TSOH_DILAVNI_<<";
|
||||||
|
|
||||||
// data that has defaults in the program dir but overrides/additions in the user dir
|
// data that has defaults in the program dir but overrides/additions in the user dir
|
||||||
private static final String _DEFAULTS_DIR = RES_DIR + "defaults" + PATH_SEPARATOR;
|
private static final String _DEFAULTS_DIR = RES_DIR + "defaults" + PATH_SEPARATOR;
|
||||||
|
|||||||
52
forge-gui/src/main/java/forge/util/URLValidator.java
Normal file
52
forge-gui/src/main/java/forge/util/URLValidator.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package forge.util;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class URLValidator {
|
||||||
|
|
||||||
|
private static final Pattern DOMAIN_NAME_PATTERN = Pattern.compile("^(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\\.[A-Za-z]{2,})+$");
|
||||||
|
|
||||||
|
public static HostPort parseIP(String ip) {
|
||||||
|
String[] parts = ip.split("\\.");
|
||||||
|
if (parts.length != 4) return null;
|
||||||
|
for (String part : parts) {
|
||||||
|
try {
|
||||||
|
int num = Integer.parseInt(part);
|
||||||
|
if (num < 0 || num > 255) return null;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new HostPort(ip, null); // No port for raw IP
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static HostPort parseURL(String url) {
|
||||||
|
try {
|
||||||
|
//prepend http:// if a protocol is missing so URI parsing does not fail
|
||||||
|
String formattedUrl = url.matches("^[a-zA-Z][a-zA-Z0-9+.-]*://.*") ? url : "http://" + url;
|
||||||
|
URI uri = new URI(formattedUrl);
|
||||||
|
String host = uri.getHost();
|
||||||
|
int port = uri.getPort(); // Returns -1 if port is not specified
|
||||||
|
if (host == null) return null;
|
||||||
|
HostPort hostPort;
|
||||||
|
if (parseIP(host) != null) {
|
||||||
|
hostPort = new HostPort(host, port == -1 ? null : port);
|
||||||
|
} else if (DOMAIN_NAME_PATTERN.matcher(host).matches()) {
|
||||||
|
hostPort = new HostPort(host, port == -1 ? null : port);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return hostPort;
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//This is fine, Records were introduced in Java 16, its essentially a DTO class with implicit getters and constructors
|
||||||
|
public record HostPort(String host, Integer port) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user