Add relay daemon mode to lobby_connect.

This (along with the existing custom_broadcasts support) allows for users on different read: _routed_ subnets to see and connect to each other's games.

To use this mode:

Build lobby_connect and run it with the "-d" argument.

Create the custom_broadcasts.txt file in the steam_settings folder next to steam_api.dll / steam_api64.dll and put the IP address of the host running lobby_connect in it.

Run games.

Note: This should even work with existing installations, _provided_ that at least one of them creates the custom_broadcasts.txt file as described above.
(This is because existing installations use broadcast packets to establish new connections, forwarding all of their knowledge to each other.
 Thus having at least one host on the current subnet configured in this new way turns it into a "proxy" for the other hosts.)

Caveat: This will _NOT_ work if NAT is involved. This is due to the lack of NAT traversal support in the emu.
(I.e. The lobby_connect daemon will get the info from the NAT'ed hosts and forward it to the others, but hosts outside the NAT won't be able to connect.)

Signed-off-by: redpolline <11156324-redpolline@users.noreply.gitlab.com>
This commit is contained in:
redpolline 2024-01-10 04:30:17 -05:00
parent 98488d6570
commit d1a0a68d4f

View file

@ -32,93 +32,113 @@
#else
#endif
int main() {
int main(int argc, char ** argv) {
bool broadcast_relay_daemon = false;
if (argc > 1) {
for (int x = 1; x < argc; x++) {
if (strcmp(argv[x], "-d") == 0) {
broadcast_relay_daemon = true;
}
}
}
if (SteamAPI_Init()) {
//Set appid to: LOBBY_CONNECT_APPID
SteamAPI_RestartAppIfNecessary(LOBBY_CONNECT_APPID);
std::cout << "This is a program to find lobbies and run the game with lobby connect parameters" << std::endl;
std::cout << "Api initialized, ";
if (broadcast_relay_daemon) {
std::cout << "Running in relay daemon mode. Press Ctrl+C to exit...." << std::endl;
std::cout.flush();
while (1) {
SteamAPI_RunCallbacks();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
} else {
std::cout << "This is a program to find lobbies and run the game with lobby connect parameters" << std::endl;
std::cout << "Api initialized, ";
top:
std::cout << "waiting a few seconds for connections:" << std::endl;
for (int i = 0; i < 10; ++i) {
SteamAPI_RunCallbacks();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
std::cout << "waiting a few seconds for connections:" << std::endl;
for (int i = 0; i < 10; ++i) {
SteamAPI_RunCallbacks();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
int friend_count = SteamFriends()->GetFriendCount(k_EFriendFlagAll);
std::cout << "People on the network: " << friend_count << std::endl;
for (int i = 0; i < friend_count; ++i) {
CSteamID id = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll);
const char *name = SteamFriends()->GetFriendPersonaName(id);
int friend_count = SteamFriends()->GetFriendCount(k_EFriendFlagAll);
std::cout << "People on the network: " << friend_count << std::endl;
for (int i = 0; i < friend_count; ++i) {
CSteamID id = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll);
const char *name = SteamFriends()->GetFriendPersonaName(id);
FriendGameInfo_t friend_info = {};
SteamFriends()->GetFriendGamePlayed(id, &friend_info);
std::cout << name << " is playing: " << friend_info.m_gameID.AppID() << std::endl;
}
FriendGameInfo_t friend_info = {};
SteamFriends()->GetFriendGamePlayed(id, &friend_info);
std::cout << name << " is playing: " << friend_info.m_gameID.AppID() << std::endl;
}
std::cout << std::endl << "--------------Menu-------------" << std::endl << "\tappid\tname\tcommand line" << std::endl;
std::cout << std::endl << "--------------Menu-------------" << std::endl << "\tappid\tname\tcommand line" << std::endl;
std::vector<std::string> arguments;
for (int i = 0; i < friend_count; ++i) {
CSteamID id = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll);
const char *name = SteamFriends()->GetFriendPersonaName(id);
const char *connect = SteamFriends()->GetFriendRichPresence( id, "connect");
FriendGameInfo_t friend_info = {};
SteamFriends()->GetFriendGamePlayed(id, &friend_info);
std::vector<std::string> arguments;
for (int i = 0; i < friend_count; ++i) {
CSteamID id = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll);
const char *name = SteamFriends()->GetFriendPersonaName(id);
const char *connect = SteamFriends()->GetFriendRichPresence( id, "connect");
FriendGameInfo_t friend_info = {};
SteamFriends()->GetFriendGamePlayed(id, &friend_info);
if (strlen(connect) > 0) {
std::cout << arguments.size() << "\t" << friend_info.m_gameID.AppID() << "\t" << name << "\t" << connect << std::endl;
arguments.push_back(connect);
} else {
if (friend_info.m_steamIDLobby != k_steamIDNil) {
std::string connect = "+connect_lobby " + std::to_string(friend_info.m_steamIDLobby.ConvertToUint64());
if (strlen(connect) > 0) {
std::cout << arguments.size() << "\t" << friend_info.m_gameID.AppID() << "\t" << name << "\t" << connect << std::endl;
arguments.push_back(connect);
} else {
if (friend_info.m_steamIDLobby != k_steamIDNil) {
std::string connect = "+connect_lobby " + std::to_string(friend_info.m_steamIDLobby.ConvertToUint64());
std::cout << arguments.size() << "\t" << friend_info.m_gameID.AppID() << "\t" << name << "\t" << connect << std::endl;
arguments.push_back(connect);
}
}
}
}
std::cout << arguments.size() << ": Retry." << std::endl;
std::cout << std::endl << "Enter the number corresponding to your choice then press Enter." << std::endl;
unsigned int choice;
std::cin >> choice;
std::cout << arguments.size() << ": Retry." << std::endl;
std::cout << std::endl << "Enter the number corresponding to your choice then press Enter." << std::endl;
unsigned int choice;
std::cin >> choice;
if (choice >= arguments.size()) goto top;
if (choice >= arguments.size()) goto top;
#ifdef _WIN32
std::cout << "starting the game with: " << arguments[choice] << std::endl << "Please select the game exe" << std::endl;
std::cout << "starting the game with: " << arguments[choice] << std::endl << "Please select the game exe" << std::endl;
OPENFILENAMEA ofn;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = 0;
ofn.lpstrFilter = "Exe Files (*.exe)\0*.exe\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "txt";
if(GetOpenFileNameA(&ofn))
{
std::string filename = szFileName;
filename = "\"" + filename + "\" " + arguments[choice];
std::cout << filename << std::endl;
STARTUPINFOA lpStartupInfo;
PROCESS_INFORMATION lpProcessInfo;
OPENFILENAMEA ofn;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = 0;
ofn.lpstrFilter = "Exe Files (*.exe)\0*.exe\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "txt";
if(GetOpenFileNameA(&ofn))
{
std::string filename = szFileName;
filename = "\"" + filename + "\" " + arguments[choice];
std::cout << filename << std::endl;
STARTUPINFOA lpStartupInfo;
PROCESS_INFORMATION lpProcessInfo;
ZeroMemory( &lpStartupInfo, sizeof( lpStartupInfo ) );
lpStartupInfo.cb = sizeof( lpStartupInfo );
ZeroMemory( &lpProcessInfo, sizeof( lpProcessInfo ) );
ZeroMemory( &lpStartupInfo, sizeof( lpStartupInfo ) );
lpStartupInfo.cb = sizeof( lpStartupInfo );
ZeroMemory( &lpProcessInfo, sizeof( lpProcessInfo ) );
CreateProcessA( NULL,
const_cast<char *>(filename.c_str()), NULL, NULL,
NULL, NULL, NULL, NULL,
&lpStartupInfo,
&lpProcessInfo
);
}
CreateProcessA( NULL,
const_cast<char *>(filename.c_str()), NULL, NULL,
NULL, NULL, NULL, NULL,
&lpStartupInfo,
&lpProcessInfo
);
}
#else
std::cout << "Please launch the game with these arguments: " << arguments[choice] << std::endl;
std::cout << "Please launch the game with these arguments: " << arguments[choice] << std::endl;
#endif
}
}
}