Skip to content

Commit 2ec0d99

Browse files
committed
- Latest plugin code, AC msgs now go via service
1 parent 3492f67 commit 2ec0d99

6 files changed

Lines changed: 146 additions & 30 deletions

File tree

Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,13 @@ void MilesAudioManager::reset()
480480
void MilesAudioManager::update()
481481
{
482482
AudioManager::update();
483+
484+
// Check audio device is initialized before updating
485+
if (m_digitalHandle == nullptr)
486+
{
487+
return; // Audio device not ready, skip update
488+
}
489+
483490
setDeviceListenerPosition();
484491
processRequestList();
485492
processPlayingList();
@@ -1193,15 +1200,21 @@ void MilesAudioManager::freeAllMilesHandles()
11931200
std::list<HSAMPLE>::iterator it;
11941201
for ( it = m_availableSamples.begin(); it != m_availableSamples.end(); /* empty */ ) {
11951202
HSAMPLE sample = *it;
1196-
AIL_release_sample_handle(sample);
1203+
if (sample != nullptr)
1204+
{
1205+
AIL_release_sample_handle(sample);
1206+
}
11971207
it = m_availableSamples.erase(it);
11981208
}
11991209
m_num2DSamples = 0;
12001210

12011211
std::list<H3DSAMPLE>::iterator it3D;
12021212
for ( it3D = m_available3DSamples.begin(); it3D != m_available3DSamples.end(); /* empty */ ) {
12031213
H3DSAMPLE sample3D = *it3D;
1204-
AIL_release_3D_sample_handle(sample3D);
1214+
if (sample3D != nullptr)
1215+
{
1216+
AIL_release_3D_sample_handle(sample3D);
1217+
}
12051218
it3D = m_available3DSamples.erase(it3D);
12061219
}
12071220
m_num3DSamples = 0;
@@ -1440,9 +1453,13 @@ AsciiString MilesAudioManager::getMusicTrackName() const
14401453
void MilesAudioManager::openDevice()
14411454
{
14421455
if (!TheGlobalData->m_audioOn) {
1456+
m_digitalHandle = nullptr;
14431457
return;
14441458
}
14451459

1460+
// Always clear handle at start - only set if initialization succeeds
1461+
m_digitalHandle = nullptr;
1462+
14461463
AIL_set_redist_directory("MSS\\");
14471464
AIL_startup();
14481465
Int retval = 0;
@@ -1453,22 +1470,31 @@ void MilesAudioManager::openDevice()
14531470

14541471
retval = AIL_quick_startup(audioSettings->m_useDigital, audioSettings->m_useMidi, audioSettings->m_outputRate, audioSettings->m_outputBits, audioSettings->m_outputChannels);
14551472

1456-
// Quick handles tells us where to store the various devices. For now, we're only interested in the digital handle.
1473+
if (!retval) {
1474+
// Initialization failed - ensure m_digitalHandle stays nullptr and audio is disabled
1475+
m_digitalHandle = nullptr;
1476+
setOn(false, AudioAffect_All);
1477+
return; // EXIT EARLY - don't continue with invalid device
1478+
}
1479+
1480+
// Only get handles if initialization succeeded
14571481
AIL_quick_handles(&m_digitalHandle, nullptr, nullptr);
14581482

1459-
if (retval) {
1460-
buildProviderList();
1461-
} else {
1462-
// if we couldn't initialize any devices, turn sound off (fail silently)
1463-
setOn( false, AudioAffect_All );
1483+
// If we still don't have a valid handle, disable audio
1484+
if (m_digitalHandle == nullptr) {
1485+
setOn(false, AudioAffect_All);
1486+
return;
14641487
}
14651488

1489+
// Device initialized successfully - proceed with setup
1490+
buildProviderList();
14661491
selectProvider(TheAudio->getProviderIndex(m_pref3DProvider));
14671492

14681493
// Now that we're all done, update the cached variables so that everything is in sync.
14691494
TheAudio->refreshCachedVariables();
14701495

14711496
if (!isValidProvider()) {
1497+
m_digitalHandle = nullptr; // Mark as invalid if provider check fails
14721498
return;
14731499
}
14741500

@@ -1478,9 +1504,13 @@ void MilesAudioManager::openDevice()
14781504
//-------------------------------------------------------------------------------------------------
14791505
void MilesAudioManager::closeDevice()
14801506
{
1481-
freeAllMilesHandles();
1482-
unselectProvider();
1483-
AIL_shutdown();
1507+
if (m_digitalHandle != nullptr)
1508+
{
1509+
freeAllMilesHandles();
1510+
unselectProvider();
1511+
AIL_shutdown();
1512+
m_digitalHandle = nullptr;
1513+
}
14841514
}
14851515

14861516
//-------------------------------------------------------------------------------------------------

GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_Init.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ enum EWebSocketMessageID
5959
NETWORK_ROOM_MARK_READY = 5,
6060
LOBBY_CURRENT_LOBBY_UPDATE = 6,
6161
NETWORK_ROOM_LOBBY_LIST_UPDATE = 7,
62-
UNUSED_PLACEHOLDER = 8, // this was relay upgrade, was removed. We can re-use it later, but service needs this placeholder
62+
ANTICHEAT_MESSAGE = 8,
6363
PLAYER_NAME_CHANGE = 9,
6464
LOBBY_ROOM_CHAT_FROM_CLIENT = 10,
6565
LOBBY_CHAT_FROM_SERVER = 11,
@@ -157,6 +157,8 @@ class WebSocket
157157
void SendData_Signalling(int64_t targetUserID, std::vector<uint8_t> vecPayload);
158158
void SendData_StartGame();
159159

160+
void SendData_ACMessage(int64_t targetUserID, std::vector<uint8_t> vecPayload);
161+
160162
void SendData_ChangeLobbyPassword(UnicodeString& strNewPassword);
161163
void SendData_RemoveLobbyPassword();
162164

GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
#include "GameNetwork/NetworkInterface.h"
102102
extern NetworkInterface * TheNetwork;
103103
#endif
104+
#include "ValveNetworkingSockets/steam/isteamnetworkingsockets.h"
104105

105106

106107
// ------------------------------------------------------------------------------------------------

GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_Init.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,7 @@ void NGMP_OnlineServicesManager::InitSentry()
10111011

10121012
sentry_options_set_dsn(options, "https://61750bebd112d279bcc286d617819269@o4509316925554688.ingest.us.sentry.io/4509316927586304");
10131013
sentry_options_set_database_path(options, strDumpPath.c_str());
1014-
sentry_options_set_release(options, "generalsonline-client@042826_QFE3_EAC");
1014+
sentry_options_set_release(options, "generalsonline-client@042826_QFE4_EAC");
10151015

10161016
#if defined(USE_TEST_ENV)
10171017
sentry_options_set_environment(options, "test");
@@ -1190,6 +1190,16 @@ void WebSocket::SendData_StartGame()
11901190
}
11911191

11921192

1193+
void WebSocket::SendData_ACMessage(int64_t targetUserID, std::vector<uint8_t> vecPayload)
1194+
{
1195+
nlohmann::json j;
1196+
j["msg_id"] = EWebSocketMessageID::ANTICHEAT_MESSAGE;
1197+
j["target_user_id"] = targetUserID;
1198+
j["payload"] = vecPayload;
1199+
std::string strBody = j.dump();
1200+
Send(strBody.c_str());
1201+
}
1202+
11931203
void WebSocket::SendData_SubscribeRealtimeUpdates()
11941204
{
11951205
nlohmann::json j;

GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_RoomsInterface.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,15 @@ class WebSocketMessage_NetworkSignal : public WebSocketMessageBase
343343
NLOHMANN_DEFINE_TYPE_INTRUSIVE(WebSocketMessage_NetworkSignal, target_user_id, payload)
344344
};
345345

346+
class WebSocketMessage_AnticheatMessage : public WebSocketMessageBase
347+
{
348+
public:
349+
int64_t target_user_id = -1;
350+
std::vector<uint8_t> payload;
351+
352+
NLOHMANN_DEFINE_TYPE_INTRUSIVE(WebSocketMessage_AnticheatMessage, target_user_id, payload)
353+
};
354+
346355
class WebSocketMessage_ServerProbe : public WebSocketMessageBase
347356
{
348357
public:
@@ -1129,6 +1138,22 @@ void WebSocket::Tick()
11291138
}
11301139
break;
11311140

1141+
case EWebSocketMessageID::ANTICHEAT_MESSAGE:
1142+
{
1143+
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] GOT AC MSG FROM WEBSOCKET!");
1144+
1145+
WebSocketMessage_AnticheatMessage acMsg;
1146+
bool bParsed = JSONGetAsObject(jsonObject, &acMsg);
1147+
1148+
if (bParsed)
1149+
{
1150+
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] AC Msg Signal User: %lld!", acMsg.target_user_id);
1151+
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] AC Msg Signal Payload Size: %d!", (int)acMsg.payload.size());
1152+
AnticheatPlugInterface::AC_NetworkMessageArrived(acMsg.target_user_id, acMsg.payload.data(), acMsg.payload.size());
1153+
}
1154+
}
1155+
break;
1156+
11321157
case EWebSocketMessageID::LOBBY_CURRENT_LOBBY_UPDATE:
11331158
{
11341159
// re-get the room info as it is stale

GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/PluginInterfaces.cpp

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
AnticheatPlugInterface::Functions.fn##funcName = (FuncDef##funcName)GetProcAddress(g_hACPluginModule, #funcName); \
99
if (!AnticheatPlugInterface::Functions.fn##funcName) \
1010
{ \
11-
NetworkLog(ELogVerbosity::LOG_RELEASE, "Failed to find " #funcName " function", MB_OK); \
11+
NetworkLog(ELogVerbosity::LOG_RELEASE, "Failed to find " #funcName " function"); \
1212
FreeLibrary(g_hACPluginModule); \
13+
g_hACPluginModule = nullptr; \
1314
return; \
1415
}
1516

1617
bool AnticheatPlugInterface::IsExternalProcessRunning()
1718
{
18-
if (IsPluginLoaded())
19+
if (IsPluginLoaded() && Functions.fnIsExternalProcessRunning != nullptr)
1920
{
2021
return Functions.fnIsExternalProcessRunning();
2122
}
@@ -25,7 +26,7 @@ bool AnticheatPlugInterface::IsExternalProcessRunning()
2526

2627
int AnticheatPlugInterface::GetAnticheatIdentifier()
2728
{
28-
if (IsPluginLoaded())
29+
if (IsPluginLoaded() && Functions.fnGetAnticheatIdentifier != nullptr)
2930
{
3031
return Functions.fnGetAnticheatIdentifier();
3132
}
@@ -35,6 +36,13 @@ int AnticheatPlugInterface::GetAnticheatIdentifier()
3536

3637
void AnticheatPlugInterface::LoadPlugin(const char* szPluginName)
3738
{
39+
if (szPluginName == nullptr)
40+
{
41+
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] ERROR: Plugin name is null");
42+
m_bPluginLoadFailed = true;
43+
return;
44+
}
45+
3846
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] Attempting to load plugin from %s", szPluginName);
3947

4048
m_bPluginLoadFailed = false;
@@ -71,7 +79,10 @@ void AnticheatPlugInterface::LoadPlugin(const char* szPluginName)
7179
AC_PLUGIN_LOAD_FUNCTION(GetAnticheatIdentifier);
7280

7381
#if _DEBUG
74-
SetWindowText(ApplicationHWnd, Functions.fnIsExternalProcessRunning() ? "SECURED" : "INSECURE");
82+
if (ApplicationHWnd != nullptr)
83+
{
84+
SetWindowText(ApplicationHWnd, Functions.fnIsExternalProcessRunning() ? "SECURED" : "INSECURE");
85+
}
7586
#endif
7687

7788
// integrity callback
@@ -111,7 +122,8 @@ void AnticheatPlugInterface::LoadPlugin(const char* szPluginName)
111122
}
112123

113124
// If it's us, leave, if its someone else, d/c them
114-
if (pAuthInterface->GetUserID() == userID)
125+
uint32_t localUserID = pAuthInterface->GetUserID();
126+
if (localUserID == userID)
115127
{
116128
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] Leaving lobby, lobby isn't secure, action was requested against local user.");
117129
g_bPendingExitLobby = true;
@@ -144,14 +156,45 @@ void AnticheatPlugInterface::LoadPlugin(const char* szPluginName)
144156
return;
145157
}
146158

147-
NetworkMesh* pMesh = NGMP_OnlineServicesManager::GetNetworkMesh();
148-
if (pMesh != nullptr)
159+
// prefer websocket if we have it, otherwise fall back to p2p mesh
160+
bool bFallbackToP2P = false;
161+
std::shared_ptr<WebSocket> pWS = NGMP_OnlineServicesManager::GetWebSocket();
162+
if (pWS != nullptr)
149163
{
150-
pMesh->SendACPacket(goUserID, pData, dataLen);
164+
if (pWS->IsConnected())
165+
{
166+
if (dataLen > 0)
167+
{
168+
std::vector<uint8_t> vecPayload((uint8_t*)pData, (uint8_t*)pData + dataLen);
169+
pWS->SendData_ACMessage(goUserID, vecPayload);
170+
}
171+
else
172+
{
173+
bFallbackToP2P = true;
174+
}
175+
}
176+
else
177+
{
178+
bFallbackToP2P = true;
179+
}
151180
}
152181
else
153182
{
154-
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] ERROR: Cannot send AC packet - NetworkMesh is null");
183+
bFallbackToP2P = true;
184+
}
185+
186+
if (bFallbackToP2P)
187+
{
188+
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] AC Packets - WebSocket unavailable, falling back to P2P");
189+
NetworkMesh* pMesh = NGMP_OnlineServicesManager::GetNetworkMesh();
190+
if (pMesh != nullptr)
191+
{
192+
pMesh->SendACPacket(goUserID, pData, dataLen);
193+
}
194+
else
195+
{
196+
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] ERROR: Cannot send AC packet - NetworkMesh is null");
197+
}
155198
}
156199
});
157200

