@@ -15,17 +15,26 @@ enum struct CVSEntry
1515 char CVSE_newval [CVS_CVAR_MAXLEN ];
1616}
1717
18+ enum struct CVSPending
19+ {
20+ char CVSP_name [CVS_CVAR_MAXLEN ];
21+ char CVSP_newval [CVS_CVAR_MAXLEN ];
22+ }
23+
1824static bool
1925 bTrackingStarted = false ;
2026
2127static ArrayList
22- CvarSettingsArray = null ;
28+ CvarSettingsArray = null ,
29+ PendingCvarsArray = null ;
2330
2431void CVS_OnModuleStart ()
2532{
2633 CVSEntry cvsetting ;
34+ CVSPending cvspending ;
2735
2836 CvarSettingsArray = new ArrayList (sizeof (cvsetting ));
37+ PendingCvarsArray = new ArrayList (sizeof (cvspending ));
2938
3039 RegConsoleCmd (" confogl_cvarsettings" , CVS_CvarSettings_Cmd , " List all ConVars being enforced by Confogl" );
3140 RegConsoleCmd (" confogl_cvardiff" , CVS_CvarDiff_Cmd , " List any ConVars that have been changed from their initialized values" );
@@ -42,6 +51,8 @@ void CVS_OnModuleEnd()
4251
4352void CVS_OnConfigsExecuted ()
4453{
54+ ResolvePendingCvars ();
55+
4556 if (bTrackingStarted ) {
4657 SetEnforcedCvars ();
4758 }
@@ -62,6 +73,7 @@ static Action CVS_SetCvars_Cmd(int args)
6273 LogMessage (" [%s ] No longer accepting new ConVars" , CVS_MODULE_NAME );
6374#endif
6475
76+ ResolvePendingCvars ();
6577 SetEnforcedCvars ();
6678 bTrackingStarted = true ;
6779
@@ -211,6 +223,7 @@ static void ClearAllSettings()
211223 }
212224
213225 CvarSettingsArray .Clear ();
226+ PendingCvarsArray .Clear ();
214227}
215228
216229static void SetEnforcedCvars ()
@@ -251,44 +264,95 @@ static void AddCvar(const char[] cvar, const char[] newval)
251264 return ;
252265 }
253266
254- ConVar newCvar = FindConVar (cvar );
255-
256- if (newCvar == null ) {
257- Debug_LogError (CVS_MODULE_NAME , " Could not find CVar specified (%s )" , cvar );
258- return ;
259- }
260-
261267 char cvarBuffer [CVS_CVAR_MAXLEN ];
262268 int iSize = CvarSettingsArray .Length ;
263269
264- CVSEntry newEntry ;
270+ CVSEntry existingEntry ;
265271
266272 for (int i = 0 ; i < iSize ; i ++ ) {
267- CvarSettingsArray .GetArray (i , newEntry , sizeof (newEntry ));
273+ CvarSettingsArray .GetArray (i , existingEntry , sizeof (existingEntry ));
268274
269- (newEntry .CVSE_cvar ).GetName (cvarBuffer , CVS_CVAR_MAXLEN );
275+ (existingEntry .CVSE_cvar ).GetName (cvarBuffer , CVS_CVAR_MAXLEN );
270276
271277 if (strcmp (cvar , cvarBuffer , false ) == 0 ) {
272278 Debug_LogError (CVS_MODULE_NAME , " Attempt to track ConVar %s , which is already being tracked." , cvar );
273279 return ;
274280 }
275281 }
276282
277- newCvar .GetString (cvarBuffer , CVS_CVAR_MAXLEN );
283+ int iPendingSize = PendingCvarsArray .Length ;
284+ CVSPending pendingEntry ;
285+
286+ for (int i = 0 ; i < iPendingSize ; i ++ ) {
287+ PendingCvarsArray .GetArray (i , pendingEntry , sizeof (pendingEntry ));
288+
289+ if (strcmp (cvar , pendingEntry .CVSP_name , false ) == 0 ) {
290+ Debug_LogError (CVS_MODULE_NAME , " Attempt to track ConVar %s , which is already pending late-bind." , cvar );
291+ return ;
292+ }
293+ }
294+
295+ ConVar newCvar = FindConVar (cvar );
278296
279- newEntry .CVSE_cvar = newCvar ;
297+ if (newCvar == null ) {
298+ // Owning plugin may not be loaded yet; retry from CVS_OnConfigsExecuted.
299+ strcopy (pendingEntry .CVSP_name , CVS_CVAR_MAXLEN , cvar );
300+ strcopy (pendingEntry .CVSP_newval , CVS_CVAR_MAXLEN , newval );
301+ PendingCvarsArray .PushArray (pendingEntry , sizeof (pendingEntry ));
302+
303+ #if CVARS_DEBUG
304+ LogMessage (" [%s ] Pending late-bind for cvar = %s , newval = %s " , CVS_MODULE_NAME , cvar , newval );
305+ #endif
306+ return ;
307+ }
308+
309+ PushTrackedCvar (newCvar , newval );
310+ }
311+
312+ static void PushTrackedCvar (ConVar cvar , const char [] newval )
313+ {
314+ char cvarBuffer [CVS_CVAR_MAXLEN ];
315+ cvar .GetString (cvarBuffer , CVS_CVAR_MAXLEN );
316+
317+ CVSEntry newEntry ;
318+ newEntry .CVSE_cvar = cvar ;
280319 strcopy (newEntry .CVSE_oldval , CVS_CVAR_MAXLEN , cvarBuffer );
281320 strcopy (newEntry .CVSE_newval , CVS_CVAR_MAXLEN , newval );
282321
283- newCvar .AddChangeHook (CVS_ConVarChange );
322+ cvar .AddChangeHook (CVS_ConVarChange );
284323
285324#if CVARS_DEBUG
286- LogMessage (" [%s ] cvar = %s , newval = %s , oldval = %s " , CVS_MODULE_NAME , cvar , newval , cvarBuffer );
325+ char cvarName [CVS_CVAR_MAXLEN ];
326+ cvar .GetName (cvarName , sizeof (cvarName ));
327+ LogMessage (" [%s ] cvar = %s , newval = %s , oldval = %s " , CVS_MODULE_NAME , cvarName , newval , cvarBuffer );
287328#endif
288329
289330 CvarSettingsArray .PushArray (newEntry , sizeof (newEntry ));
290331}
291332
333+ static void ResolvePendingCvars ()
334+ {
335+ int iSize = PendingCvarsArray .Length ;
336+ if (iSize == 0 ) {
337+ return ;
338+ }
339+
340+ CVSPending pendingEntry ;
341+
342+ // Reverse iteration so Erase() doesn't shift entries we haven't visited.
343+ for (int i = iSize - 1 ; i >= 0 ; i -- ) {
344+ PendingCvarsArray .GetArray (i , pendingEntry , sizeof (pendingEntry ));
345+
346+ ConVar resolved = FindConVar (pendingEntry .CVSP_name );
347+ if (resolved == null ) {
348+ continue ;
349+ }
350+
351+ PushTrackedCvar (resolved , pendingEntry .CVSP_newval );
352+ PendingCvarsArray .Erase (i );
353+ }
354+ }
355+
292356static void CVS_ConVarChange (ConVar hConVar , const char [] sOldValue , const char [] sNewValue )
293357{
294358 if (bTrackingStarted ) {
0 commit comments