拆分房间功能和管理到单独文件,并删除control_packets相关代码
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "tcp_server.h"
|
#include "tcp_server.h"
|
||||||
#include "tcp/tcp_client.h"
|
#include "tcp/tcp_client.h"
|
||||||
#include "steamnet/steam_networking_manager.h"
|
#include "steam/steam_networking_manager.h"
|
||||||
|
|
||||||
using boost::asio::ip::tcp;
|
using boost::asio::ip::tcp;
|
||||||
|
|
||||||
|
|||||||
93
steam/steam_message_handler.cpp
Normal file
93
steam/steam_message_handler.cpp
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#include "steam_message_handler.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstring>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <steam_api.h>
|
||||||
|
#include <isteamnetworkingsockets.h>
|
||||||
|
|
||||||
|
SteamMessageHandler::SteamMessageHandler(boost::asio::io_context& io_context, ISteamNetworkingSockets* interface, std::vector<HSteamNetConnection>& connections, std::map<HSteamNetConnection, std::shared_ptr<TCPClient>>& clientMap, std::mutex& clientMutex, std::mutex& connectionsMutex, std::unique_ptr<TCPServer>& server, bool& g_isHost, int& localPort)
|
||||||
|
: io_context_(io_context), m_pInterface_(interface), connections_(connections), clientMap_(clientMap), clientMutex_(clientMutex), connectionsMutex_(connectionsMutex), server_(server), g_isHost_(g_isHost), localPort_(localPort), running_(false) {}
|
||||||
|
|
||||||
|
SteamMessageHandler::~SteamMessageHandler() {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamMessageHandler::start() {
|
||||||
|
if (running_) return;
|
||||||
|
running_ = true;
|
||||||
|
thread_ = std::thread([this]() { run(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamMessageHandler::stop() {
|
||||||
|
if (!running_) return;
|
||||||
|
running_ = false;
|
||||||
|
if (thread_.joinable()) {
|
||||||
|
thread_.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamMessageHandler::run() {
|
||||||
|
while (running_) {
|
||||||
|
// Poll networking
|
||||||
|
m_pInterface_->RunCallbacks();
|
||||||
|
|
||||||
|
// Update user info (assuming userMap is accessible, but for simplicity, skip or add as param)
|
||||||
|
// Note: userMap update might need to be handled elsewhere or passed
|
||||||
|
|
||||||
|
// Receive messages
|
||||||
|
pollMessages();
|
||||||
|
|
||||||
|
// Sleep a bit to avoid busy loop
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamMessageHandler::pollMessages() {
|
||||||
|
std::vector<HSteamNetConnection> currentConnections;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lockConn(connectionsMutex_);
|
||||||
|
currentConnections = connections_;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(clientMutex_);
|
||||||
|
for (auto conn : currentConnections) {
|
||||||
|
ISteamNetworkingMessage* pIncomingMsgs[10];
|
||||||
|
int numMsgs = m_pInterface_->ReceiveMessagesOnConnection(conn, pIncomingMsgs, 10);
|
||||||
|
for (int i = 0; i < numMsgs; ++i) {
|
||||||
|
ISteamNetworkingMessage* pIncomingMsg = pIncomingMsgs[i];
|
||||||
|
const char* data = (const char*)pIncomingMsg->m_pData;
|
||||||
|
size_t size = pIncomingMsg->m_cbSize;
|
||||||
|
// Normal forwarding
|
||||||
|
if (server_) {
|
||||||
|
server_->sendToAll((const char*)pIncomingMsg->m_pData, pIncomingMsg->m_cbSize);
|
||||||
|
}
|
||||||
|
// Lazy connect: Create TCP Client on first message if not already connected
|
||||||
|
if (clientMap_.find(conn) == clientMap_.end() && g_isHost_ && localPort_ > 0) {
|
||||||
|
auto client = std::make_shared<TCPClient>("localhost", localPort_);
|
||||||
|
if (client->connect()) {
|
||||||
|
client->setReceiveCallback([conn, this](const char* data, size_t size) {
|
||||||
|
std::lock_guard<std::mutex> lock(clientMutex_);
|
||||||
|
m_pInterface_->SendMessageToConnection(conn, data, size, k_nSteamNetworkingSend_Reliable, nullptr);
|
||||||
|
});
|
||||||
|
client->setDisconnectCallback([conn, this]() {
|
||||||
|
std::lock_guard<std::mutex> lock(clientMutex_);
|
||||||
|
if (clientMap_.count(conn)) {
|
||||||
|
clientMap_[conn]->disconnect();
|
||||||
|
clientMap_.erase(conn);
|
||||||
|
std::cout << "TCP client disconnected, removed from map" << std::endl;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
clientMap_[conn] = client;
|
||||||
|
std::cout << "Created TCP Client for connection on first message" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Failed to connect TCP Client for connection" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Send to corresponding TCP client if exists (for host)
|
||||||
|
if (clientMap_.count(conn)) {
|
||||||
|
clientMap_[conn]->send((const char*)pIncomingMsg->m_pData, pIncomingMsg->m_cbSize);
|
||||||
|
}
|
||||||
|
pIncomingMsg->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
#include <steamnetworkingtypes.h>
|
#include <steamnetworkingtypes.h>
|
||||||
#include "tcp_server.h"
|
#include "tcp_server.h"
|
||||||
#include "tcp/tcp_client.h"
|
#include "tcp/tcp_client.h"
|
||||||
#include "control_packets.h"
|
|
||||||
|
|
||||||
class SteamMessageHandler {
|
class SteamMessageHandler {
|
||||||
public:
|
public:
|
||||||
@@ -23,7 +22,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
void run();
|
void run();
|
||||||
void pollMessages();
|
void pollMessages();
|
||||||
void handleControlPacket(const char* data, size_t size, HSteamNetConnection conn);
|
|
||||||
|
|
||||||
boost::asio::io_context& io_context_;
|
boost::asio::io_context& io_context_;
|
||||||
ISteamNetworkingSockets* m_pInterface_;
|
ISteamNetworkingSockets* m_pInterface_;
|
||||||
@@ -13,107 +13,11 @@ void SteamNetworkingManager::OnSteamNetConnectionStatusChanged(SteamNetConnectio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SteamFriendsCallbacks::SteamFriendsCallbacks(SteamNetworkingManager *manager) : manager_(manager)
|
|
||||||
{
|
|
||||||
std::cout << "SteamFriendsCallbacks constructor called" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamFriendsCallbacks::OnGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t *pCallback)
|
|
||||||
{
|
|
||||||
std::cout << "GameRichPresenceJoinRequested received" << std::endl;
|
|
||||||
if (manager_)
|
|
||||||
{
|
|
||||||
const char *connectStr = pCallback->m_rgchConnect;
|
|
||||||
std::cout << "Connect string: '" << (connectStr ? connectStr : "null") << "'" << std::endl;
|
|
||||||
if (connectStr && connectStr[0] != '\0')
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
uint64 id = std::stoull(connectStr);
|
|
||||||
std::string str = connectStr;
|
|
||||||
std::cout << "Parsed ID: " << id << std::endl;
|
|
||||||
if (str.find("7656119") == 0)
|
|
||||||
{
|
|
||||||
// It's a Steam ID, join host directly
|
|
||||||
std::cout << "Parsed Steam ID: " << id << ", joining host" << std::endl;
|
|
||||||
if (!manager_->isHost() && !manager_->isConnected())
|
|
||||||
{
|
|
||||||
manager_->joinHost(id);
|
|
||||||
// Start TCP Server if dependencies are set
|
|
||||||
if (manager_->server_ && !(*manager_->server_))
|
|
||||||
{
|
|
||||||
*manager_->server_ = std::make_unique<TCPServer>(8888, manager_);
|
|
||||||
if (!(*manager_->server_)->start())
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to start TCP server" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Already host or connected, ignoring join request" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Assume it's a lobby ID
|
|
||||||
CSteamID lobbySteamID(id);
|
|
||||||
std::cout << "Parsed lobby ID: " << id << std::endl;
|
|
||||||
if (!manager_->isHost() && !manager_->isConnected())
|
|
||||||
{
|
|
||||||
std::cout << "Joining lobby from invite: " << id << std::endl;
|
|
||||||
manager_->joinLobby(lobbySteamID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Already host or connected, ignoring invite" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to parse connect string: " << connectStr << " error: " << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "Empty connect string in join request" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Manager is null" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamFriendsCallbacks::OnGameLobbyJoinRequested(GameLobbyJoinRequested_t *pCallback)
|
|
||||||
{
|
|
||||||
std::cout << "GameLobbyJoinRequested received" << std::endl;
|
|
||||||
if (manager_)
|
|
||||||
{
|
|
||||||
CSteamID lobbyID = pCallback->m_steamIDLobby;
|
|
||||||
std::cout << "Lobby ID: " << lobbyID.ConvertToUint64() << std::endl;
|
|
||||||
if (!manager_->isHost() && !manager_->isConnected())
|
|
||||||
{
|
|
||||||
std::cout << "Joining lobby from request: " << lobbyID.ConvertToUint64() << std::endl;
|
|
||||||
manager_->joinLobby(lobbyID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Already host or connected, ignoring lobby join request" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Manager is null" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SteamNetworkingManager::SteamNetworkingManager()
|
SteamNetworkingManager::SteamNetworkingManager()
|
||||||
: m_pInterface(nullptr), hListenSock(k_HSteamListenSocket_Invalid), g_isHost(false), g_isClient(false), g_isConnected(false),
|
: m_pInterface(nullptr), hListenSock(k_HSteamListenSocket_Invalid), g_isHost(false), g_isClient(false), g_isConnected(false),
|
||||||
g_hConnection(k_HSteamNetConnection_Invalid),
|
g_hConnection(k_HSteamNetConnection_Invalid),
|
||||||
io_context_(nullptr), clientMap_(nullptr), clientMutex_(nullptr), server_(nullptr), localPort_(nullptr), messageHandler_(nullptr),
|
io_context_(nullptr), clientMap_(nullptr), clientMutex_(nullptr), server_(nullptr), localPort_(nullptr), messageHandler_(nullptr),
|
||||||
steamFriendsCallbacks(nullptr), steamMatchmakingCallbacks(nullptr), currentLobby(k_steamIDNil)
|
roomManager_(nullptr)
|
||||||
{
|
{
|
||||||
std::cout << "Initialized SteamNetworkingManager" << std::endl;
|
std::cout << "Initialized SteamNetworkingManager" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -122,8 +26,7 @@ SteamNetworkingManager::~SteamNetworkingManager()
|
|||||||
{
|
{
|
||||||
stopMessageHandler();
|
stopMessageHandler();
|
||||||
delete messageHandler_;
|
delete messageHandler_;
|
||||||
delete steamFriendsCallbacks;
|
delete roomManager_;
|
||||||
delete steamMatchmakingCallbacks;
|
|
||||||
shutdown();
|
shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,8 +116,7 @@ bool SteamNetworkingManager::initialize()
|
|||||||
std::cout << "[SteamNet] STUN servers: " << stunServersBuffer << std::endl;
|
std::cout << "[SteamNet] STUN servers: " << stunServersBuffer << std::endl;
|
||||||
|
|
||||||
// Create callbacks after Steam API init
|
// Create callbacks after Steam API init
|
||||||
steamFriendsCallbacks = new SteamFriendsCallbacks(this);
|
roomManager_ = new SteamRoomManager(this);
|
||||||
steamMatchmakingCallbacks = new SteamMatchmakingCallbacks(this);
|
|
||||||
|
|
||||||
SteamNetworkingUtils()->InitRelayNetworkAccess();
|
SteamNetworkingUtils()->InitRelayNetworkAccess();
|
||||||
SteamNetworkingUtils()->SetGlobalCallback_SteamNetConnectionStatusChanged(OnSteamNetConnectionStatusChanged);
|
SteamNetworkingUtils()->SetGlobalCallback_SteamNetConnectionStatusChanged(OnSteamNetConnectionStatusChanged);
|
||||||
@@ -242,7 +144,8 @@ bool SteamNetworkingManager::initialize()
|
|||||||
|
|
||||||
void SteamNetworkingManager::shutdown()
|
void SteamNetworkingManager::shutdown()
|
||||||
{
|
{
|
||||||
leaveLobby();
|
if (roomManager_)
|
||||||
|
roomManager_->leaveLobby();
|
||||||
if (g_hConnection != k_HSteamNetConnection_Invalid)
|
if (g_hConnection != k_HSteamNetConnection_Invalid)
|
||||||
{
|
{
|
||||||
m_pInterface->CloseConnection(g_hConnection, 0, nullptr, false);
|
m_pInterface->CloseConnection(g_hConnection, 0, nullptr, false);
|
||||||
@@ -258,82 +161,57 @@ void SteamNetworkingManager::shutdown()
|
|||||||
|
|
||||||
bool SteamNetworkingManager::createLobby()
|
bool SteamNetworkingManager::createLobby()
|
||||||
{
|
{
|
||||||
SteamAPICall_t hSteamAPICall = SteamMatchmaking()->CreateLobby(k_ELobbyTypePublic, 4);
|
if (roomManager_)
|
||||||
if (hSteamAPICall == k_uAPICallInvalid)
|
return roomManager_->createLobby();
|
||||||
{
|
return false;
|
||||||
std::cerr << "Failed to create lobby" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Call result will be handled by callback
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamNetworkingManager::leaveLobby()
|
void SteamNetworkingManager::leaveLobby()
|
||||||
{
|
{
|
||||||
if (currentLobby != k_steamIDNil)
|
if (roomManager_)
|
||||||
{
|
roomManager_->leaveLobby();
|
||||||
SteamMatchmaking()->LeaveLobby(currentLobby);
|
|
||||||
currentLobby = k_steamIDNil;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SteamNetworkingManager::searchLobbies()
|
bool SteamNetworkingManager::searchLobbies()
|
||||||
{
|
{
|
||||||
lobbies.clear();
|
if (roomManager_)
|
||||||
SteamAPICall_t hSteamAPICall = SteamMatchmaking()->RequestLobbyList();
|
return roomManager_->searchLobbies();
|
||||||
if (hSteamAPICall == k_uAPICallInvalid)
|
return false;
|
||||||
{
|
|
||||||
std::cerr << "Failed to request lobby list" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Results will be handled by callback
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SteamNetworkingManager::joinLobby(CSteamID lobbyID)
|
bool SteamNetworkingManager::joinLobby(CSteamID lobbyID)
|
||||||
{
|
{
|
||||||
if (SteamMatchmaking()->JoinLobby(lobbyID) != k_EResultOK)
|
if (roomManager_)
|
||||||
{
|
return roomManager_->joinLobby(lobbyID);
|
||||||
std::cerr << "Failed to join lobby" << std::endl;
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
// Connection will be handled by callback
|
const std::vector<CSteamID>& SteamNetworkingManager::getLobbies() const
|
||||||
return true;
|
{
|
||||||
|
static std::vector<CSteamID> empty;
|
||||||
|
if (roomManager_)
|
||||||
|
return roomManager_->getLobbies();
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSteamID SteamNetworkingManager::getCurrentLobby() const
|
||||||
|
{
|
||||||
|
if (roomManager_)
|
||||||
|
return roomManager_->getCurrentLobby();
|
||||||
|
return k_steamIDNil;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SteamNetworkingManager::startHosting()
|
bool SteamNetworkingManager::startHosting()
|
||||||
{
|
{
|
||||||
if (!createLobby())
|
if (roomManager_)
|
||||||
{
|
return roomManager_->startHosting();
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
hListenSock = m_pInterface->CreateListenSocketP2P(0, 0, nullptr);
|
|
||||||
|
|
||||||
if (hListenSock != k_HSteamListenSocket_Invalid)
|
|
||||||
{
|
|
||||||
g_isHost = true;
|
|
||||||
std::cout << "Created listen socket for hosting game room" << std::endl;
|
|
||||||
// Rich Presence is set in OnLobbyCreated callback
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to create listen socket for hosting" << std::endl;
|
|
||||||
leaveLobby();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamNetworkingManager::stopHosting()
|
void SteamNetworkingManager::stopHosting()
|
||||||
{
|
{
|
||||||
if (hListenSock != k_HSteamListenSocket_Invalid)
|
if (roomManager_)
|
||||||
{
|
roomManager_->stopHosting();
|
||||||
m_pInterface->CloseListenSocket(hListenSock);
|
|
||||||
hListenSock = k_HSteamListenSocket_Invalid;
|
|
||||||
}
|
|
||||||
leaveLobby();
|
|
||||||
g_isHost = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SteamNetworkingManager::joinHost(uint64 hostID)
|
bool SteamNetworkingManager::joinHost(uint64 hostID)
|
||||||
@@ -462,65 +340,3 @@ void SteamNetworkingManager::handleConnectionStatusChanged(SteamNetConnectionSta
|
|||||||
std::cout << "Connection closed" << std::endl;
|
std::cout << "Connection closed" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SteamMatchmakingCallbacks::SteamMatchmakingCallbacks(SteamNetworkingManager *manager) : manager_(manager) {}
|
|
||||||
|
|
||||||
void SteamMatchmakingCallbacks::OnLobbyCreated(LobbyCreated_t *pCallback)
|
|
||||||
{
|
|
||||||
if (pCallback->m_eResult == k_EResultOK)
|
|
||||||
{
|
|
||||||
manager_->currentLobby = pCallback->m_ulSteamIDLobby;
|
|
||||||
std::cout << "Lobby created: " << manager_->currentLobby.ConvertToUint64() << std::endl;
|
|
||||||
// Set Rich Presence with lobby ID
|
|
||||||
std::string lobbyStr = std::to_string(manager_->currentLobby.ConvertToUint64());
|
|
||||||
SteamFriends()->SetRichPresence("connect", lobbyStr.c_str());
|
|
||||||
SteamFriends()->SetRichPresence("status", "主持游戏房间");
|
|
||||||
SteamFriends()->SetRichPresence("steam_display", "#StatusWithConnectFormat");
|
|
||||||
std::cout << "Set Rich Presence connect to: " << lobbyStr << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to create lobby" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamMatchmakingCallbacks::OnLobbyListReceived(LobbyMatchList_t *pCallback)
|
|
||||||
{
|
|
||||||
manager_->lobbies.clear();
|
|
||||||
for (uint32 i = 0; i < pCallback->m_nLobbiesMatching; ++i)
|
|
||||||
{
|
|
||||||
CSteamID lobbyID = SteamMatchmaking()->GetLobbyByIndex(i);
|
|
||||||
manager_->lobbies.push_back(lobbyID);
|
|
||||||
}
|
|
||||||
std::cout << "Received " << pCallback->m_nLobbiesMatching << " lobbies" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamMatchmakingCallbacks::OnLobbyEntered(LobbyEnter_t *pCallback)
|
|
||||||
{
|
|
||||||
if (pCallback->m_EChatRoomEnterResponse == k_EChatRoomEnterResponseSuccess)
|
|
||||||
{
|
|
||||||
manager_->currentLobby = pCallback->m_ulSteamIDLobby;
|
|
||||||
std::cout << "Entered lobby: " << pCallback->m_ulSteamIDLobby << std::endl;
|
|
||||||
// Only join host if not the host
|
|
||||||
if (!manager_->isHost())
|
|
||||||
{
|
|
||||||
CSteamID hostID = SteamMatchmaking()->GetLobbyOwner(pCallback->m_ulSteamIDLobby);
|
|
||||||
if (manager_->joinHost(hostID.ConvertToUint64()))
|
|
||||||
{
|
|
||||||
// Start TCP Server if dependencies are set
|
|
||||||
if (manager_->server_ && !(*manager_->server_))
|
|
||||||
{
|
|
||||||
*manager_->server_ = std::make_unique<TCPServer>(8888, manager_);
|
|
||||||
if (!(*manager_->server_)->start())
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to start TCP server" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to enter lobby" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,33 +11,13 @@
|
|||||||
#include <steamnetworkingtypes.h>
|
#include <steamnetworkingtypes.h>
|
||||||
#include <isteammatchmaking.h>
|
#include <isteammatchmaking.h>
|
||||||
#include "steam_message_handler.h"
|
#include "steam_message_handler.h"
|
||||||
|
#include "steam_room_manager.h"
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
class TCPClient;
|
class TCPClient;
|
||||||
class TCPServer;
|
class TCPServer;
|
||||||
class SteamNetworkingManager;
|
class SteamNetworkingManager;
|
||||||
|
|
||||||
// Callback class for Steam Friends
|
|
||||||
class SteamFriendsCallbacks {
|
|
||||||
public:
|
|
||||||
SteamFriendsCallbacks(SteamNetworkingManager* manager);
|
|
||||||
STEAM_CALLBACK(SteamFriendsCallbacks, OnGameRichPresenceJoinRequested, GameRichPresenceJoinRequested_t);
|
|
||||||
STEAM_CALLBACK(SteamFriendsCallbacks, OnGameLobbyJoinRequested, GameLobbyJoinRequested_t);
|
|
||||||
private:
|
|
||||||
SteamNetworkingManager* manager_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Callback class for Steam Matchmaking
|
|
||||||
class SteamMatchmakingCallbacks {
|
|
||||||
public:
|
|
||||||
SteamMatchmakingCallbacks(SteamNetworkingManager* manager);
|
|
||||||
STEAM_CALLBACK(SteamMatchmakingCallbacks, OnLobbyCreated, LobbyCreated_t);
|
|
||||||
STEAM_CALLBACK(SteamMatchmakingCallbacks, OnLobbyListReceived, LobbyMatchList_t);
|
|
||||||
STEAM_CALLBACK(SteamMatchmakingCallbacks, OnLobbyEntered, LobbyEnter_t);
|
|
||||||
private:
|
|
||||||
SteamNetworkingManager* manager_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// User info structure
|
// User info structure
|
||||||
struct UserInfo {
|
struct UserInfo {
|
||||||
CSteamID steamID;
|
CSteamID steamID;
|
||||||
@@ -64,8 +44,8 @@ public:
|
|||||||
void leaveLobby();
|
void leaveLobby();
|
||||||
bool searchLobbies();
|
bool searchLobbies();
|
||||||
bool joinLobby(CSteamID lobbyID);
|
bool joinLobby(CSteamID lobbyID);
|
||||||
const std::vector<CSteamID>& getLobbies() const { return lobbies; }
|
const std::vector<CSteamID>& getLobbies() const;
|
||||||
CSteamID getCurrentLobby() const { return currentLobby; }
|
CSteamID getCurrentLobby() const;
|
||||||
|
|
||||||
// Joining
|
// Joining
|
||||||
bool joinHost(uint64 hostID);
|
bool joinHost(uint64 hostID);
|
||||||
@@ -109,10 +89,6 @@ private:
|
|||||||
HSteamNetConnection g_hConnection;
|
HSteamNetConnection g_hConnection;
|
||||||
CSteamID g_hostSteamID;
|
CSteamID g_hostSteamID;
|
||||||
|
|
||||||
// Lobby
|
|
||||||
std::vector<CSteamID> lobbies;
|
|
||||||
CSteamID currentLobby;
|
|
||||||
|
|
||||||
// Connections
|
// Connections
|
||||||
std::vector<HSteamNetConnection> connections;
|
std::vector<HSteamNetConnection> connections;
|
||||||
std::map<HSteamNetConnection, UserInfo> userMap;
|
std::map<HSteamNetConnection, UserInfo> userMap;
|
||||||
@@ -125,8 +101,9 @@ private:
|
|||||||
|
|
||||||
// Friends
|
// Friends
|
||||||
std::vector<std::pair<CSteamID, std::string>> friendsList;
|
std::vector<std::pair<CSteamID, std::string>> friendsList;
|
||||||
SteamFriendsCallbacks* steamFriendsCallbacks;
|
|
||||||
SteamMatchmakingCallbacks* steamMatchmakingCallbacks;
|
// Room manager
|
||||||
|
SteamRoomManager* roomManager_;
|
||||||
|
|
||||||
// Message handler dependencies
|
// Message handler dependencies
|
||||||
boost::asio::io_context* io_context_;
|
boost::asio::io_context* io_context_;
|
||||||
@@ -139,6 +116,8 @@ private:
|
|||||||
// Callback
|
// Callback
|
||||||
static void OnSteamNetConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *pInfo);
|
static void OnSteamNetConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *pInfo);
|
||||||
void handleConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *pInfo);
|
void handleConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *pInfo);
|
||||||
|
|
||||||
|
friend class SteamRoomManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STEAM_NETWORKING_MANAGER_H
|
#endif // STEAM_NETWORKING_MANAGER_H
|
||||||
256
steam/steam_room_manager.cpp
Normal file
256
steam/steam_room_manager.cpp
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
#include "steam_room_manager.h"
|
||||||
|
#include "steam_networking_manager.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
SteamFriendsCallbacks::SteamFriendsCallbacks(SteamNetworkingManager *manager) : manager_(manager)
|
||||||
|
{
|
||||||
|
std::cout << "SteamFriendsCallbacks constructor called" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamFriendsCallbacks::OnGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t *pCallback)
|
||||||
|
{
|
||||||
|
std::cout << "GameRichPresenceJoinRequested received" << std::endl;
|
||||||
|
if (manager_)
|
||||||
|
{
|
||||||
|
const char *connectStr = pCallback->m_rgchConnect;
|
||||||
|
std::cout << "Connect string: '" << (connectStr ? connectStr : "null") << "'" << std::endl;
|
||||||
|
if (connectStr && connectStr[0] != '\0')
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
uint64 id = std::stoull(connectStr);
|
||||||
|
std::string str = connectStr;
|
||||||
|
std::cout << "Parsed ID: " << id << std::endl;
|
||||||
|
if (str.find("7656119") == 0)
|
||||||
|
{
|
||||||
|
// It's a Steam ID, join host directly
|
||||||
|
std::cout << "Parsed Steam ID: " << id << ", joining host" << std::endl;
|
||||||
|
if (!manager_->isHost() && !manager_->isConnected())
|
||||||
|
{
|
||||||
|
manager_->joinHost(id);
|
||||||
|
// Start TCP Server if dependencies are set
|
||||||
|
if (manager_->server_ && !(*manager_->server_))
|
||||||
|
{
|
||||||
|
*manager_->server_ = std::make_unique<TCPServer>(8888, manager_);
|
||||||
|
if (!(*manager_->server_)->start())
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to start TCP server" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Already host or connected, ignoring join request" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Assume it's a lobby ID
|
||||||
|
CSteamID lobbySteamID(id);
|
||||||
|
std::cout << "Parsed lobby ID: " << id << std::endl;
|
||||||
|
if (!manager_->isHost() && !manager_->isConnected())
|
||||||
|
{
|
||||||
|
std::cout << "Joining lobby from invite: " << id << std::endl;
|
||||||
|
manager_->joinLobby(lobbySteamID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Already host or connected, ignoring invite" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to parse connect string: " << connectStr << " error: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Empty connect string in join request" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Manager is null" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamFriendsCallbacks::OnGameLobbyJoinRequested(GameLobbyJoinRequested_t *pCallback)
|
||||||
|
{
|
||||||
|
std::cout << "GameLobbyJoinRequested received" << std::endl;
|
||||||
|
if (manager_)
|
||||||
|
{
|
||||||
|
CSteamID lobbyID = pCallback->m_steamIDLobby;
|
||||||
|
std::cout << "Lobby ID: " << lobbyID.ConvertToUint64() << std::endl;
|
||||||
|
if (!manager_->isHost() && !manager_->isConnected())
|
||||||
|
{
|
||||||
|
std::cout << "Joining lobby from request: " << lobbyID.ConvertToUint64() << std::endl;
|
||||||
|
manager_->joinLobby(lobbyID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Already host or connected, ignoring lobby join request" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Manager is null" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SteamMatchmakingCallbacks::SteamMatchmakingCallbacks(SteamNetworkingManager *manager) : manager_(manager) {}
|
||||||
|
|
||||||
|
void SteamMatchmakingCallbacks::OnLobbyCreated(LobbyCreated_t *pCallback)
|
||||||
|
{
|
||||||
|
if (pCallback->m_eResult == k_EResultOK)
|
||||||
|
{
|
||||||
|
manager_->roomManager_->setCurrentLobby(pCallback->m_ulSteamIDLobby);
|
||||||
|
std::cout << "Lobby created: " << manager_->roomManager_->getCurrentLobby().ConvertToUint64() << std::endl;
|
||||||
|
// Set Rich Presence with lobby ID
|
||||||
|
std::string lobbyStr = std::to_string(manager_->roomManager_->getCurrentLobby().ConvertToUint64());
|
||||||
|
SteamFriends()->SetRichPresence("connect", lobbyStr.c_str());
|
||||||
|
SteamFriends()->SetRichPresence("status", "主持游戏房间");
|
||||||
|
SteamFriends()->SetRichPresence("steam_display", "#StatusWithConnectFormat");
|
||||||
|
std::cout << "Set Rich Presence connect to: " << lobbyStr << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to create lobby" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamMatchmakingCallbacks::OnLobbyListReceived(LobbyMatchList_t *pCallback)
|
||||||
|
{
|
||||||
|
manager_->roomManager_->clearLobbies();
|
||||||
|
for (uint32 i = 0; i < pCallback->m_nLobbiesMatching; ++i)
|
||||||
|
{
|
||||||
|
CSteamID lobbyID = SteamMatchmaking()->GetLobbyByIndex(i);
|
||||||
|
manager_->roomManager_->addLobby(lobbyID);
|
||||||
|
}
|
||||||
|
std::cout << "Received " << pCallback->m_nLobbiesMatching << " lobbies" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamMatchmakingCallbacks::OnLobbyEntered(LobbyEnter_t *pCallback)
|
||||||
|
{
|
||||||
|
if (pCallback->m_EChatRoomEnterResponse == k_EChatRoomEnterResponseSuccess)
|
||||||
|
{
|
||||||
|
manager_->roomManager_->setCurrentLobby(pCallback->m_ulSteamIDLobby);
|
||||||
|
std::cout << "Entered lobby: " << pCallback->m_ulSteamIDLobby << std::endl;
|
||||||
|
// Only join host if not the host
|
||||||
|
if (!manager_->isHost())
|
||||||
|
{
|
||||||
|
CSteamID hostID = SteamMatchmaking()->GetLobbyOwner(pCallback->m_ulSteamIDLobby);
|
||||||
|
if (manager_->joinHost(hostID.ConvertToUint64()))
|
||||||
|
{
|
||||||
|
// Start TCP Server if dependencies are set
|
||||||
|
if (manager_->server_ && !(*manager_->server_))
|
||||||
|
{
|
||||||
|
*manager_->server_ = std::make_unique<TCPServer>(8888, manager_);
|
||||||
|
if (!(*manager_->server_)->start())
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to start TCP server" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to enter lobby" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SteamRoomManager::SteamRoomManager(SteamNetworkingManager *networkingManager)
|
||||||
|
: networkingManager_(networkingManager), currentLobby(k_steamIDNil),
|
||||||
|
steamFriendsCallbacks(nullptr), steamMatchmakingCallbacks(nullptr)
|
||||||
|
{
|
||||||
|
steamFriendsCallbacks = new SteamFriendsCallbacks(networkingManager_);
|
||||||
|
steamMatchmakingCallbacks = new SteamMatchmakingCallbacks(networkingManager_);
|
||||||
|
}
|
||||||
|
|
||||||
|
SteamRoomManager::~SteamRoomManager()
|
||||||
|
{
|
||||||
|
delete steamFriendsCallbacks;
|
||||||
|
delete steamMatchmakingCallbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SteamRoomManager::createLobby()
|
||||||
|
{
|
||||||
|
SteamAPICall_t hSteamAPICall = SteamMatchmaking()->CreateLobby(k_ELobbyTypePublic, 4);
|
||||||
|
if (hSteamAPICall == k_uAPICallInvalid)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to create lobby" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Call result will be handled by callback
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamRoomManager::leaveLobby()
|
||||||
|
{
|
||||||
|
if (currentLobby != k_steamIDNil)
|
||||||
|
{
|
||||||
|
SteamMatchmaking()->LeaveLobby(currentLobby);
|
||||||
|
currentLobby = k_steamIDNil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SteamRoomManager::searchLobbies()
|
||||||
|
{
|
||||||
|
lobbies.clear();
|
||||||
|
SteamAPICall_t hSteamAPICall = SteamMatchmaking()->RequestLobbyList();
|
||||||
|
if (hSteamAPICall == k_uAPICallInvalid)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to request lobby list" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Results will be handled by callback
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SteamRoomManager::joinLobby(CSteamID lobbyID)
|
||||||
|
{
|
||||||
|
if (SteamMatchmaking()->JoinLobby(lobbyID) != k_EResultOK)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to join lobby" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Connection will be handled by callback
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SteamRoomManager::startHosting()
|
||||||
|
{
|
||||||
|
if (!createLobby())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkingManager_->hListenSock = networkingManager_->m_pInterface->CreateListenSocketP2P(0, 0, nullptr);
|
||||||
|
|
||||||
|
if (networkingManager_->hListenSock != k_HSteamListenSocket_Invalid)
|
||||||
|
{
|
||||||
|
networkingManager_->g_isHost = true;
|
||||||
|
std::cout << "Created listen socket for hosting game room" << std::endl;
|
||||||
|
// Rich Presence is set in OnLobbyCreated callback
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to create listen socket for hosting" << std::endl;
|
||||||
|
leaveLobby();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamRoomManager::stopHosting()
|
||||||
|
{
|
||||||
|
if (networkingManager_->hListenSock != k_HSteamListenSocket_Invalid)
|
||||||
|
{
|
||||||
|
networkingManager_->m_pInterface->CloseListenSocket(networkingManager_->hListenSock);
|
||||||
|
networkingManager_->hListenSock = k_HSteamListenSocket_Invalid;
|
||||||
|
}
|
||||||
|
leaveLobby();
|
||||||
|
networkingManager_->g_isHost = false;
|
||||||
|
}
|
||||||
58
steam/steam_room_manager.h
Normal file
58
steam/steam_room_manager.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <steam_api.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
class SteamNetworkingManager; // Forward declaration
|
||||||
|
|
||||||
|
class SteamFriendsCallbacks
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SteamFriendsCallbacks(SteamNetworkingManager *manager);
|
||||||
|
void OnGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t *pCallback);
|
||||||
|
void OnGameLobbyJoinRequested(GameLobbyJoinRequested_t *pCallback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SteamNetworkingManager *manager_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SteamMatchmakingCallbacks
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SteamMatchmakingCallbacks(SteamNetworkingManager *manager);
|
||||||
|
void OnLobbyCreated(LobbyCreated_t *pCallback);
|
||||||
|
void OnLobbyListReceived(LobbyMatchList_t *pCallback);
|
||||||
|
void OnLobbyEntered(LobbyEnter_t *pCallback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SteamNetworkingManager *manager_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SteamRoomManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SteamRoomManager(SteamNetworkingManager *networkingManager);
|
||||||
|
~SteamRoomManager();
|
||||||
|
|
||||||
|
bool createLobby();
|
||||||
|
void leaveLobby();
|
||||||
|
bool searchLobbies();
|
||||||
|
bool joinLobby(CSteamID lobbyID);
|
||||||
|
bool startHosting();
|
||||||
|
void stopHosting();
|
||||||
|
|
||||||
|
CSteamID getCurrentLobby() const { return currentLobby; }
|
||||||
|
const std::vector<CSteamID>& getLobbies() const { return lobbies; }
|
||||||
|
|
||||||
|
void setCurrentLobby(CSteamID lobby) { currentLobby = lobby; }
|
||||||
|
void addLobby(CSteamID lobby) { lobbies.push_back(lobby); }
|
||||||
|
void clearLobbies() { lobbies.clear(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SteamNetworkingManager *networkingManager_;
|
||||||
|
CSteamID currentLobby;
|
||||||
|
std::vector<CSteamID> lobbies;
|
||||||
|
SteamFriendsCallbacks *steamFriendsCallbacks;
|
||||||
|
SteamMatchmakingCallbacks *steamMatchmakingCallbacks;
|
||||||
|
};
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#include "control_packets.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
// 假设需要访问全局变量,但为了简单,这里只打印
|
|
||||||
// 如果需要,可以传递引用或使用全局
|
|
||||||
|
|
||||||
void handleControlPacket(const char* data, size_t size, HSteamNetConnection conn) {
|
|
||||||
std::string_view packetData(data, size);
|
|
||||||
std::cout << "Received control packet: " << packetData << " from connection " << conn << std::endl;
|
|
||||||
// 这里添加处理逻辑,例如解析JSON或命令
|
|
||||||
// 例如,如果data是"ping",回复"pong"
|
|
||||||
if (packetData == "ping") {
|
|
||||||
// 发送回复,但需要接口
|
|
||||||
// 暂时只打印
|
|
||||||
std::cout << "Responding to ping" << std::endl;
|
|
||||||
}
|
|
||||||
// 可以扩展为更多控制命令
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#ifndef CONTROL_PACKETS_H
|
|
||||||
#define CONTROL_PACKETS_H
|
|
||||||
|
|
||||||
#include <steamnetworkingtypes.h>
|
|
||||||
|
|
||||||
void handleControlPacket(const char* data, size_t size, HSteamNetConnection conn);
|
|
||||||
|
|
||||||
#endif // CONTROL_PACKETS_H
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
#include "steam_message_handler.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <chrono>
|
|
||||||
#include <thread>
|
|
||||||
#include <steam_api.h>
|
|
||||||
#include <isteamnetworkingsockets.h>
|
|
||||||
|
|
||||||
// Constants for control packets
|
|
||||||
const char* CONTROL_PREFIX = "CONTROL:";
|
|
||||||
const size_t CONTROL_PREFIX_LEN = 8;
|
|
||||||
|
|
||||||
SteamMessageHandler::SteamMessageHandler(boost::asio::io_context& io_context, ISteamNetworkingSockets* interface, std::vector<HSteamNetConnection>& connections, std::map<HSteamNetConnection, std::shared_ptr<TCPClient>>& clientMap, std::mutex& clientMutex, std::mutex& connectionsMutex, std::unique_ptr<TCPServer>& server, bool& g_isHost, int& localPort)
|
|
||||||
: io_context_(io_context), m_pInterface_(interface), connections_(connections), clientMap_(clientMap), clientMutex_(clientMutex), connectionsMutex_(connectionsMutex), server_(server), g_isHost_(g_isHost), localPort_(localPort), running_(false) {}
|
|
||||||
|
|
||||||
SteamMessageHandler::~SteamMessageHandler() {
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamMessageHandler::handleControlPacket(const char* data, size_t size, HSteamNetConnection conn) {
|
|
||||||
std::string_view packetData(data, size);
|
|
||||||
std::cout << "Received control packet: " << packetData << " from connection " << conn << std::endl;
|
|
||||||
// Add handling logic here
|
|
||||||
if (packetData == "ping") {
|
|
||||||
std::cout << "Responding to ping" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamMessageHandler::start() {
|
|
||||||
if (running_) return;
|
|
||||||
running_ = true;
|
|
||||||
thread_ = std::thread([this]() { run(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamMessageHandler::stop() {
|
|
||||||
if (!running_) return;
|
|
||||||
running_ = false;
|
|
||||||
if (thread_.joinable()) {
|
|
||||||
thread_.join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamMessageHandler::run() {
|
|
||||||
while (running_) {
|
|
||||||
// Poll networking
|
|
||||||
m_pInterface_->RunCallbacks();
|
|
||||||
|
|
||||||
// Update user info (assuming userMap is accessible, but for simplicity, skip or add as param)
|
|
||||||
// Note: userMap update might need to be handled elsewhere or passed
|
|
||||||
|
|
||||||
// Receive messages
|
|
||||||
pollMessages();
|
|
||||||
|
|
||||||
// Sleep a bit to avoid busy loop
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamMessageHandler::pollMessages() {
|
|
||||||
std::vector<HSteamNetConnection> currentConnections;
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lockConn(connectionsMutex_);
|
|
||||||
currentConnections = connections_;
|
|
||||||
}
|
|
||||||
std::lock_guard<std::mutex> lock(clientMutex_);
|
|
||||||
for (auto conn : currentConnections) {
|
|
||||||
ISteamNetworkingMessage* pIncomingMsgs[10];
|
|
||||||
int numMsgs = m_pInterface_->ReceiveMessagesOnConnection(conn, pIncomingMsgs, 10);
|
|
||||||
for (int i = 0; i < numMsgs; ++i) {
|
|
||||||
ISteamNetworkingMessage* pIncomingMsg = pIncomingMsgs[i];
|
|
||||||
const char* data = (const char*)pIncomingMsg->m_pData;
|
|
||||||
size_t size = pIncomingMsg->m_cbSize;
|
|
||||||
if (size >= CONTROL_PREFIX_LEN && memcmp(data, CONTROL_PREFIX, CONTROL_PREFIX_LEN) == 0) {
|
|
||||||
// Handle control packet
|
|
||||||
handleControlPacket(data + CONTROL_PREFIX_LEN, size - CONTROL_PREFIX_LEN, conn);
|
|
||||||
} else {
|
|
||||||
// Normal forwarding
|
|
||||||
if (server_) {
|
|
||||||
server_->sendToAll((const char*)pIncomingMsg->m_pData, pIncomingMsg->m_cbSize);
|
|
||||||
}
|
|
||||||
// Lazy connect: Create TCP Client on first message if not already connected
|
|
||||||
if (clientMap_.find(conn) == clientMap_.end() && g_isHost_ && localPort_ > 0) {
|
|
||||||
auto client = std::make_shared<TCPClient>("localhost", localPort_);
|
|
||||||
if (client->connect()) {
|
|
||||||
client->setReceiveCallback([conn, this](const char* data, size_t size) {
|
|
||||||
std::lock_guard<std::mutex> lock(clientMutex_);
|
|
||||||
m_pInterface_->SendMessageToConnection(conn, data, size, k_nSteamNetworkingSend_Reliable, nullptr);
|
|
||||||
});
|
|
||||||
client->setDisconnectCallback([conn, this]() {
|
|
||||||
std::lock_guard<std::mutex> lock(clientMutex_);
|
|
||||||
if (clientMap_.count(conn)) {
|
|
||||||
clientMap_[conn]->disconnect();
|
|
||||||
clientMap_.erase(conn);
|
|
||||||
std::cout << "TCP client disconnected, removed from map" << std::endl;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
clientMap_[conn] = client;
|
|
||||||
std::cout << "Created TCP Client for connection on first message" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cerr << "Failed to connect TCP Client for connection" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Send to corresponding TCP client if exists (for host)
|
|
||||||
if (clientMap_.count(conn)) {
|
|
||||||
clientMap_[conn]->send((const char*)pIncomingMsg->m_pData, pIncomingMsg->m_cbSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pIncomingMsg->Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "tcp_server.h"
|
#include "tcp_server.h"
|
||||||
#include "../steamnet/steam_networking_manager.h"
|
#include "../steam/steam_networking_manager.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user