using Sandbox.Network;
using System;
using System.Collections.Generic;
namespace Sandbox;
internal class ReplicatedConvars
{
public StringTable StringTable { get; init; }
public ReplicatedConvars( string name )
{
StringTable = new( name, true );
StringTable.OnChangeOrAdd += OnTableEntryUpdated;
StringTable.OnRemoved += OnTableEntryRemoved;
StringTable.OnSnapshot += OnTableSnapshot;
ConVarSystem.ConVarChanged += OnConVarChanged;
}
///
/// Should be called after the assemblies are loaded. We'll update all the replicated convars now.
///
public void OnAssembliesLoaded()
{
if ( !Networking.IsHost )
return;
foreach ( var convar in ConVarSystem.Members.Values )
{
if ( !convar.IsReplicated ) continue;
StringTable.SetString( convar.Name, convar.Value );
}
}
public void Reset()
{
StringTable.Reset();
}
///
/// Called any time a ConVar changes.
///
void OnConVarChanged( Command convar, string oldValue )
{
if ( !Networking.IsHost ) return;
if ( !convar.IsReplicated ) return;
StringTable.SetString( convar.Name, convar.Value );
}
void OnTableEntryUpdated( StringTable.Entry entry )
{
if ( Networking.IsHost ) return; // host table shouldn't update host table!
var newValue = entry.ReadAsString();
// no change
if ( _values.GetValueOrDefault( entry.Name ) == newValue )
return;
_values[entry.Name] = newValue;
Log.Info( $"Replicated Var Changed: {entry.Name} = {newValue}" );
// TODO - if we have a notice flag, broadcast to the game somehow
}
void OnTableEntryRemoved( StringTable.Entry entry )
{
}
void OnTableSnapshot()
{
_values.Clear();
foreach ( var (_, entry) in StringTable.Entries )
{
OnTableEntryUpdated( entry );
}
}
private readonly Dictionary _values = new( StringComparer.OrdinalIgnoreCase );
///
/// Get the value of a replicated ConVar.
///
public bool TryGetValue( string name, out string value )
{
return _values.TryGetValue( name, out value );
}
}