Files
Archimedes/modules/ClientModule/ClientModule.cpp
2025-05-12 00:14:11 -05:00

142 lines
5.0 KiB
C++

#include "ClientModule.h"
ClientModule::ClientModule(Archimedes::App* a, void* h) : Archimedes::Module(a, h) {
name = "ClientModule";
}
ClientModule::~ClientModule() {
if(app) {
app->unregisterEvent(Archimedes::DataRecievedEvent());
app->unregisterEvent(Archimedes::DataSentEvent());
app->unregisterEvent(Archimedes::ConnectionStatusChangedEvent());
GameNetworkingSockets_Kill();
}
}
void ClientModule::onLoad() {
app->registerEvent(Archimedes::DataSentEvent());
app->registerEvent(Archimedes::DataRecievedEvent());
app->registerEvent(Archimedes::ConnectionStatusChangedEvent());
SteamDatagramErrMsg errMsg;
if ( !GameNetworkingSockets_Init( nullptr, errMsg ) ) {
//FatalError( "GameNetworkingSockets_Init failed. %s", errMsg );
std::cerr << "GameNetworkingSockets_Init() Failed: " << errMsg << std::endl;
}
//SteamNetworkingUtils()->SetDebugOutputFunction( k_ESteamNetworkingSocketsDebugOutputType_Msg, DebugOutput );
interface = SteamNetworkingSockets();
}
void ClientModule::startClient(SteamNetworkingIPAddr& serverAddr) {
if(!running) {
// Start connecting
char szAddr[ SteamNetworkingIPAddr::k_cchMaxString ];
serverAddr.ToString( szAddr, sizeof(szAddr), true );
std::cerr << "Connecting to chat server at " << szAddr << std::endl;
SteamNetworkingConfigValue_t opt;
opt.SetPtr( k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, (void*)SteamNetConnectionStatusChangedCallback );
connection = interface->ConnectByIPAddress( serverAddr, 1, &opt );
if ( connection == k_HSteamNetConnection_Invalid )
std::cerr << "Failed to create connection\n";
running = true;
}
}
void ClientModule::stopClient() { running = false; }
void ClientModule::run() {
if(running) {
pollIncomingData();
PollConnectionStateChanges();
}
}
bool ClientModule::onEvent(const Archimedes::Event& event) {
unsigned int type = app->getEventType(event);
if(eventsToHandle & CMEventEnum::ConnectionStatusChanged && type == app->getEventType(Archimedes::ConnectionStatusChangedEvent())) {
Archimedes::ConnectionStatusChangedEvent& e = (Archimedes::ConnectionStatusChangedEvent&) event;
switch(e.info->m_info.m_eState) {
case k_ESteamNetworkingConnectionState_None:
// NOTE: We will get callbacks here when we destroy connections. You can ignore these.
break;
case k_ESteamNetworkingConnectionState_ClosedByPeer:
case k_ESteamNetworkingConnectionState_ProblemDetectedLocally:
{
// Ignore if they were not previously connected. (If they disconnected
// before we accepted the connection.)
if ( e.info->m_eOldState == k_ESteamNetworkingConnectionState_Connected )
{
}
else
{
assert( e.info->m_eOldState == k_ESteamNetworkingConnectionState_Connecting );
}
// Clean up the connection. This is important!
// The connection is "closed" in the network sense, but
// it has not been destroyed. We must close it on our end, too
// to finish up. The reason information do not matter in this case,
// and we cannot linger because it's already closed on the other end,
// so we just pass 0's.
//
// OnDisconnect
interface->CloseConnection( e.info->m_hConn, 0, nullptr, false );
connection = k_HSteamNetConnection_Invalid;
stopClient();
break;
}
case k_ESteamNetworkingConnectionState_Connecting:
{
break;
}
case k_ESteamNetworkingConnectionState_Connected:
//OnConnect
break;
default:
// Silences -Wswitch
break;
}
return true;
} else if(eventsToHandle & CMEventEnum::DataRecieved && type == app->getEventType(Archimedes::DataRecievedEvent())) {
return true;
} else if(eventsToHandle & CMEventEnum::DataSent && type == app->getEventType(Archimedes::DataSentEvent())) {
return true;
}
return false;
}
void ClientModule::pollIncomingData() {
while(running && connection != k_HSteamNetConnection_Invalid) {
ISteamNetworkingMessage *pIncomingMsg = nullptr;
int numMsgs = interface->ReceiveMessagesOnConnection( connection, &pIncomingMsg, 1 );
if ( numMsgs == 0 )
break;
if ( numMsgs < 0 )
std::cerr << "Error checking for messages" << std::endl;
assert( numMsgs == 1 && pIncomingMsg );
assert( pIncomingMsg->m_conn == connection );
app->emitEvent(new Archimedes::DataRecievedEvent(pIncomingMsg));
}
}