diff --git a/managed/src/SwiftlyS2.Core/Modules/Convars/ConVar.cs b/managed/src/SwiftlyS2.Core/Modules/Convars/ConVar.cs index 84eb439ed..fd63e3f39 100644 --- a/managed/src/SwiftlyS2.Core/Modules/Convars/ConVar.cs +++ b/managed/src/SwiftlyS2.Core/Modules/Convars/ConVar.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using SwiftlyS2.Core.Natives; using SwiftlyS2.Shared.Convars; using SwiftlyS2.Shared.Natives; @@ -10,383 +11,530 @@ namespace SwiftlyS2.Core.Convars; internal delegate void ConVarCallbackDelegate( int playerId, nint name, nint value ); -internal class ConVar : IConVar +internal class ConVar : IConVar { + private Dictionary _callbacks = new(); + private Lock _lock = new(); + protected nint _minValuePtrPtr => NativeConvars.GetMinValuePtrPtr(Name); + protected nint _maxValuePtrPtr => NativeConvars.GetMaxValuePtrPtr(Name); - private Dictionary _callbacks = new(); - private Lock _lock = new(); - - private nint _minValuePtrPtr => NativeConvars.GetMinValuePtrPtr(Name); - private nint _maxValuePtrPtr => NativeConvars.GetMaxValuePtrPtr(Name); - - public EConVarType Type => (EConVarType)NativeConvars.GetConvarType(Name); - - private bool IsValidType => Type > EConVarType.EConVarType_Invalid && Type < EConVarType.EConVarType_MAX; - - // im not sure - private bool IsMinMaxType => IsValidType && Type != EConVarType.EConVarType_String && Type != EConVarType.EConVarType_Color; - - public T MinValue { - get => GetMinValue(); - set => SetMinValue(value); - } - public T MaxValue { - get => GetMaxValue(); - set => SetMaxValue(value); - } - - public T DefaultValue { - get => GetDefaultValue(); - set => SetDefaultValue(value); - } - - public ConvarFlags Flags { - get => (ConvarFlags)NativeConvars.GetFlags(Name); - set => NativeConvars.SetFlags(Name, (ulong)value); - } - - public bool HasDefaultValue => NativeConvars.HasDefaultValue(Name); - - public bool HasMinValue => _minValuePtrPtr.Read() != 0; - public bool HasMaxValue => _maxValuePtrPtr.Read() != 0; - - public string Name { get; set; } - - internal ConVar( string name ) - { - Name = name; - - ValidateType(); - } - - public void ValidateType() - { - if ( - (typeof(T) == typeof(bool) && Type != EConVarType.EConVarType_Bool) || - (typeof(T) == typeof(short) && Type != EConVarType.EConVarType_Int16) || - (typeof(T) == typeof(ushort) && Type != EConVarType.EConVarType_UInt16) || - (typeof(T) == typeof(int) && Type != EConVarType.EConVarType_Int32) || - (typeof(T) == typeof(uint) && Type != EConVarType.EConVarType_UInt32) || - (typeof(T) == typeof(float) && Type != EConVarType.EConVarType_Float32) || - (typeof(T) == typeof(long) && Type != EConVarType.EConVarType_Int64) || - (typeof(T) == typeof(ulong) && Type != EConVarType.EConVarType_UInt64) || - (typeof(T) == typeof(double) && Type != EConVarType.EConVarType_Float64) || - (typeof(T) == typeof(Color) && Type != EConVarType.EConVarType_Color) || - (typeof(T) == typeof(QAngle) && Type != EConVarType.EConVarType_Qangle) || - (typeof(T) == typeof(Vector) && Type != EConVarType.EConVarType_Vector3) || - (typeof(T) == typeof(Vector2D) && Type != EConVarType.EConVarType_Vector2) || - (typeof(T) == typeof(Vector4D) && Type != EConVarType.EConVarType_Vector4) || - (typeof(T) == typeof(string) && Type != EConVarType.EConVarType_String) - ) - { - throw new Exception($"Type mismatch for convar {Name}. The real type is {Type}."); - } - } + public string Name { get; set; } - public T Value { - get => GetValue(); - set => SetValue(value); - } + public EConVarType Type => (EConVarType)NativeConvars.GetConvarType(Name); - public void ReplicateToClient( int clientId, T value ) - { - var val = ""; - if (value is bool boolValue) - { - val = boolValue ? "1" : "0"; + public bool HasDefaultValue => NativeConvars.HasDefaultValue(Name); + + public bool HasMinValue => _minValuePtrPtr.Read() != 0; + + public bool HasMaxValue => _maxValuePtrPtr.Read() != 0; + + public string ValueAsString { + get => GetValueAsString(); + set => SetValueAsString(value); } - else if (value is short shortValue) - { - val = shortValue.ToString(); + + public string MaxValueAsString { + get => GetMaxValueAsString(); + set => SetMaxValueAsString(value); } - else if (value is ushort ushortValue) - { - val = ushortValue.ToString(); + + public string MinValueAsString { + get => GetMinValueAsString(); + set => SetMinValueAsString(value); } - else if (value is int intValue) - { - val = intValue.ToString(); + + public string DefaultValueAsString { + get => GetDefaultValueAsString(); + set => SetDefaultValueAsString(value); } - else if (value is uint uintValue) - { - val = uintValue.ToString(); + + public ConvarFlags Flags { + get => (ConvarFlags)NativeConvars.GetFlags(Name); + set => NativeConvars.SetFlags(Name, (ulong)value); } - else if (value is float floatValue) + + internal ConVar( string name ) { - val = floatValue.ToString(); + Name = name; } - else if (value is long longValue) + + public void SetInternalAsString( string value ) { - val = longValue.ToString(); + NativeConvars.SetValueInternalAsString(Name, value); } - else if (value is ulong ulongValue) + + private void SetValueAsString( string value ) { - val = ulongValue.ToString(); + var success = NativeConvars.SetValueAsString(Name, value); + if (!success) + { + throw new ArgumentException($"Failed to set value of convar {Name} (type {Type}) to {value}."); + } } - else if (value is double doubleValue) + + private string GetValueAsString() { - val = doubleValue.ToString(); + return NativeConvars.GetValueAsString(Name); } - else if (value is Color colorValue) + + private void SetDefaultValueAsString( string value ) { - val = $"{colorValue.R},{colorValue.G},{colorValue.B}"; + var success = NativeConvars.SetDefaultValueAsString(Name, value); + if (!success) + { + throw new ArgumentException($"Failed to set default value of convar {Name} (type {Type}) to {value}."); + } } - else if (value is QAngle qAngleValue) + + + private string GetDefaultValueAsString() { - val = $"{qAngleValue.Pitch},{qAngleValue.Yaw},{qAngleValue.Roll}"; + return NativeConvars.GetDefaultValueAsString(Name); } - else if (value is Vector vectorValue) + + private void SetMinValueAsString( string value ) { - val = $"{vectorValue.X},{vectorValue.Y},{vectorValue.Z}"; + var success = NativeConvars.SetMinValueAsString(Name, value); + if (!success) + { + throw new ArgumentException($"Failed to set min value of convar {Name} (type {Type}) to {value}."); + } } - else if (value is Vector2D vector2DValue) + + private string GetMinValueAsString() { - val = $"{vector2DValue.X},{vector2DValue.Y}"; + return NativeConvars.GetMinValueAsString(Name); } - else if (value is Vector4D vector4DValue) + + private void SetMaxValueAsString( string value ) { - val = $"{vector4DValue.X},{vector4DValue.Y},{vector4DValue.Z},{vector4DValue.W}"; + var success = NativeConvars.SetMaxValueAsString(Name, value); + if (!success) + { + throw new ArgumentException($"Failed to set max value of convar {Name} (type {Type}) to {value}."); + } } - else if (value is string stringValue) + + private string GetMaxValueAsString() { - val = stringValue; + return NativeConvars.GetMaxValueAsString(Name); } - else throw new ArgumentException($"Invalid type {typeof(T).Name}"); - NativeConvars.SetClientConvarValueString(clientId, Name, val); - } + public void QueryClient( int clientId, Action callback ) + { + Action? removeSelf = null; + ConVarCallbackDelegate nativeCallback = ( playerId, namePtr, valuePtr ) => + { + if (clientId != playerId) return; + var name = Marshal.PtrToStringAnsi(namePtr); + if (name != Name) return; + var value = Marshal.PtrToStringAnsi(valuePtr)!; - public void QueryClient( int clientId, Action callback ) - { + // var convertedValue = (T)Convert.ChangeType(value, typeof(T))!; + callback(value); + if (removeSelf != null) removeSelf(); + }; - Action? removeSelf = null; - ConVarCallbackDelegate nativeCallback = ( playerId, namePtr, valuePtr ) => - { - if (clientId != playerId) return; - var name = Marshal.PtrToStringAnsi(namePtr); - if (name != Name) return; - var value = Marshal.PtrToStringAnsi(valuePtr)!; - // var convertedValue = (T)Convert.ChangeType(value, typeof(T))!; - callback(value); - if (removeSelf != null) removeSelf(); - }; + var callbackPtr = Marshal.GetFunctionPointerForDelegate(nativeCallback); + var listenerId = NativeConvars.AddQueryClientCvarCallback(callbackPtr); + lock (_lock) + { + _callbacks[listenerId] = nativeCallback; + } - var callbackPtr = Marshal.GetFunctionPointerForDelegate(nativeCallback); + removeSelf = () => + { + lock (_lock) + { + _callbacks.Remove(listenerId); + NativeConvars.RemoveQueryClientCvarCallback(listenerId); + } + }; - var listenerId = NativeConvars.AddQueryClientCvarCallback(callbackPtr); - lock (_lock) - { - _callbacks[listenerId] = nativeCallback; + NativeConvars.QueryClientConvar(clientId, Name); } - removeSelf = () => - { - lock (_lock) - { - _callbacks.Remove(listenerId); - NativeConvars.RemoveQueryClientCvarCallback(listenerId); - } - }; - - NativeConvars.QueryClientConvar(clientId, Name); - } - - public T GetValue() - { - unsafe - { - if (Type != EConVarType.EConVarType_String) - { - return *(T*)NativeConvars.GetValuePtr(Name); - } - else - { - return (T)(object)(*(CUtlString*)NativeConvars.GetValuePtr(Name)).Value; - } - } - } - - public void SetValue( T value ) - { - unsafe - { - if (Type != EConVarType.EConVarType_String) - { - NativeConvars.SetValuePtr(Name, (nint)(&value)); - } - else - { - CUtlString str = new(); - str.Value = (string)(object)value; - NativeConvars.SetValuePtr(Name, (nint)(&str)); - } - } - } - - - public void SetInternal( T value ) - { - unsafe - { - if (Type != EConVarType.EConVarType_String) - { - NativeConvars.SetValueInternalPtr(Name, (nint)(&value)); - } - else - { - CUtlString str = new(); - str.Value = (string)(object)value; - NativeConvars.SetValueInternalPtr(Name, (nint)(&str)); - } - } - } - - - public T GetMinValue() - { - if (!IsMinMaxType) + public void ReplicateToClientAsString( int clientId, string value ) { - throw new Exception($"Convar {Name} is not a min/max type."); + NativeConvars.SetClientConvarValueString(clientId, Name, value); } - if (!HasMinValue) - { - throw new Exception($"Convar {Name} doesn't have a min value."); - } - unsafe - { - return **(T**)_minValuePtrPtr; - } - } - public T GetMaxValue() - { - if (!IsMinMaxType) - { - throw new Exception($"Convar {Name} is not a min/max type."); - } - if (!HasMaxValue) - { - throw new Exception($"Convar {Name} doesn't have a max value."); - } - unsafe + public bool TryGetDefaultValueAsString( out string defaultValue ) { - return **(T**)_maxValuePtrPtr; - } - } - public void SetMinValue( T minValue ) - { - if (!IsMinMaxType) - { - throw new Exception($"Convar {Name} is not a min/max type."); + defaultValue = ""; + if (!HasDefaultValue) + { + return false; + } + + defaultValue = GetDefaultValueAsString(); + return true; } - unsafe + + public bool TryGetMinValueAsString( out string minValue ) { - if (_minValuePtrPtr.Read() == nint.Zero) - { - _minValuePtrPtr.Write(NativeAllocator.Alloc(16)); - } - **(T**)_minValuePtrPtr = minValue; + minValue = ""; + if (!HasMinValue) + { + return false; + } + + minValue = GetMinValueAsString(); + return true; } - } - public void SetMaxValue( T maxValue ) - { - if (!IsMinMaxType) + public bool TryGetMaxValueAsString( out string maxValue ) { - throw new Exception($"Convar {Name} is not a min/max type."); + maxValue = ""; + if (!HasMaxValue) + { + return false; + } + + maxValue = GetMaxValueAsString(); + return true; } - unsafe - { - if (_maxValuePtrPtr.Read() == nint.Zero) - { - _maxValuePtrPtr.Write(NativeAllocator.Alloc(16)); - } - **(T**)_maxValuePtrPtr = maxValue; +} + +internal class ConVar : ConVar, IConVar +{ + private bool IsValidType => Type > EConVarType.EConVarType_Invalid && Type < EConVarType.EConVarType_MAX; + + // im not sure + private bool IsMinMaxType => + IsValidType && Type != EConVarType.EConVarType_String && Type != EConVarType.EConVarType_Color; + + public T MinValue { + get => GetMinValue(); + set => SetMinValue(value); + } + + public T MaxValue { + get => GetMaxValue(); + set => SetMaxValue(value); + } + + public T DefaultValue { + get => GetDefaultValue(); + set => SetDefaultValue(value); + } + + + internal ConVar( string name ) : base(name) + { + ValidateType(); + } + + public void ValidateType() + { + if ( + (typeof(T) == typeof(bool) && Type != EConVarType.EConVarType_Bool) || + (typeof(T) == typeof(short) && Type != EConVarType.EConVarType_Int16) || + (typeof(T) == typeof(ushort) && Type != EConVarType.EConVarType_UInt16) || + (typeof(T) == typeof(int) && Type != EConVarType.EConVarType_Int32) || + (typeof(T) == typeof(uint) && Type != EConVarType.EConVarType_UInt32) || + (typeof(T) == typeof(float) && Type != EConVarType.EConVarType_Float32) || + (typeof(T) == typeof(long) && Type != EConVarType.EConVarType_Int64) || + (typeof(T) == typeof(ulong) && Type != EConVarType.EConVarType_UInt64) || + (typeof(T) == typeof(double) && Type != EConVarType.EConVarType_Float64) || + (typeof(T) == typeof(Color) && Type != EConVarType.EConVarType_Color) || + (typeof(T) == typeof(QAngle) && Type != EConVarType.EConVarType_Qangle) || + (typeof(T) == typeof(Vector) && Type != EConVarType.EConVarType_Vector3) || + (typeof(T) == typeof(Vector2D) && Type != EConVarType.EConVarType_Vector2) || + (typeof(T) == typeof(Vector4D) && Type != EConVarType.EConVarType_Vector4) || + (typeof(T) == typeof(string) && Type != EConVarType.EConVarType_String) + ) + { + throw new Exception($"Type mismatch for convar {Name}. The real type is {Type}."); + } + } + + public T Value { + get => GetValue(); + set => SetValue(value); + } + + public void ReplicateToClient( int clientId, T value ) + { + var val = ""; + if (value is bool boolValue) + { + val = boolValue ? "1" : "0"; + } + else if (value is short shortValue) + { + val = shortValue.ToString(); + } + else if (value is ushort ushortValue) + { + val = ushortValue.ToString(); + } + else if (value is int intValue) + { + val = intValue.ToString(); + } + else if (value is uint uintValue) + { + val = uintValue.ToString(); + } + else if (value is float floatValue) + { + val = floatValue.ToString(); + } + else if (value is long longValue) + { + val = longValue.ToString(); + } + else if (value is ulong ulongValue) + { + val = ulongValue.ToString(); + } + else if (value is double doubleValue) + { + val = doubleValue.ToString(); + } + else if (value is Color colorValue) + { + val = $"{colorValue.R},{colorValue.G},{colorValue.B}"; + } + else if (value is QAngle qAngleValue) + { + val = $"{qAngleValue.Pitch},{qAngleValue.Yaw},{qAngleValue.Roll}"; + } + else if (value is Vector vectorValue) + { + val = $"{vectorValue.X},{vectorValue.Y},{vectorValue.Z}"; + } + else if (value is Vector2D vector2DValue) + { + val = $"{vector2DValue.X},{vector2DValue.Y}"; + } + else if (value is Vector4D vector4DValue) + { + val = $"{vector4DValue.X},{vector4DValue.Y},{vector4DValue.Z},{vector4DValue.W}"; + } + else if (value is string stringValue) + { + val = stringValue; + } + else throw new ArgumentException($"Invalid type {typeof(T).Name}"); + + NativeConvars.SetClientConvarValueString(clientId, Name, val); + } + + + public T GetValue() + { + unsafe + { + if (Type != EConVarType.EConVarType_String) + { + return *(T*)NativeConvars.GetValuePtr(Name); + } + else + { + return (T)(object)(*(CUtlString*)NativeConvars.GetValuePtr(Name)).Value; + } + } + } + + public void SetValue( T value ) + { + unsafe + { + if (Type != EConVarType.EConVarType_String) + { + NativeConvars.SetValuePtr(Name, (nint)(&value)); + } + else + { + CUtlString str = new(); + str.Value = (string)(object)value; + NativeConvars.SetValuePtr(Name, (nint)(&str)); + } + } + } + + + public void SetInternal( T value ) + { + unsafe + { + if (Type != EConVarType.EConVarType_String) + { + NativeConvars.SetValueInternalPtr(Name, (nint)(&value)); + } + else + { + CUtlString str = new(); + str.Value = (string)(object)value; + NativeConvars.SetValueInternalPtr(Name, (nint)(&str)); + } + } + } + + + public T GetMinValue() + { + if (!IsMinMaxType) + { + throw new Exception($"Convar {Name} is not a min/max type."); + } + + if (!HasMinValue) + { + throw new Exception($"Convar {Name} doesn't have a min value."); + } + + unsafe + { + return **(T**)_minValuePtrPtr; + } + } + + public T GetMaxValue() + { + if (!IsMinMaxType) + { + throw new Exception($"Convar {Name} is not a min/max type."); + } + + if (!HasMaxValue) + { + throw new Exception($"Convar {Name} doesn't have a max value."); + } + + unsafe + { + return **(T**)_maxValuePtrPtr; + } + } + + public void SetMinValue( T minValue ) + { + if (!IsMinMaxType) + { + throw new Exception($"Convar {Name} is not a min/max type."); + } + + unsafe + { + if (_minValuePtrPtr.Read() == nint.Zero) + { + _minValuePtrPtr.Write(NativeAllocator.Alloc(16)); + } + + **(T**)_minValuePtrPtr = minValue; + } + } + + public void SetMaxValue( T maxValue ) + { + if (!IsMinMaxType) + { + throw new Exception($"Convar {Name} is not a min/max type."); + } + + unsafe + { + if (_maxValuePtrPtr.Read() == nint.Zero) + { + _maxValuePtrPtr.Write(NativeAllocator.Alloc(16)); + } + + **(T**)_maxValuePtrPtr = maxValue; + } } - } - public T GetDefaultValue() - { - unsafe - { - var ptr = NativeConvars.GetDefaultValuePtr(Name); - if (ptr == nint.Zero) - { - throw new Exception($"Convar {Name} doesn't have a default value."); - } - if (Type != EConVarType.EConVarType_String) - { - return *(T*)ptr; - } - else - { - return (T)(object)(*(CUtlString*)ptr).Value; - } - } - } - - public void SetDefaultValue( T defaultValue ) - { - unsafe + public T GetDefaultValue() { - var ptr = NativeConvars.GetDefaultValuePtr(Name); - if (ptr == nint.Zero) - { - throw new Exception($"Convar {Name} doesn't have a default value."); - } - if (Type != EConVarType.EConVarType_String) - { - *(T*)NativeConvars.GetDefaultValuePtr(Name) = defaultValue; - } - else - { - NativeConvars.GetDefaultValuePtr(Name).Write(StringPool.Allocate((string)(object)defaultValue)); - } - } - } - - public bool TryGetMinValue( out T minValue ) - { - if (!IsMinMaxType) - { - minValue = default; - return false; + unsafe + { + var ptr = NativeConvars.GetDefaultValuePtr(Name); + if (ptr == nint.Zero) + { + throw new Exception($"Convar {Name} doesn't have a default value."); + } + + if (Type != EConVarType.EConVarType_String) + { + return *(T*)ptr; + } + else + { + return (T)(object)(*(CUtlString*)ptr).Value; + } + } } - if (!HasMinValue) + + public void SetDefaultValue( T defaultValue ) { - minValue = default; - return false; + unsafe + { + var ptr = NativeConvars.GetDefaultValuePtr(Name); + if (ptr == nint.Zero) + { + throw new Exception($"Convar {Name} doesn't have a default value."); + } + + if (Type != EConVarType.EConVarType_String) + { + *(T*)NativeConvars.GetDefaultValuePtr(Name) = defaultValue; + } + else + { + NativeConvars.GetDefaultValuePtr(Name).Write(StringPool.Allocate((string)(object)defaultValue)); + } + } } - minValue = GetMinValue(); - return true; - } - public bool TryGetMaxValue( out T maxValue ) - { - if (!IsMinMaxType) + public bool TryGetMinValue( out T minValue ) { - maxValue = default; - return false; + if (!IsMinMaxType) + { + minValue = default; + return false; + } + + if (!HasMinValue) + { + minValue = default; + return false; + } + + minValue = GetMinValue(); + return true; } - if (!HasMaxValue) + + public bool TryGetMaxValue( out T maxValue ) { - maxValue = default; - return false; + if (!IsMinMaxType) + { + maxValue = default; + return false; + } + + if (!HasMaxValue) + { + maxValue = default; + return false; + } + + maxValue = GetMaxValue(); + return true; } - maxValue = GetMaxValue(); - return true; - } - public bool TryGetDefaultValue( out T defaultValue ) - { - if (!HasDefaultValue) + public bool TryGetDefaultValue( out T defaultValue ) { - defaultValue = default; - return false; + if (!HasDefaultValue) + { + defaultValue = default; + return false; + } + + defaultValue = GetDefaultValue(); + return true; } - defaultValue = GetDefaultValue(); - return true; - } } diff --git a/managed/src/SwiftlyS2.Core/Modules/Convars/ConVarService.cs b/managed/src/SwiftlyS2.Core/Modules/Convars/ConVarService.cs index b85240346..913e88fff 100644 --- a/managed/src/SwiftlyS2.Core/Modules/Convars/ConVarService.cs +++ b/managed/src/SwiftlyS2.Core/Modules/Convars/ConVarService.cs @@ -4,488 +4,280 @@ namespace SwiftlyS2.Core.Convars; +internal enum EConVarType : int +{ + EConVarType_Invalid = -1, + EConVarType_Bool, + EConVarType_Int16, + EConVarType_UInt16, + EConVarType_Int32, + EConVarType_UInt32, + EConVarType_Int64, + EConVarType_UInt64, + EConVarType_Float32, + EConVarType_Float64, + EConVarType_String, + EConVarType_Color, + EConVarType_Vector2, + EConVarType_Vector3, + EConVarType_Vector4, + EConVarType_Qangle, + EConVarType_MAX +}; + internal class ConVarService : IConVarService { - public IConVar? Find( string name ) - { - - if (!NativeConvars.ExistsConvar(name)) - { - return null; - } - - return new ConVar(name); - - } - - public IConVar Create( string name, string helpMessage, T defaultValue, ConvarFlags flags = ConvarFlags.NONE ) - { - if (NativeConvars.ExistsConvar(name)) - { - throw new Exception($"Convar {name} already exists."); - } - - if (defaultValue is bool boolValue) - { - NativeConvars.CreateConvarBool(name, (int)EConVarType.EConVarType_Bool, (ulong)flags, helpMessage, boolValue, 0, 0); - } - else if (defaultValue is short shortValue) - { - NativeConvars.CreateConvarInt16(name, (int)EConVarType.EConVarType_Int16, (ulong)flags, helpMessage, shortValue, 0, 0); - } - else if (defaultValue is ushort ushortValue) - { - NativeConvars.CreateConvarUInt16(name, (int)EConVarType.EConVarType_UInt16, (ulong)flags, helpMessage, ushortValue, 0, 0); - } - else if (defaultValue is int intValue) - { - NativeConvars.CreateConvarInt32(name, (int)EConVarType.EConVarType_Int32, (ulong)flags, helpMessage, intValue, 0, 0); - } - else if (defaultValue is uint uintValue) - { - NativeConvars.CreateConvarUInt32(name, (int)EConVarType.EConVarType_UInt32, (ulong)flags, helpMessage, uintValue, 0, 0); - } - else if (defaultValue is long longValue) - { - NativeConvars.CreateConvarInt64(name, (int)EConVarType.EConVarType_Int64, (ulong)flags, helpMessage, longValue, 0, 0); - } - else if (defaultValue is ulong ulongValue) - { - NativeConvars.CreateConvarUInt64(name, (int)EConVarType.EConVarType_UInt64, (ulong)flags, helpMessage, ulongValue, 0, 0); - } - else if (defaultValue is float floatValue) - { - NativeConvars.CreateConvarFloat(name, (int)EConVarType.EConVarType_Float32, (ulong)flags, helpMessage, floatValue, 0, 0); - } - else if (defaultValue is double doubleValue) - { - NativeConvars.CreateConvarDouble(name, (int)EConVarType.EConVarType_Float64, (ulong)flags, helpMessage, doubleValue, 0, 0); - } - else if (defaultValue is Vector2D vector2Value) - { - NativeConvars.CreateConvarVector2D(name, (int)EConVarType.EConVarType_Vector2, (ulong)flags, helpMessage, vector2Value, 0, 0); - } - else if (defaultValue is Vector vector3Value) - { - NativeConvars.CreateConvarVector(name, (int)EConVarType.EConVarType_Vector3, (ulong)flags, helpMessage, vector3Value, 0, 0); - } - else if (defaultValue is Vector4D vector4Value) - { - NativeConvars.CreateConvarVector4D(name, (int)EConVarType.EConVarType_Vector4, (ulong)flags, helpMessage, vector4Value, 0, 0); - } - else if (defaultValue is QAngle qAngleValue) - { - NativeConvars.CreateConvarQAngle(name, (int)EConVarType.EConVarType_Qangle, (ulong)flags, helpMessage, qAngleValue, 0, 0); - } - else if (defaultValue is Color colorValue) - { - NativeConvars.CreateConvarColor(name, (int)EConVarType.EConVarType_Color, (ulong)flags, helpMessage, colorValue, 0, 0); - } - else if (defaultValue is string stringValue) - { - NativeConvars.CreateConvarString(name, (int)EConVarType.EConVarType_String, (ulong)flags, helpMessage, stringValue, 0, 0); - } - else - { - throw new Exception($"Unsupported type {typeof(T)}."); - } - - return new ConVar(name); - } - - public IConVar Create( string name, string helpMessage, T defaultValue, T? minValue, T? maxValue, ConvarFlags flags = ConvarFlags.NONE ) where T : unmanaged - { - - if (NativeConvars.ExistsConvar(name)) - { - throw new Exception($"Convar {name} already exists."); - } - unsafe - { - - if (defaultValue is short shortValue) - { - short* pMin = stackalloc short[1]; - if (minValue.HasValue) - { - pMin[0] = (short)(object)minValue.Value; - } - - short* pMax = stackalloc short[1]; - if (maxValue.HasValue) - { - pMax[0] = (short)(object)maxValue.Value; - } - - NativeConvars.CreateConvarInt16(name, (int)EConVarType.EConVarType_Int16, (ulong)flags, helpMessage, shortValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); - } - else if (defaultValue is ushort ushortValue) - { - ushort* pMin = stackalloc ushort[1]; - if (minValue.HasValue) - { - pMin[0] = (ushort)(object)minValue.Value; - } - - ushort* pMax = stackalloc ushort[1]; - if (maxValue.HasValue) - { - pMax[0] = (ushort)(object)maxValue.Value; - } - - NativeConvars.CreateConvarUInt16(name, (int)EConVarType.EConVarType_UInt16, (ulong)flags, helpMessage, ushortValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); - } - else if (defaultValue is int intValue) - { - int* pMin = stackalloc int[1]; - if (minValue.HasValue) - { - pMin[0] = (int)(object)minValue.Value; - } - - int* pMax = stackalloc int[1]; - if (maxValue.HasValue) - { - pMax[0] = (int)(object)maxValue.Value; - } - - NativeConvars.CreateConvarInt32(name, (int)EConVarType.EConVarType_Int32, (ulong)flags, helpMessage, intValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); - } - else if (defaultValue is uint uintValue) - { - uint* pMin = stackalloc uint[1]; - if (minValue.HasValue) - { - pMin[0] = (uint)(object)minValue.Value; - } - - uint* pMax = stackalloc uint[1]; - if (maxValue.HasValue) - { - pMax[0] = (uint)(object)maxValue.Value; - } - - NativeConvars.CreateConvarUInt32(name, (int)EConVarType.EConVarType_UInt32, (ulong)flags, helpMessage, uintValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); - } - else if (defaultValue is long longValue) - { - long* pMin = stackalloc long[1]; - if (minValue.HasValue) - { - pMin[0] = (long)(object)minValue.Value; - } - - long* pMax = stackalloc long[1]; - if (maxValue.HasValue) - { - pMax[0] = (long)(object)maxValue.Value; - } - - NativeConvars.CreateConvarInt64(name, (int)EConVarType.EConVarType_Int64, (ulong)flags, helpMessage, longValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); - } - else if (defaultValue is ulong ulongValue) - { - ulong* pMin = stackalloc ulong[1]; - if (minValue.HasValue) - { - pMin[0] = (ulong)(object)minValue.Value; - } - - ulong* pMax = stackalloc ulong[1]; - if (maxValue.HasValue) - { - pMax[0] = (ulong)(object)maxValue.Value; - } - - NativeConvars.CreateConvarUInt64(name, (int)EConVarType.EConVarType_UInt64, (ulong)flags, helpMessage, ulongValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); - } - else if (defaultValue is float floatValue) - { - float* pMin = stackalloc float[1]; - if (minValue.HasValue) - { - pMin[0] = (float)(object)minValue.Value; - } - - float* pMax = stackalloc float[1]; - if (maxValue.HasValue) - { - pMax[0] = (float)(object)maxValue.Value; - } - - NativeConvars.CreateConvarFloat(name, (int)EConVarType.EConVarType_Float32, (ulong)flags, helpMessage, floatValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); - } - else if (defaultValue is double doubleValue) - { - double* pMin = stackalloc double[1]; - if (minValue.HasValue) - { - pMin[0] = (double)(object)minValue.Value; - } - - double* pMax = stackalloc double[1]; - if (maxValue.HasValue) - { - pMax[0] = (double)(object)maxValue.Value; - } - - NativeConvars.CreateConvarDouble(name, (int)EConVarType.EConVarType_Float64, (ulong)flags, helpMessage, doubleValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); - } - else - { - throw new Exception($"You can't assign min and max values to {typeof(T)}."); - } - } - - return new ConVar(name); - } - - public IConVar CreateOrFind( string name, string helpMessage, T defaultValue, ConvarFlags flags = ConvarFlags.NONE ) - { - return NativeConvars.ExistsConvar(name) ? new ConVar(name) : Create(name, helpMessage, defaultValue, flags); - } - - public IConVar CreateOrFind( string name, string helpMessage, T defaultValue, T? minValue, T? maxValue, ConvarFlags flags = ConvarFlags.NONE ) where T : unmanaged - { - return NativeConvars.ExistsConvar(name) ? new ConVar(name) : Create(name, helpMessage, defaultValue, minValue, maxValue, flags); - } - - public string? ReadValueAsString( string name ) - { - if (!NativeConvars.ExistsConvar(name)) return null; - - var type = (EConVarType)NativeConvars.GetConvarType(name); - - var valuePtr = NativeConvars.GetValuePtr(name); - - return GetValueFromPtr(type, valuePtr); - } - - private unsafe string GetValueFromPtr( EConVarType kind, nint ptr ) - { - return kind switch { - EConVarType.EConVarType_Bool => *(byte*)ptr == 1 ? "1" : "0", - EConVarType.EConVarType_Invalid => string.Empty, - EConVarType.EConVarType_Int16 => (*(short*)ptr).ToString(), - EConVarType.EConVarType_UInt16 => (*(ushort*)ptr).ToString(), - EConVarType.EConVarType_Int32 => (*(int*)ptr).ToString(), - EConVarType.EConVarType_UInt32 => (*(uint*)ptr).ToString(), - EConVarType.EConVarType_Int64 => (*(long*)ptr).ToString(), - EConVarType.EConVarType_UInt64 => (*(ulong*)ptr).ToString(), - EConVarType.EConVarType_Float32 => (*(float*)ptr).ToString(), - EConVarType.EConVarType_Float64 => (*(double*)ptr).ToString(), - EConVarType.EConVarType_String => ((CUtlString*)ptr)->Value, - EConVarType.EConVarType_Color => $"{(*(Color*)ptr).R},{(*(Color*)ptr).G},{(*(Color*)ptr).B}", - EConVarType.EConVarType_Vector2 => $"{(*(Vector2D*)ptr).X},{(*(Vector2D*)ptr).Y}", - EConVarType.EConVarType_Vector3 => $"{(*(Vector*)ptr).X},{(*(Vector*)ptr).Y},{(*(Vector*)ptr).Z}", - EConVarType.EConVarType_Vector4 => $"{(*(Vector4D*)ptr).X},{(*(Vector4D*)ptr).Y},{(*(Vector4D*)ptr).Z},{(*(Vector4D*)ptr).W}", - EConVarType.EConVarType_Qangle => $"{(*(QAngle*)ptr).Pitch},{(*(QAngle*)ptr).Yaw},{(*(QAngle*)ptr).Roll}", - EConVarType.EConVarType_MAX => string.Empty, - _ => string.Empty, - }; - } - - public unsafe void SetValueAsString( string name, string value ) - { - if (!NativeConvars.ExistsConvar(name)) return; - - var type = (EConVarType)NativeConvars.GetConvarType(name); - - switch (type) - { - case EConVarType.EConVarType_Invalid: - return; - case EConVarType.EConVarType_Bool: - { - if (bool.TryParse(value, out var result)) - { - byte boolValue = result ? (byte)1 : (byte)0; - NativeConvars.SetValuePtr(name, (nint)(&boolValue)); - } - } - break; - case EConVarType.EConVarType_Int16: - { - if (short.TryParse(value, out var shortValue)) - { - NativeConvars.SetValuePtr(name, (nint)(&shortValue)); - } - } - break; - case EConVarType.EConVarType_UInt16: - { - if (ushort.TryParse(value, out var ushortValue)) - { - NativeConvars.SetValuePtr(name, (nint)(&ushortValue)); - } - } - break; - case EConVarType.EConVarType_Int32: - { - if (int.TryParse(value, out var intValue)) - { - NativeConvars.SetValuePtr(name, (nint)(&intValue)); - } - } - break; - case EConVarType.EConVarType_UInt32: - { - if (uint.TryParse(value, out var uintValue)) - { - NativeConvars.SetValuePtr(name, (nint)(&uintValue)); - } - } - break; - case EConVarType.EConVarType_Int64: - { - if (long.TryParse(value, out var longValue)) - { - NativeConvars.SetValuePtr(name, (nint)(&longValue)); - } - } - break; - case EConVarType.EConVarType_UInt64: - { - if (ulong.TryParse(value, out var ulongValue)) - { - NativeConvars.SetValuePtr(name, (nint)(&ulongValue)); - } - } - break; - case EConVarType.EConVarType_Float32: - { - if (float.TryParse(value, out var floatValue)) - { - NativeConvars.SetValuePtr(name, (nint)(&floatValue)); - } - } - break; - case EConVarType.EConVarType_Float64: - { - if (double.TryParse(value, out var doubleValue)) - { - NativeConvars.SetValuePtr(name, (nint)(&doubleValue)); - } - } - break; - case EConVarType.EConVarType_String: - { - CUtlString str = new(); - str.Value = value; - NativeConvars.SetValuePtr(name, (nint)(&str)); - } - break; - case EConVarType.EConVarType_Color: - { - var parts = value.Split(','); - if (parts.Length >= 3 && - byte.TryParse(parts[0], out var r) && - byte.TryParse(parts[1], out var g) && - byte.TryParse(parts[2], out var b)) - { - var colorValue = new Color(r, g, b); - NativeConvars.SetValuePtr(name, (nint)(&colorValue)); - } - } - break; - case EConVarType.EConVarType_Vector2: - { - var parts = value.Split(','); - if (parts.Length >= 2 && - float.TryParse(parts[0], out var x) && - float.TryParse(parts[1], out var y)) - { - var vector2Value = new Vector2D(x, y); - NativeConvars.SetValuePtr(name, (nint)(&vector2Value)); - } - } - break; - case EConVarType.EConVarType_Vector3: - { - var parts = value.Split(','); - if (parts.Length >= 3 && - float.TryParse(parts[0], out var x) && - float.TryParse(parts[1], out var y) && - float.TryParse(parts[2], out var z)) - { - var vector3Value = new Vector(x, y, z); - NativeConvars.SetValuePtr(name, (nint)(&vector3Value)); - } - } - break; - case EConVarType.EConVarType_Vector4: - { - var parts = value.Split(','); - if (parts.Length >= 4 && - float.TryParse(parts[0], out var x) && - float.TryParse(parts[1], out var y) && - float.TryParse(parts[2], out var z) && - float.TryParse(parts[3], out var w)) - { - var vector4Value = new Vector4D(x, y, z, w); - NativeConvars.SetValuePtr(name, (nint)(&vector4Value)); - } - } - break; - case EConVarType.EConVarType_Qangle: - { - var parts = value.Split(','); - if (parts.Length >= 3 && - float.TryParse(parts[0], out var pitch) && - float.TryParse(parts[1], out var yaw) && - float.TryParse(parts[2], out var roll)) - { - var qAngleValue = new QAngle(pitch, yaw, roll); - NativeConvars.SetValuePtr(name, (nint)(&qAngleValue)); - } - } - break; - case EConVarType.EConVarType_MAX: - break; - } - } - - public EConVarType GetConVarType( string name ) - { - return !NativeConvars.ExistsConvar(name) ? EConVarType.EConVarType_Invalid : (EConVarType)NativeConvars.GetConvarType(name); - } - - public string? GetDefaultValue( string name ) - { - if (!NativeConvars.ExistsConvar(name)) return null; - - var type = (EConVarType)NativeConvars.GetConvarType(name); - - var valuePtr = NativeConvars.GetDefaultValuePtr(name); - return valuePtr == 0 ? null : GetValueFromPtr(type, valuePtr); - } - - public unsafe string? GetMinValue( string name ) - { - if (!NativeConvars.ExistsConvar(name)) return null; - - var type = (EConVarType)NativeConvars.GetConvarType(name); - - if (type > EConVarType.EConVarType_Invalid && type < EConVarType.EConVarType_MAX && type != EConVarType.EConVarType_String && type != EConVarType.EConVarType_Color) - { - var valuePtr = *(void**)NativeConvars.GetMinValuePtrPtr(name); - return valuePtr == null ? null : GetValueFromPtr(type, (nint)valuePtr); - } - else return null; - } - - public unsafe string? GetMaxValue( string name ) - { - if (!NativeConvars.ExistsConvar(name)) return null; - - var type = (EConVarType)NativeConvars.GetConvarType(name); - - if (type > EConVarType.EConVarType_Invalid && type < EConVarType.EConVarType_MAX && type != EConVarType.EConVarType_String && type != EConVarType.EConVarType_Color) - { - var valuePtr = *(void**)NativeConvars.GetMaxValuePtrPtr(name); - return valuePtr == null ? null : GetValueFromPtr(type, (nint)valuePtr); - } - else return null; - } + public IConVar? Find( string name ) + { + + if (!NativeConvars.ExistsConvar(name)) + { + return null; + } + + return new ConVar(name); + } + + public IConVar? FindAsString( string name ) + { + if (!NativeConvars.ExistsConvar(name)) + { + return null; + } + + return new ConVar(name); + } + + public IConVar Create( string name, string helpMessage, T defaultValue, ConvarFlags flags = ConvarFlags.NONE ) + { + if (NativeConvars.ExistsConvar(name)) + { + throw new Exception($"Convar {name} already exists."); + } + + if (defaultValue is bool boolValue) + { + NativeConvars.CreateConvarBool(name, (int)EConVarType.EConVarType_Bool, (ulong)flags, helpMessage, boolValue, 0, 0); + } + else if (defaultValue is short shortValue) + { + NativeConvars.CreateConvarInt16(name, (int)EConVarType.EConVarType_Int16, (ulong)flags, helpMessage, shortValue, 0, 0); + } + else if (defaultValue is ushort ushortValue) + { + NativeConvars.CreateConvarUInt16(name, (int)EConVarType.EConVarType_UInt16, (ulong)flags, helpMessage, ushortValue, 0, 0); + } + else if (defaultValue is int intValue) + { + NativeConvars.CreateConvarInt32(name, (int)EConVarType.EConVarType_Int32, (ulong)flags, helpMessage, intValue, 0, 0); + } + else if (defaultValue is uint uintValue) + { + NativeConvars.CreateConvarUInt32(name, (int)EConVarType.EConVarType_UInt32, (ulong)flags, helpMessage, uintValue, 0, 0); + } + else if (defaultValue is long longValue) + { + NativeConvars.CreateConvarInt64(name, (int)EConVarType.EConVarType_Int64, (ulong)flags, helpMessage, longValue, 0, 0); + } + else if (defaultValue is ulong ulongValue) + { + NativeConvars.CreateConvarUInt64(name, (int)EConVarType.EConVarType_UInt64, (ulong)flags, helpMessage, ulongValue, 0, 0); + } + else if (defaultValue is float floatValue) + { + NativeConvars.CreateConvarFloat(name, (int)EConVarType.EConVarType_Float32, (ulong)flags, helpMessage, floatValue, 0, 0); + } + else if (defaultValue is double doubleValue) + { + NativeConvars.CreateConvarDouble(name, (int)EConVarType.EConVarType_Float64, (ulong)flags, helpMessage, doubleValue, 0, 0); + } + else if (defaultValue is Vector2D vector2Value) + { + NativeConvars.CreateConvarVector2D(name, (int)EConVarType.EConVarType_Vector2, (ulong)flags, helpMessage, vector2Value, 0, 0); + } + else if (defaultValue is Vector vector3Value) + { + NativeConvars.CreateConvarVector(name, (int)EConVarType.EConVarType_Vector3, (ulong)flags, helpMessage, vector3Value, 0, 0); + } + else if (defaultValue is Vector4D vector4Value) + { + NativeConvars.CreateConvarVector4D(name, (int)EConVarType.EConVarType_Vector4, (ulong)flags, helpMessage, vector4Value, 0, 0); + } + else if (defaultValue is QAngle qAngleValue) + { + NativeConvars.CreateConvarQAngle(name, (int)EConVarType.EConVarType_Qangle, (ulong)flags, helpMessage, qAngleValue, 0, 0); + } + else if (defaultValue is Color colorValue) + { + NativeConvars.CreateConvarColor(name, (int)EConVarType.EConVarType_Color, (ulong)flags, helpMessage, colorValue, 0, 0); + } + else if (defaultValue is string stringValue) + { + NativeConvars.CreateConvarString(name, (int)EConVarType.EConVarType_String, (ulong)flags, helpMessage, stringValue, 0, 0); + } + else + { + throw new Exception($"Unsupported type {typeof(T)}."); + } + + return new ConVar(name); + } + + public IConVar Create( string name, string helpMessage, T defaultValue, T? minValue, T? maxValue, ConvarFlags flags = ConvarFlags.NONE ) where T : unmanaged + { + + if (NativeConvars.ExistsConvar(name)) + { + throw new Exception($"Convar {name} already exists."); + } + unsafe + { + + if (defaultValue is short shortValue) + { + short* pMin = stackalloc short[1]; + if (minValue.HasValue) + { + pMin[0] = (short)(object)minValue.Value; + } + + short* pMax = stackalloc short[1]; + if (maxValue.HasValue) + { + pMax[0] = (short)(object)maxValue.Value; + } + + NativeConvars.CreateConvarInt16(name, (int)EConVarType.EConVarType_Int16, (ulong)flags, helpMessage, shortValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); + } + else if (defaultValue is ushort ushortValue) + { + ushort* pMin = stackalloc ushort[1]; + if (minValue.HasValue) + { + pMin[0] = (ushort)(object)minValue.Value; + } + + ushort* pMax = stackalloc ushort[1]; + if (maxValue.HasValue) + { + pMax[0] = (ushort)(object)maxValue.Value; + } + + NativeConvars.CreateConvarUInt16(name, (int)EConVarType.EConVarType_UInt16, (ulong)flags, helpMessage, ushortValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); + } + else if (defaultValue is int intValue) + { + int* pMin = stackalloc int[1]; + if (minValue.HasValue) + { + pMin[0] = (int)(object)minValue.Value; + } + + int* pMax = stackalloc int[1]; + if (maxValue.HasValue) + { + pMax[0] = (int)(object)maxValue.Value; + } + + NativeConvars.CreateConvarInt32(name, (int)EConVarType.EConVarType_Int32, (ulong)flags, helpMessage, intValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); + } + else if (defaultValue is uint uintValue) + { + uint* pMin = stackalloc uint[1]; + if (minValue.HasValue) + { + pMin[0] = (uint)(object)minValue.Value; + } + + uint* pMax = stackalloc uint[1]; + if (maxValue.HasValue) + { + pMax[0] = (uint)(object)maxValue.Value; + } + + NativeConvars.CreateConvarUInt32(name, (int)EConVarType.EConVarType_UInt32, (ulong)flags, helpMessage, uintValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); + } + else if (defaultValue is long longValue) + { + long* pMin = stackalloc long[1]; + if (minValue.HasValue) + { + pMin[0] = (long)(object)minValue.Value; + } + + long* pMax = stackalloc long[1]; + if (maxValue.HasValue) + { + pMax[0] = (long)(object)maxValue.Value; + } + + NativeConvars.CreateConvarInt64(name, (int)EConVarType.EConVarType_Int64, (ulong)flags, helpMessage, longValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); + } + else if (defaultValue is ulong ulongValue) + { + ulong* pMin = stackalloc ulong[1]; + if (minValue.HasValue) + { + pMin[0] = (ulong)(object)minValue.Value; + } + + ulong* pMax = stackalloc ulong[1]; + if (maxValue.HasValue) + { + pMax[0] = (ulong)(object)maxValue.Value; + } + + NativeConvars.CreateConvarUInt64(name, (int)EConVarType.EConVarType_UInt64, (ulong)flags, helpMessage, ulongValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); + } + else if (defaultValue is float floatValue) + { + float* pMin = stackalloc float[1]; + if (minValue.HasValue) + { + pMin[0] = (float)(object)minValue.Value; + } + + float* pMax = stackalloc float[1]; + if (maxValue.HasValue) + { + pMax[0] = (float)(object)maxValue.Value; + } + + NativeConvars.CreateConvarFloat(name, (int)EConVarType.EConVarType_Float32, (ulong)flags, helpMessage, floatValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); + } + else if (defaultValue is double doubleValue) + { + double* pMin = stackalloc double[1]; + if (minValue.HasValue) + { + pMin[0] = (double)(object)minValue.Value; + } + + double* pMax = stackalloc double[1]; + if (maxValue.HasValue) + { + pMax[0] = (double)(object)maxValue.Value; + } + + NativeConvars.CreateConvarDouble(name, (int)EConVarType.EConVarType_Float64, (ulong)flags, helpMessage, doubleValue, minValue.HasValue ? (nint)pMin : 0, maxValue.HasValue ? (nint)pMax : 0); + } + else + { + throw new Exception($"You can't assign min and max values to {typeof(T)}."); + } + } + + return new ConVar(name); + } + + public IConVar CreateOrFind( string name, string helpMessage, T defaultValue, ConvarFlags flags = ConvarFlags.NONE ) + { + return NativeConvars.ExistsConvar(name) ? new ConVar(name) : Create(name, helpMessage, defaultValue, flags); + } + + public IConVar CreateOrFind( string name, string helpMessage, T defaultValue, T? minValue, T? maxValue, ConvarFlags flags = ConvarFlags.NONE ) where T : unmanaged + { + return NativeConvars.ExistsConvar(name) ? new ConVar(name) : Create(name, helpMessage, defaultValue, minValue, maxValue, flags); + } } \ No newline at end of file diff --git a/managed/src/SwiftlyS2.Core/Services/StartupService.cs b/managed/src/SwiftlyS2.Core/Services/StartupService.cs index 7a2ccb2fb..4ef7c6592 100644 --- a/managed/src/SwiftlyS2.Core/Services/StartupService.cs +++ b/managed/src/SwiftlyS2.Core/Services/StartupService.cs @@ -11,7 +11,6 @@ internal class StartupService : IHostedService public StartupService( IServiceProvider provider ) { // this.provider = provider; - // provider.UseTestService(); provider.UseCoreHookService(); provider.UsePermissionManager(); provider.UseCommandTrackerService(); @@ -20,6 +19,7 @@ public StartupService( IServiceProvider provider ) provider.UseCoreCommandService(); // Initialize PluginManager after everything is ready provider.UsePluginManager(); + // provider.UseTestService(); } public Task StartAsync( CancellationToken cancellationToken ) diff --git a/managed/src/SwiftlyS2.Core/Services/TestService.cs b/managed/src/SwiftlyS2.Core/Services/TestService.cs index 9180ed988..cf77dcecb 100644 --- a/managed/src/SwiftlyS2.Core/Services/TestService.cs +++ b/managed/src/SwiftlyS2.Core/Services/TestService.cs @@ -48,27 +48,24 @@ ISwiftlyCore core _Logger.LogWarning("TestService created"); _Logger.LogWarning("TestService created"); - Test2(); + Test(); } public void Test() { - _Core.Event.OnEntityCreated += (@event) => - { - var name = _Core.Memory.GetObjectPtrVtableName(@event.Entity.Address); - Console.WriteLine("Entity spawned: " + name); - var hasVtable = _Core.Memory.ObjectPtrHasVtable(@event.Entity.Address + 1); - Console.WriteLine("Has vtable: " + hasVtable); - var vtable = _Core.Memory.ObjectPtrHasBaseClass(@event.Entity.Address, "CBaseEntity"); - Console.WriteLine("Has base class: " + vtable); - var handle = _Core.EntitySystem.GetRefEHandle(@event.Entity); - }; - // _Core.Event.OnItemServicesCanAcquireHook += (@event) => { - // Console.WriteLine(@event.EconItemView.ItemDefinitionIndex); + _Core.Command.RegisterCommand("tc", (args) => { + var cvar = _Core.ConVar.Find("mp_warmuptime"); - // @event.SetAcquireResult(AcquireResult.NotAllowedByProhibition); - // }; + // cvar.MinValueAsString + + + cvar!.ValueAsString = "10"; + cvar!.DefaultValueAsString = "50"; + cvar!.MaxValueAsString = "100"; + cvar!.MinValueAsString = "10"; + cvar.ReplicateToClientAsString(0, "10"); + }); } diff --git a/managed/src/SwiftlyS2.Generated/Natives/Convars.cs b/managed/src/SwiftlyS2.Generated/Natives/Convars.cs index 5dee59521..00dd27f5d 100644 --- a/managed/src/SwiftlyS2.Generated/Natives/Convars.cs +++ b/managed/src/SwiftlyS2.Generated/Natives/Convars.cs @@ -663,4 +663,212 @@ public unsafe static void SetValueInternalPtr(string cvarName, nint value) { pool.Return(cvarNameBuffer); } } + + private unsafe static delegate* unmanaged _SetValueAsString; + + public unsafe static bool SetValueAsString(string cvarName, string value) { + if (Thread.CurrentThread.ManagedThreadId != _MainThreadID) { + throw new InvalidOperationException("This method can only be called from the main thread."); + } + var pool = ArrayPool.Shared; + var cvarNameLength = Encoding.UTF8.GetByteCount(cvarName); + var cvarNameBuffer = pool.Rent(cvarNameLength + 1); + Encoding.UTF8.GetBytes(cvarName, cvarNameBuffer); + cvarNameBuffer[cvarNameLength] = 0; + var valueLength = Encoding.UTF8.GetByteCount(value); + var valueBuffer = pool.Rent(valueLength + 1); + Encoding.UTF8.GetBytes(value, valueBuffer); + valueBuffer[valueLength] = 0; + fixed (byte* cvarNameBufferPtr = cvarNameBuffer) { + fixed (byte* valueBufferPtr = valueBuffer) { + var ret = _SetValueAsString(cvarNameBufferPtr, valueBufferPtr); + pool.Return(cvarNameBuffer); + pool.Return(valueBuffer); + return ret == 1; + } + } + } + + private unsafe static delegate* unmanaged _GetValueAsString; + + public unsafe static string GetValueAsString(string cvarName) { + var pool = ArrayPool.Shared; + var cvarNameLength = Encoding.UTF8.GetByteCount(cvarName); + var cvarNameBuffer = pool.Rent(cvarNameLength + 1); + Encoding.UTF8.GetBytes(cvarName, cvarNameBuffer); + cvarNameBuffer[cvarNameLength] = 0; + fixed (byte* cvarNameBufferPtr = cvarNameBuffer) { + var ret = _GetValueAsString(null, cvarNameBufferPtr); + var retBuffer = pool.Rent(ret + 1); + fixed (byte* retBufferPtr = retBuffer) { + ret = _GetValueAsString(retBufferPtr, cvarNameBufferPtr); + var retString = Encoding.UTF8.GetString(retBufferPtr, ret); + pool.Return(retBuffer); + pool.Return(cvarNameBuffer); + return retString; + } + } + } + + private unsafe static delegate* unmanaged _SetDefaultValueAsString; + + public unsafe static bool SetDefaultValueAsString(string cvarName, string value) { + if (Thread.CurrentThread.ManagedThreadId != _MainThreadID) { + throw new InvalidOperationException("This method can only be called from the main thread."); + } + var pool = ArrayPool.Shared; + var cvarNameLength = Encoding.UTF8.GetByteCount(cvarName); + var cvarNameBuffer = pool.Rent(cvarNameLength + 1); + Encoding.UTF8.GetBytes(cvarName, cvarNameBuffer); + cvarNameBuffer[cvarNameLength] = 0; + var valueLength = Encoding.UTF8.GetByteCount(value); + var valueBuffer = pool.Rent(valueLength + 1); + Encoding.UTF8.GetBytes(value, valueBuffer); + valueBuffer[valueLength] = 0; + fixed (byte* cvarNameBufferPtr = cvarNameBuffer) { + fixed (byte* valueBufferPtr = valueBuffer) { + var ret = _SetDefaultValueAsString(cvarNameBufferPtr, valueBufferPtr); + pool.Return(cvarNameBuffer); + pool.Return(valueBuffer); + return ret == 1; + } + } + } + + private unsafe static delegate* unmanaged _GetDefaultValueAsString; + + public unsafe static string GetDefaultValueAsString(string cvarName) { + var pool = ArrayPool.Shared; + var cvarNameLength = Encoding.UTF8.GetByteCount(cvarName); + var cvarNameBuffer = pool.Rent(cvarNameLength + 1); + Encoding.UTF8.GetBytes(cvarName, cvarNameBuffer); + cvarNameBuffer[cvarNameLength] = 0; + fixed (byte* cvarNameBufferPtr = cvarNameBuffer) { + var ret = _GetDefaultValueAsString(null, cvarNameBufferPtr); + var retBuffer = pool.Rent(ret + 1); + fixed (byte* retBufferPtr = retBuffer) { + ret = _GetDefaultValueAsString(retBufferPtr, cvarNameBufferPtr); + var retString = Encoding.UTF8.GetString(retBufferPtr, ret); + pool.Return(retBuffer); + pool.Return(cvarNameBuffer); + return retString; + } + } + } + + private unsafe static delegate* unmanaged _SetMinValueAsString; + + public unsafe static bool SetMinValueAsString(string cvarName, string value) { + if (Thread.CurrentThread.ManagedThreadId != _MainThreadID) { + throw new InvalidOperationException("This method can only be called from the main thread."); + } + var pool = ArrayPool.Shared; + var cvarNameLength = Encoding.UTF8.GetByteCount(cvarName); + var cvarNameBuffer = pool.Rent(cvarNameLength + 1); + Encoding.UTF8.GetBytes(cvarName, cvarNameBuffer); + cvarNameBuffer[cvarNameLength] = 0; + var valueLength = Encoding.UTF8.GetByteCount(value); + var valueBuffer = pool.Rent(valueLength + 1); + Encoding.UTF8.GetBytes(value, valueBuffer); + valueBuffer[valueLength] = 0; + fixed (byte* cvarNameBufferPtr = cvarNameBuffer) { + fixed (byte* valueBufferPtr = valueBuffer) { + var ret = _SetMinValueAsString(cvarNameBufferPtr, valueBufferPtr); + pool.Return(cvarNameBuffer); + pool.Return(valueBuffer); + return ret == 1; + } + } + } + + private unsafe static delegate* unmanaged _GetMinValueAsString; + + public unsafe static string GetMinValueAsString(string cvarName) { + var pool = ArrayPool.Shared; + var cvarNameLength = Encoding.UTF8.GetByteCount(cvarName); + var cvarNameBuffer = pool.Rent(cvarNameLength + 1); + Encoding.UTF8.GetBytes(cvarName, cvarNameBuffer); + cvarNameBuffer[cvarNameLength] = 0; + fixed (byte* cvarNameBufferPtr = cvarNameBuffer) { + var ret = _GetMinValueAsString(null, cvarNameBufferPtr); + var retBuffer = pool.Rent(ret + 1); + fixed (byte* retBufferPtr = retBuffer) { + ret = _GetMinValueAsString(retBufferPtr, cvarNameBufferPtr); + var retString = Encoding.UTF8.GetString(retBufferPtr, ret); + pool.Return(retBuffer); + pool.Return(cvarNameBuffer); + return retString; + } + } + } + + private unsafe static delegate* unmanaged _SetMaxValueAsString; + + public unsafe static bool SetMaxValueAsString(string cvarName, string value) { + if (Thread.CurrentThread.ManagedThreadId != _MainThreadID) { + throw new InvalidOperationException("This method can only be called from the main thread."); + } + var pool = ArrayPool.Shared; + var cvarNameLength = Encoding.UTF8.GetByteCount(cvarName); + var cvarNameBuffer = pool.Rent(cvarNameLength + 1); + Encoding.UTF8.GetBytes(cvarName, cvarNameBuffer); + cvarNameBuffer[cvarNameLength] = 0; + var valueLength = Encoding.UTF8.GetByteCount(value); + var valueBuffer = pool.Rent(valueLength + 1); + Encoding.UTF8.GetBytes(value, valueBuffer); + valueBuffer[valueLength] = 0; + fixed (byte* cvarNameBufferPtr = cvarNameBuffer) { + fixed (byte* valueBufferPtr = valueBuffer) { + var ret = _SetMaxValueAsString(cvarNameBufferPtr, valueBufferPtr); + pool.Return(cvarNameBuffer); + pool.Return(valueBuffer); + return ret == 1; + } + } + } + + private unsafe static delegate* unmanaged _GetMaxValueAsString; + + public unsafe static string GetMaxValueAsString(string cvarName) { + var pool = ArrayPool.Shared; + var cvarNameLength = Encoding.UTF8.GetByteCount(cvarName); + var cvarNameBuffer = pool.Rent(cvarNameLength + 1); + Encoding.UTF8.GetBytes(cvarName, cvarNameBuffer); + cvarNameBuffer[cvarNameLength] = 0; + fixed (byte* cvarNameBufferPtr = cvarNameBuffer) { + var ret = _GetMaxValueAsString(null, cvarNameBufferPtr); + var retBuffer = pool.Rent(ret + 1); + fixed (byte* retBufferPtr = retBuffer) { + ret = _GetMaxValueAsString(retBufferPtr, cvarNameBufferPtr); + var retString = Encoding.UTF8.GetString(retBufferPtr, ret); + pool.Return(retBuffer); + pool.Return(cvarNameBuffer); + return retString; + } + } + } + + private unsafe static delegate* unmanaged _SetValueInternalAsString; + + public unsafe static void SetValueInternalAsString(string cvarName, string value) { + if (Thread.CurrentThread.ManagedThreadId != _MainThreadID) { + throw new InvalidOperationException("This method can only be called from the main thread."); + } + var pool = ArrayPool.Shared; + var cvarNameLength = Encoding.UTF8.GetByteCount(cvarName); + var cvarNameBuffer = pool.Rent(cvarNameLength + 1); + Encoding.UTF8.GetBytes(cvarName, cvarNameBuffer); + cvarNameBuffer[cvarNameLength] = 0; + var valueLength = Encoding.UTF8.GetByteCount(value); + var valueBuffer = pool.Rent(valueLength + 1); + Encoding.UTF8.GetBytes(value, valueBuffer); + valueBuffer[valueLength] = 0; + fixed (byte* cvarNameBufferPtr = cvarNameBuffer) { + fixed (byte* valueBufferPtr = valueBuffer) { + _SetValueInternalAsString(cvarNameBufferPtr, valueBufferPtr); + pool.Return(cvarNameBuffer); + pool.Return(valueBuffer); + } + } + } } \ No newline at end of file diff --git a/managed/src/SwiftlyS2.Shared/Modules/Convars/IConVar.cs b/managed/src/SwiftlyS2.Shared/Modules/Convars/IConVar.cs index 4ad0ef09e..370ae4f93 100644 --- a/managed/src/SwiftlyS2.Shared/Modules/Convars/IConVar.cs +++ b/managed/src/SwiftlyS2.Shared/Modules/Convars/IConVar.cs @@ -1,6 +1,103 @@ namespace SwiftlyS2.Shared.Convars; -public interface IConVar { +public interface IConVar { + + /// + /// The string value of the convar. + /// When setting, if the convar can be replicated, it will automatically replicate to all clients. + /// Also, setting value with this method will internally put it into a set queue, + /// Which means that for some special case ( e.g. setting sv_enablebunnyhopping inside a hook ) it won't work, + /// in such cases you should use the SetInternal method instead. + /// + /// Thrown when the string value can't be parsed. + /// + public string ValueAsString { get; set; } + + /// + /// The max value of the convar in string. + /// + /// Thrown when the string value can't be parsed. + /// + string MaxValueAsString { get; set; } + + /// + /// The min value of the convar in string. + /// + /// Thrown when the string value can't be parsed. + /// + string MinValueAsString { get; set; } + + /// + /// The default value of the convar in string. + /// + /// Thrown when the string value can't be parsed. + /// + string DefaultValueAsString { get; set; } + + /// + /// Whether the convar has a default value. + /// + bool HasDefaultValue { get; } + + /// + /// Whether the convar has a min value. + /// + bool HasMinValue { get; } + + /// + /// Whether the convar has a max value. + /// + bool HasMaxValue { get; } + + /// + /// The flags of the convar. + /// + ConvarFlags Flags { get; set; } + + + /// + /// Internally set the value of the convar. + /// Won't replicate the change to clients. + /// + /// The value to set. + void SetInternalAsString( string value ); + + /// + /// Replicate the value of the convar to specified client. + /// + /// The client id to replicate to. + void ReplicateToClientAsString( int clientId, string value ); + + /// + /// Query the value of the convar from specified client. + /// + /// + /// The action to execute with the value. + void QueryClient( int clientId, Action callback ); + + /// + /// Try to get the default value of the convar. + /// + /// The default value of the convar. + /// True if the default value is found, false otherwise. + bool TryGetDefaultValueAsString(out string defaultValue); + + /// + /// Try to get the min value of the convar. + /// + /// The min value of the convar. + /// True if the min value is found, false otherwise. + bool TryGetMinValueAsString(out string minValue); + + /// + /// Try to get the max value of the convar. + /// + /// The max value of the convar. + /// True if the max value is found, false otherwise. + bool TryGetMaxValueAsString(out string maxValue); +} + +public interface IConVar : IConVar { /// /// The value of the convar. /// When setting, if the convar can be replicated, it will automatically replicate to all clients. @@ -49,7 +146,6 @@ public interface IConVar { /// ConvarFlags Flags { get; set; } - /// /// Internally set the value of the convar. /// Won't replicate the change to clients. @@ -57,18 +153,18 @@ public interface IConVar { /// The value to set. void SetInternal(T value); - /// - /// Replicate the value of the convar to specified client. - /// - /// The client id to replicate to. - void ReplicateToClient(int clientId, T value); - /// /// Query the value of the convar from specified client. /// /// /// The action to execute with the value. - void QueryClient(int clientId, Action callback); + void QueryClient( int clientId, Action callback ); + + /// + /// Replicate the value of the convar to specified client. + /// + /// The client id to replicate to. + void ReplicateToClient( int clientId, T value ); /// /// Try to get the min value of the convar. @@ -90,4 +186,6 @@ public interface IConVar { /// The default value of the convar. /// True if the default value is found, false otherwise. bool TryGetDefaultValue(out T defaultValue); + + } \ No newline at end of file diff --git a/managed/src/SwiftlyS2.Shared/Modules/Convars/IConVarService.cs b/managed/src/SwiftlyS2.Shared/Modules/Convars/IConVarService.cs index b1ee50357..a7212e190 100644 --- a/managed/src/SwiftlyS2.Shared/Modules/Convars/IConVarService.cs +++ b/managed/src/SwiftlyS2.Shared/Modules/Convars/IConVarService.cs @@ -1,107 +1,68 @@ -using SwiftlyS2.Core.Convars; -using SwiftlyS2.Shared.Natives; - namespace SwiftlyS2.Shared.Convars; -public interface IConVarService -{ - - /// - /// Find a existing convar by name. - /// - /// The type of the convar. - /// The name of the convar. - /// The convar if found, null otherwise. - public IConVar? Find( string name ); - - /// - /// Create a new convar. - /// - /// The type of the convar. - /// The name of the convar. - /// The help message of the convar. - /// The default value of the convar. - /// The flags of the convar. - /// The created convar. - /// Reference to the created convar. - public IConVar Create( string name, string helpMessage, T defaultValue, ConvarFlags flags = ConvarFlags.NONE ); - - /// - /// Create a new convar with min and max values. - /// - /// The type of the convar. - /// The name of the convar. - /// The help message of the convar. - /// The default value of the convar. - /// The flags of the convar. - /// The min value of the convar. - /// The max value of the convar. - /// The created convar. - public IConVar Create( string name, string helpMessage, T defaultValue, T? minValue, T? maxValue, ConvarFlags flags = ConvarFlags.NONE ) where T : unmanaged; - - /// - /// Create a new convar or find an existing one by name. - /// - /// The type of the convar. - /// The name of the convar. - /// The help message of the convar. - /// The default value of the convar. - /// The flags of the convar. - /// The created or found convar. - public IConVar CreateOrFind( string name, string helpMessage, T defaultValue, ConvarFlags flags = ConvarFlags.NONE ); - - /// - /// Create a new convar or find an existing one by name with min and max values. - /// - /// The type of the convar. - /// The name of the convar. - /// The help message of the convar. - /// The default value of the convar. - /// The min value of the convar. - /// The max value of the convar. - /// The flags of the convar. - /// The created or found convar. - public IConVar CreateOrFind( string name, string helpMessage, T defaultValue, T? minValue, T? maxValue, ConvarFlags flags = ConvarFlags.NONE ) where T : unmanaged; - - /// - /// Reads the value of a convar as a string. - /// - /// The name of the convar. - /// The value of the convar as a string. - public string? ReadValueAsString( string name ); +public interface IConVarService { + + /// + /// Find a existing convar by name. + /// + /// The type of the convar. + /// The name of the convar. + /// The convar if found, null otherwise. + IConVar? Find(string name); - /// - /// Sets the value of a convar as a string. - /// - /// The name of the convar. - /// The value to set. - public void SetValueAsString( string name, string value ); + /// + /// Find a existing convar by name with no type. + /// + /// The name of the convar. + /// The convar if found, null otherwise. + IConVar? FindAsString(string name); - /// - /// Gets the type of a convar by name. - /// - /// The name of the convar. - /// The type of the convar. - public EConVarType GetConVarType( string name ); + /// + /// Create a new convar. + /// + /// The type of the convar. + /// The name of the convar. + /// The help message of the convar. + /// The default value of the convar. + /// The flags of the convar. + /// The created convar. + /// Reference to the created convar. + IConVar Create(string name, string helpMessage, T defaultValue, ConvarFlags flags = ConvarFlags.NONE); - /// - /// Gets the default value of a convar by name. - /// - /// The name of the convar. - /// The default value of the convar as a string. - public string? GetDefaultValue( string name ); + /// + /// Create a new convar with min and max values. + /// + /// The type of the convar. + /// The name of the convar. + /// The help message of the convar. + /// The default value of the convar. + /// The flags of the convar. + /// The min value of the convar. + /// The max value of the convar. + /// The created convar. + IConVar Create(string name, string helpMessage, T defaultValue, T? minValue, T? maxValue, ConvarFlags flags = ConvarFlags.NONE) where T: unmanaged; - /// - /// Gets the min value of a convar by name. - /// - /// The name of the convar. - /// The min value of the convar as a string. - public string? GetMinValue( string name ); + /// + /// Create a new convar or find an existing one by name. + /// + /// The type of the convar. + /// The name of the convar. + /// The help message of the convar. + /// The default value of the convar. + /// The flags of the convar. + /// The created or found convar. + IConVar CreateOrFind(string name, string helpMessage, T defaultValue, ConvarFlags flags = ConvarFlags.NONE); - /// - /// Gets the max value of a convar by name. - /// - /// The name of the convar. - /// The max value of the convar as a string. - public string? GetMaxValue( string name ); + /// + /// Create a new convar or find an existing one by name with min and max values. + /// + /// The type of the convar. + /// The name of the convar. + /// The help message of the convar. + /// The default value of the convar. + /// The min value of the convar. + /// The max value of the convar. + /// The flags of the convar. + /// The created or found convar. + IConVar CreateOrFind(string name, string helpMessage, T defaultValue, T? minValue, T? maxValue, ConvarFlags flags = ConvarFlags.NONE) where T: unmanaged; } \ No newline at end of file diff --git a/managed/src/SwiftlyS2.Shared/Natives/Structs/EConVarType.cs b/managed/src/SwiftlyS2.Shared/Natives/Structs/EConVarType.cs deleted file mode 100644 index 594735a81..000000000 --- a/managed/src/SwiftlyS2.Shared/Natives/Structs/EConVarType.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace SwiftlyS2.Shared.Natives; - -public enum EConVarType : int -{ - EConVarType_Invalid = -1, - EConVarType_Bool, - EConVarType_Int16, - EConVarType_UInt16, - EConVarType_Int32, - EConVarType_UInt32, - EConVarType_Int64, - EConVarType_UInt64, - EConVarType_Float32, - EConVarType_Float64, - EConVarType_String, - EConVarType_Color, - EConVarType_Vector2, - EConVarType_Vector3, - EConVarType_Vector4, - EConVarType_Qangle, - EConVarType_MAX -}; \ No newline at end of file diff --git a/natives/engine/convars.native b/natives/engine/convars.native index b147d8e4d..e52f08f19 100644 --- a/natives/engine/convars.native +++ b/natives/engine/convars.native @@ -38,4 +38,13 @@ sync void SetDefaultValue = string cvarName, ptr defaultValue sync void SetDefaultValueString = string cvarName, string defaultValue ptr GetValuePtr = string cvarName sync void SetValuePtr = string cvarName, ptr value -sync void SetValueInternalPtr = string cvarName, ptr value \ No newline at end of file +sync void SetValueInternalPtr = string cvarName, ptr value +sync bool SetValueAsString = string cvarName, string value +string GetValueAsString = string cvarName +sync bool SetDefaultValueAsString = string cvarName, string value +string GetDefaultValueAsString = string cvarName +sync bool SetMinValueAsString = string cvarName, string value +string GetMinValueAsString = string cvarName +sync bool SetMaxValueAsString = string cvarName, string value +string GetMaxValueAsString = string cvarName +sync void SetValueInternalAsString = string cvarName, string value diff --git a/src/scripting/engine/convars.cpp b/src/scripting/engine/convars.cpp index b593c5f57..d603f3a93 100644 --- a/src/scripting/engine/convars.cpp +++ b/src/scripting/engine/convars.cpp @@ -35,7 +35,7 @@ int Bridge_Convars_AddQueryClientCvarCallback(void* callback) static auto convarmanager = g_ifaceService.FetchInterface(CONVARMANAGER_INTERFACE_VERSION); return convarmanager->AddQueryClientCvarCallback([callback](int playerid, std::string cvarName, std::string cvarValue) -> void { ((void(*)(int, const char*, const char*))callback)(playerid, cvarName.c_str(), cvarValue.c_str()); - }); + }); } void Bridge_Convars_RemoveQueryClientCvarCallback(int callbackId) @@ -207,7 +207,7 @@ uint64_t Bridge_Convars_AddGlobalChangeListener(void* callback) auto cvarmanager = g_ifaceService.FetchInterface(CONVARMANAGER_INTERFACE_VERSION); return cvarmanager->AddGlobalChangeListener([callback](const char* convarName, int slot, const char* newValue, const char* oldValue) -> void { ((void(*)(const char*, int, const char*, const char*))callback)(convarName, slot, newValue, oldValue); - }); + }); } void Bridge_Convars_RemoveGlobalChangeListener(uint64_t listenerID) @@ -221,7 +221,7 @@ uint64_t Bridge_Convars_AddConvarCreatedListener(void* callback) auto cvarmanager = g_ifaceService.FetchInterface(CONVARMANAGER_INTERFACE_VERSION); return cvarmanager->AddConvarCreatedListener([callback](const char* convarName) -> void { ((void(*)(const char*))callback)(convarName); - }); + }); } void Bridge_Convars_RemoveConvarCreatedListener(uint64_t listenerID) @@ -235,7 +235,7 @@ uint64_t Bridge_Convars_AddConCommandCreatedListener(void* callback) auto cvarmanager = g_ifaceService.FetchInterface(CONVARMANAGER_INTERFACE_VERSION); return cvarmanager->AddConCommandCreatedListener([callback](const char* convarName) -> void { ((void(*)(const char*))callback)(convarName); - }); + }); } void Bridge_Convars_RemoveConCommandCreatedListener(uint64_t listenerID) @@ -301,6 +301,106 @@ void Bridge_Convars_SetValueInternalPtr(const char* cvarName, void* value) cvar.SetValueInternal(0, (CVValue_t*)value); } +bool Bridge_Convars_SetValueAsString(const char* cvarName, const char* value) +{ + ConVarRefAbstract cvar(cvarName); + return cvar.SetString(CUtlString(value), CSplitScreenSlot(0)); +} + +int Bridge_Convars_GetValueAsString(char* out, const char* cvarName) +{ + ConVarRefAbstract cvar(cvarName); + CBufferString buf; + cvar.GetValueAsString(buf, CSplitScreenSlot(0)); + + if (out != nullptr) + { + strcpy(out, buf.Get()); + } + return strlen(buf.Get()); +} + +bool Bridge_Convars_SetDefaultValueAsString(const char* cvarName, const char* defaultValue) +{ + ConVarRefAbstract cvar(cvarName); + auto data = cvar.GetConVarData(); + if (!data->m_defaultValue) + { + data->m_defaultValue = new CVValue_t(); + } + return cvar.GetConVarData()->TypeTraits()->StringToValue(defaultValue, data->m_defaultValue); +} + +int Bridge_Convars_GetDefaultValueAsString(char* out, const char* cvarName) +{ + ConVarRefAbstract cvar(cvarName); + CBufferString buf; + cvar.GetConVarData()->DefaultValueToString(buf); + + if (out != nullptr) + { + strcpy(out, buf.Get()); + } + return strlen(buf.Get()); +} + +int Bridge_Convars_GetMinValueAsString(char* out, const char* cvarName) +{ + ConVarRefAbstract cvar(cvarName); + CBufferString buf; + cvar.GetConVarData()->MinValueToString(buf); + + if (out != nullptr) + { + strcpy(out, buf.Get()); + } + return strlen(buf.Get()); +} + +bool Bridge_Convars_SetMinValueAsString(const char* cvarName, const char* minValue) +{ + ConVarRefAbstract cvar(cvarName); + auto data = cvar.GetConVarData(); + if (!data->m_minValue) + { + data->m_minValue = new CVValue_t(); + } + return cvar.GetConVarData()->TypeTraits()->StringToValue(minValue, data->m_minValue); +} + +int Bridge_Convars_GetMaxValueAsString(char* out, const char* cvarName) +{ + ConVarRefAbstract cvar(cvarName); + CBufferString buf; + cvar.GetConVarData()->MaxValueToString(buf); + + if (out != nullptr) + { + strcpy(out, buf.Get()); + } + return strlen(buf.Get()); +} + +bool Bridge_Convars_SetMaxValueAsString(const char* cvarName, const char* maxValue) +{ + ConVarRefAbstract cvar(cvarName); + auto data = cvar.GetConVarData(); + if (!data->m_maxValue) + { + data->m_maxValue = new CVValue_t(); + } + return cvar.GetConVarData()->TypeTraits()->StringToValue(maxValue, data->m_maxValue); +} + +void Bridge_Convars_SetValueInternalAsString(const char* cvarName, const char* value) +{ + ConVarRefAbstract cvar(cvarName); + CVValue_t v; + cvar.GetConVarData()->TypeTraits()->StringToValue(value, &v); + cvar.SetValueInternal(0, &v); +} + + DEFINE_NATIVE("Convars.QueryClientConvar", Bridge_Convars_QueryClientConvar); DEFINE_NATIVE("Convars.AddQueryClientCvarCallback", Bridge_Convars_AddQueryClientCvarCallback); DEFINE_NATIVE("Convars.RemoveQueryClientCvarCallback", Bridge_Convars_RemoveQueryClientCvarCallback); @@ -339,4 +439,13 @@ DEFINE_NATIVE("Convars.SetDefaultValue", Bridge_Convars_SetDefaultValue); DEFINE_NATIVE("Convars.SetDefaultValueString", Bridge_Convars_SetDefaultValueString); DEFINE_NATIVE("Convars.GetValuePtr", Bridge_Convars_GetValuePtr); DEFINE_NATIVE("Convars.SetValuePtr", Bridge_Convars_SetValuePtr); -DEFINE_NATIVE("Convars.SetValueInternalPtr", Bridge_Convars_SetValueInternalPtr); \ No newline at end of file +DEFINE_NATIVE("Convars.SetValueInternalPtr", Bridge_Convars_SetValueInternalPtr); +DEFINE_NATIVE("Convars.SetValueAsString", Bridge_Convars_SetValueAsString); +DEFINE_NATIVE("Convars.GetValueAsString", Bridge_Convars_GetValueAsString); +DEFINE_NATIVE("Convars.SetDefaultValueAsString", Bridge_Convars_SetDefaultValueAsString); +DEFINE_NATIVE("Convars.GetDefaultValueAsString", Bridge_Convars_GetDefaultValueAsString); +DEFINE_NATIVE("Convars.SetMinValueAsString", Bridge_Convars_SetMinValueAsString); +DEFINE_NATIVE("Convars.GetMinValueAsString", Bridge_Convars_GetMinValueAsString); +DEFINE_NATIVE("Convars.SetMaxValueAsString", Bridge_Convars_SetMaxValueAsString); +DEFINE_NATIVE("Convars.GetMaxValueAsString", Bridge_Convars_GetMaxValueAsString); +DEFINE_NATIVE("Convars.SetValueInternalAsString", Bridge_Convars_SetValueInternalAsString); \ No newline at end of file