29
29
#include " filesystem.h"
30
30
#include " steam/steam_gameserver.h"
31
31
#include < string>
32
+ #include < sstream>
32
33
#include " iserver.h"
33
34
34
35
#include " tier0/memdbgon.h"
@@ -60,7 +61,8 @@ void Panic(const char *msg, ...)
60
61
}
61
62
62
63
std::string g_sExtraAddons;
63
- CUtlVector<char *> g_vecExtraAddons;
64
+ CUtlVector<std::string> g_vecExtraAddons;
65
+ CUtlVector<std::string> g_vecMountedAddons;
64
66
65
67
typedef void (FASTCALL *SendNetMessage_t)(INetChannel *pNetChan, INetworkSerializable *pNetMessage, void *pData, int a4);
66
68
typedef void * (FASTCALL *HostStateRequest_t)(void *a1, void **pRequest);
@@ -167,7 +169,12 @@ bool MultiAddonManager::Load(PluginId id, ISmmAPI *ismm, char *error, size_t max
167
169
168
170
bool MultiAddonManager::Unload (char *error, size_t maxlen)
169
171
{
170
- g_vecExtraAddons.PurgeAndDeleteElements ();
172
+ g_vecExtraAddons.Purge ();
173
+
174
+ FOR_EACH_VEC_BACK (g_vecMountedAddons, i)
175
+ UnmountAddon (g_vecMountedAddons[i].c_str ());
176
+
177
+ g_vecMountedAddons.Purge ();
171
178
172
179
SH_REMOVE_HOOK_MEMFUNC (IServerGameDLL, GameServerSteamAPIActivated, g_pSource2Server, this , &MultiAddonManager::Hook_GameServerSteamAPIActivated, false );
173
180
SH_REMOVE_HOOK_MEMFUNC (INetworkServerService, StartupServer, g_pNetworkServerService, this , &MultiAddonManager::Hook_StartupServer, true );
@@ -188,8 +195,6 @@ bool MultiAddonManager::Unload(char *error, size_t maxlen)
188
195
return true ;
189
196
}
190
197
191
- CUtlVector<std::string> g_vecMountedAddons;
192
-
193
198
void MultiAddonManager::BuildAddonPath (const char *pszAddon, char *buf, size_t len)
194
199
{
195
200
// The workshop is stored relative to the working directory for whatever reason
@@ -280,17 +285,17 @@ void MultiAddonManager::DownloadAddon(const char *pszAddon, bool bForce = false)
280
285
281
286
void MultiAddonManager::RefreshAddons ()
282
287
{
283
- Message (" Refreshing addons (%s)\n " , g_sExtraAddons);
288
+ Message (" Refreshing addons (%s)\n " , g_sExtraAddons. c_str () );
284
289
285
290
// Remove our paths first in case addons were switched
286
291
FOR_EACH_VEC_BACK (g_vecMountedAddons, i)
287
292
UnmountAddon (g_vecMountedAddons[i].c_str ());
288
293
289
294
FOR_EACH_VEC (g_vecExtraAddons, i)
290
295
{
291
- if (!MountAddon (g_vecExtraAddons[i]))
296
+ if (!MountAddon (g_vecExtraAddons[i]. c_str () ))
292
297
{
293
- DownloadAddon (g_vecExtraAddons[i]);
298
+ DownloadAddon (g_vecExtraAddons[i]. c_str () );
294
299
continue ;
295
300
}
296
301
}
@@ -319,14 +324,30 @@ void MultiAddonManager::OnAddonDownloaded(DownloadItemResult_t *pResult)
319
324
320
325
std::string sAddon = std::to_string (pResult->m_nPublishedFileId );
321
326
322
- if (g_vecMountedAddons.Find (sAddon ) == -1 )
327
+ if (g_vecMountedAddons.Find (sAddon ) == -1 && g_vecExtraAddons. Find ( sAddon ) != - 1 )
323
328
{
324
329
// Mount late downloaded addons to the tail so we don't inadvertently override packed map files
325
330
// This will however place them below the game vpks as well, so any overrides won't work this way
326
331
MountAddon (sAddon .c_str (), true );
327
332
}
328
333
}
329
334
335
+ void SplitStringToVector (const char *pszString, CUtlVector<std::string> &vector)
336
+ {
337
+ std::stringstream stream (pszString);
338
+
339
+ vector.RemoveAll ();
340
+
341
+ while (stream.good ())
342
+ {
343
+ std::string substr;
344
+ getline (stream, substr, ' ,' );
345
+
346
+ if (!substr.empty ())
347
+ vector.AddToTail (substr);
348
+ }
349
+ }
350
+
330
351
CON_COMMAND_F (mm_extra_addons, " The workshop IDs of extra addons separated by commas, addons will be downloaded (if not present) and mounted" , FCVAR_LINKED_CONCOMMAND | FCVAR_SPONLY)
331
352
{
332
353
if (args.ArgC () < 2 )
@@ -337,32 +358,20 @@ CON_COMMAND_F(mm_extra_addons, "The workshop IDs of extra addons separated by co
337
358
338
359
g_sExtraAddons = args[1 ];
339
360
340
- g_vecExtraAddons.PurgeAndDeleteElements ();
341
- V_SplitString (g_sExtraAddons.c_str (), " ," , g_vecExtraAddons);
361
+ SplitStringToVector (args[1 ], g_vecExtraAddons);
342
362
343
363
g_MultiAddonManager.RefreshAddons ();
344
364
}
345
365
346
- CON_COMMAND_F (mm_download_addon, " Download and mount an addon manually (server only) " , FCVAR_GAMEDLL | FCVAR_RELEASE | FCVAR_SPONLY)
366
+ CON_COMMAND_F (mm_download_addon, " Download an addon manually" , FCVAR_GAMEDLL | FCVAR_RELEASE | FCVAR_SPONLY)
347
367
{
348
368
if (args.ArgC () != 2 )
349
369
{
350
370
Message (" Usage: mm_download_addon <ID>\n " );
351
371
return ;
352
372
}
353
373
354
- DownloadAddon (args[1 ], true );
355
- }
356
-
357
- CON_COMMAND_F (mm_mount_addon, " Mount an addon manually (server only)" , FCVAR_GAMEDLL | FCVAR_RELEASE | FCVAR_SPONLY)
358
- {
359
- if (args.ArgC () != 2 )
360
- {
361
- Message (" Usage: mm_mount_addon <ID>\n " );
362
- return ;
363
- }
364
-
365
- MountAddon (args[1 ], true );
374
+ g_MultiAddonManager.DownloadAddon (args[1 ], true );
366
375
}
367
376
368
377
CON_COMMAND_F (mm_print_searchpaths, " Print search paths" , FCVAR_GAMEDLL | FCVAR_RELEASE | FCVAR_SPONLY)
@@ -477,7 +486,7 @@ void FASTCALL Hook_SendNetMessage(INetChannel *pNetChan, INetworkSerializable *p
477
486
478
487
if (pPendingClient)
479
488
{
480
- Message (__FUNCTION__" : Sending addon %s to client %lli\n " , g_vecExtraAddons[pPendingClient->addon ], pPendingClient->steamid );
489
+ Message (__FUNCTION__" : Sending addon %s to client %lli\n " , g_vecExtraAddons[pPendingClient->addon ]. c_str () , pPendingClient->steamid );
481
490
482
491
CNETMsg_SignonState *pMsg = (CNETMsg_SignonState *)pData;
483
492
pMsg->set_addons (g_vecExtraAddons[pPendingClient->addon ]);
@@ -529,7 +538,7 @@ bool MultiAddonManager::Hook_ClientConnect( CPlayerSlot slot, const char *pszNam
529
538
if (!pPendingClient)
530
539
{
531
540
// Client joined for the first time or after a timeout
532
- Message (" first connection, sending addon %s\n " , g_vecExtraAddons[0 ]);
541
+ Message (" first connection, sending addon %s\n " , g_vecExtraAddons[0 ]. c_str () );
533
542
AddPendingClient (xuid);
534
543
}
535
544
else if ((Plat_FloatTime () - pPendingClient->signon_timestamp ) < g_flRejoinTimeout)
@@ -540,7 +549,7 @@ bool MultiAddonManager::Hook_ClientConnect( CPlayerSlot slot, const char *pszNam
540
549
541
550
if (pPendingClient->addon < g_vecExtraAddons.Count ())
542
551
{
543
- Message (" reconnected within the interval, sending next addon %s\n " , g_vecExtraAddons[pPendingClient->addon ]);
552
+ Message (" reconnected within the interval, sending next addon %s\n " , g_vecExtraAddons[pPendingClient->addon ]. c_str () );
544
553
}
545
554
else
546
555
{
@@ -550,7 +559,7 @@ bool MultiAddonManager::Hook_ClientConnect( CPlayerSlot slot, const char *pszNam
550
559
}
551
560
else
552
561
{
553
- Message (" reconnected after the timeout or did not receive the addon message, will resend addon %s\n " , g_vecExtraAddons[pPendingClient->addon ]);
562
+ Message (" reconnected after the timeout or did not receive the addon message, will resend addon %s\n " , g_vecExtraAddons[pPendingClient->addon ]. c_str () );
554
563
}
555
564
556
565
RETURN_META_VALUE (MRES_IGNORED, true );
0 commit comments