From 568c968c4e00e97e370ff013fbd22da4502c0ba2 Mon Sep 17 00:00:00 2001 From: Subsonic154 Date: Tue, 10 Mar 2026 05:03:53 -0400 Subject: [PATCH] Fix failure to connect to world on routers that lack Hairpin NAT support when connecting from the same network. --- src/main/resources/application.conf | 3 +++ src/main/scala/net/psforever/actors/net/LoginActor.scala | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 20885b9e5..ba20ca933 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -4,6 +4,9 @@ bind = 127.0.0.1 # The public host name or IP address. Used to forward clients from the login # server to the world server. The default value will only allow local connections. +# If you encounter issues trying to connect to the world from machines on the same network (or the same machine when this is not the default value) +# when hosting a public server with a router that lacks Hairpin NAT support, make sure the hosts file on this system +# has the host name of the system set to resolve to it's local IP address on the network. public = 127.0.0.1 # Login server configuration diff --git a/src/main/scala/net/psforever/actors/net/LoginActor.scala b/src/main/scala/net/psforever/actors/net/LoginActor.scala index abfc9c900..4d0a0c0e8 100644 --- a/src/main/scala/net/psforever/actors/net/LoginActor.scala +++ b/src/main/scala/net/psforever/actors/net/LoginActor.scala @@ -97,6 +97,7 @@ class LoginActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], conne private val serverName: String = Config.app.world.serverName private val gameTestServerAddress = new InetSocketAddress(InetAddress.getByName(Config.app.public), Config.app.world.port) + private val localHost: InetAddress = InetAddress.getLocalHost private val bcryptRounds = 12 @@ -152,7 +153,7 @@ class LoginActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], conne updateServerList() case SocketPane.NextPort(_, _, portNum) => - val address = gameTestServerAddress.getAddress.getHostAddress + val address = if (ipAddress == "127.0.0.1") ipAddress else if (ipAddress.startsWith("192.168")) localHost.getHostAddress else gameTestServerAddress.getAddress.getHostAddress log.info(s"Connecting to ${address.toLowerCase}: $portNum ...") val response = ConnectToWorldMessage(serverName, address, portNum) context.become(idlingBehavior) @@ -165,7 +166,7 @@ class LoginActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], conne private def waitingForServerTransferBehavior: Receive = persistentSetupMixinBehavior.orElse { case SocketPane.NextPort(_, _, portNum) => - val address = gameTestServerAddress.getAddress.getHostAddress + val address = if (ipAddress == "127.0.0.1") ipAddress else if (ipAddress.startsWith("192.168")) localHost.getHostAddress else gameTestServerAddress.getAddress.getHostAddress log.info(s"Connecting to ${address.toLowerCase}: $portNum ...") val response = ConnectToWorldMessage(serverName, address, portNum) context.become(idlingBehavior)