@@ -206,7 +249,8 @@ void AnticheatPlugInterface::Authenticate()
206249
return;
207250
}
208251

209-
Functions.fnLogin(pAuthInterface->GetAuthToken().c_str(),
252+
std::string authToken = pAuthInterface->GetAuthToken();
253+
Functions.fnLogin(authToken.c_str(),
210254
[](bool bSuccess)
211255
{
212256
if (!bSuccess)
@@ -226,12 +270,14 @@ void AnticheatPlugInterface::Authenticate()
226270

227271
// Now we can begin login
228272
NGMP_OnlineServices_AuthInterface* pAuthInterface = NGMP_OnlineServicesManager::GetInterface<NGMP_OnlineServices_AuthInterface>();
229-
if (pAuthInterface == nullptr)
273+
if (pAuthInterface != nullptr)
230274
{
231-
return;
275+
pAuthInterface->SendMiddlewareToken(std::string(buf));
276+
}
277+
else
278+
{
279+
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] ERROR: Auth interface became null during login callback");
232280
}
233-
234-
pAuthInterface->SendMiddlewareToken(std::string(buf));
235281
}
236282
}
237283
else
@@ -289,7 +335,7 @@ bool AnticheatPlugInterface::RegisterPlayer(std::string mwUserID, uint32_t goUse
289335

290336
if (IsPluginLoaded() && Functions.fnRegisterPlayer != nullptr)
291337
{
292-
NetworkLog(ELogVerbosity::LOG_RELEASE, "RegisterPlayer: %s to %" PRIu64, mwUserID.c_str(), goUserID);
338+
NetworkLog(ELogVerbosity::LOG_RELEASE, "RegisterPlayer: %s to %" PRIu32, mwUserID.c_str(), goUserID);
293339

294340
bool bReg = Functions.fnRegisterPlayer(mwUserID.c_str(), goUserID);
295341
NetworkLog(ELogVerbosity::LOG_RELEASE, "RegisterPlayerFunc result: %d", bReg);
@@ -304,7 +350,7 @@ bool AnticheatPlugInterface::DeregisterPlayer(std::string mwUserID, uint32_t goU
304350
{
305351
if (IsPluginLoaded() && Functions.fnDeregisterPlayer != nullptr)
306352
{
307-
NetworkLog(ELogVerbosity::LOG_RELEASE, "DeregisterPlayer: %s to %" PRIu64, mwUserID.c_str(), goUserID);
353+
NetworkLog(ELogVerbosity::LOG_RELEASE, "DeregisterPlayer: %s to %" PRIu32, mwUserID.c_str(), goUserID);
308354

309355
bool bReg = Functions.fnDeregisterPlayer(mwUserID.c_str(), goUserID);
310356
NetworkLog(ELogVerbosity::LOG_RELEASE, "DeregisterPlayerFunc result: %d", bReg);
@@ -346,12 +392,14 @@ void AnticheatPlugInterface::RefreshToken()
346392

347393
m_tokenCreationTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::utc_clock::now().time_since_epoch()).count();
348394

349-
Functions.fnRefreshToken(pAuthInterface->GetAuthToken().c_str(),
395+
std::string authToken = pAuthInterface->GetAuthToken();
396+
Functions.fnRefreshToken(authToken.c_str(),
350397
[](bool bSuccess)
351398
{
352399
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] Refreshed token: %d", bSuccess);
353400
if (!bSuccess)
354401
{
402+
NetworkLog(ELogVerbosity::LOG_RELEASE, "[AC] ERROR: Token refresh failed");
355403
// TODO_AC: Handle this, its a fatal error
356404
return;
357405
}

0 commit comments

Comments
 (0)