diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.cpp index fcc2e1d2d16..adf4f1225c6 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.cpp @@ -9,6 +9,35 @@ extern void OnKickedFromLobby(); extern NGMPGame* TheNGMPGame; +namespace +{ + std::string ResolveLobbyMapPath(const std::string& relativeMapPath, bool isOfficial) + { + const std::string systemMapPath = std::format("maps\\{}", relativeMapPath); + if (isOfficial) + { + return systemMapPath; + } + + // Match retail map-list precedence: an unofficial map packaged under Maps wins an + // ambiguous collision with a map of the same name in the user map directory. + const MapMetaData* systemMapData = TheMapCache->findMap(AsciiString(systemMapPath.c_str())); + if (systemMapData != nullptr && !systemMapData->m_isOfficial) + { + return systemMapPath; + } + + const std::string userMapPath = std::format("{}\\{}", TheMapCache->getUserMapDir(true).str(), relativeMapPath); + if (TheMapCache->findMap(AsciiString(userMapPath.c_str())) != nullptr) + { + return userMapPath; + } + + // Preserve the existing missing-map path so normal custom-map transfer behavior is unchanged. + return userMapPath; + } +} + struct JoinLobbyResponse { bool success = false; @@ -595,15 +624,7 @@ void NGMP_OnlineServices_LobbyInterface::SearchForLobbies(std::function } ++latencyIndex; - // correct map path - if (lobbyEntry.map_official) - { - lobbyEntry.map_path = std::format("maps\\{}", lobbyEntry.map_path.c_str()); - } - else - { - lobbyEntry.map_path = std::format("{}\\{}", TheMapCache->getUserMapDir(true).str(), lobbyEntry.map_path.c_str()); - } + lobbyEntry.map_path = ResolveLobbyMapPath(lobbyEntry.map_path, lobbyEntry.map_official); // NOTE: These fields won't be present becauase they're private properties //memberEntryIter["enc_key"].get_to(strEncKey); @@ -858,19 +879,7 @@ void NGMP_OnlineServices_LobbyInterface::UpdateRoomDataCache(std::functiongetUserMapDir(true); - strUserMapDIr.toLower(); - - lobbyEntry.map_path = std::format("{}\\{}", strUserMapDIr.str(), lobbyEntry.map_path.c_str()); - } + lobbyEntry.map_path = ResolveLobbyMapPath(lobbyEntry.map_path, lobbyEntry.map_official); // did the map change? cache that we need to reset and transmit our ready state bool bNeedsHasMapUpdate = false;