Implement CVariant functions (#905)

This commit is contained in:
ZoNiCaL
2025-07-07 12:22:02 +12:00
committed by GitHub
parent 267b017787
commit 124ffac7a9
8 changed files with 481 additions and 7 deletions

View File

@@ -84,6 +84,8 @@ set(SOURCE_FILES
src/scripting/natives/natives_entities.cpp
src/scripting/natives/natives_voice.cpp
src/scripting/natives/natives_metamod.cpp
src/scripting/natives/natives_cvariant.cpp
src/scripting/natives/natives_cutil.cpp
src/core/managers/entity_manager.cpp
src/core/managers/entity_manager.h
src/core/managers/chat_manager.cpp

View File

@@ -218,6 +218,138 @@ namespace CounterStrikeSharp.API.Core
}
}
public static string GetStringFromSymbolLarge(IntPtr pointer){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pointer);
ScriptContext.GlobalScriptContext.SetIdentifier(0x600A804B);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
return (string)ScriptContext.GlobalScriptContext.GetResult(typeof(string));
}
}
public static uint GetVariantType(IntPtr pvariant){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.SetIdentifier(0x7AC3DA1C);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
return (uint)ScriptContext.GlobalScriptContext.GetResult(typeof(uint));
}
}
public static int GetVariantInt(IntPtr pvariant){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.SetIdentifier(0x78156617);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
return (int)ScriptContext.GlobalScriptContext.GetResult(typeof(int));
}
}
public static uint GetVariantUint(IntPtr pvariant){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.SetIdentifier(0x7AC49FA2);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
return (uint)ScriptContext.GlobalScriptContext.GetResult(typeof(uint));
}
}
public static float GetVariantFloat(IntPtr pvariant){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.SetIdentifier(0xD20595B4);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
return (float)ScriptContext.GlobalScriptContext.GetResult(typeof(float));
}
}
public static string GetVariantString(IntPtr pvariant){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.SetIdentifier(0x41C49F71);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
return (string)ScriptContext.GlobalScriptContext.GetResult(typeof(string));
}
}
public static bool GetVariantBool(IntPtr pvariant){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.SetIdentifier(0x7ABC76EA);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
return (bool)ScriptContext.GlobalScriptContext.GetResult(typeof(bool));
}
}
public static void SetVariantInt(IntPtr pvariant, int value){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.Push(value);
ScriptContext.GlobalScriptContext.SetIdentifier(0x801EC403);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
}
}
public static void SetVariantUint(IntPtr pvariant, uint value){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.Push(value);
ScriptContext.GlobalScriptContext.SetIdentifier(0x83EC7436);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
}
}
public static void SetVariantFloat(IntPtr pvariant, float value){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.Push(value);
ScriptContext.GlobalScriptContext.SetIdentifier(0x266E8A0);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
}
}
public static void SetVariantString(IntPtr pvariant, string value){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.Push(value);
ScriptContext.GlobalScriptContext.SetIdentifier(0x2450A3E5);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
}
}
public static void SetVariantBool(IntPtr pvariant, bool value){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();
ScriptContext.GlobalScriptContext.Push(pvariant);
ScriptContext.GlobalScriptContext.Push(value);
ScriptContext.GlobalScriptContext.SetIdentifier(0x83F1967E);
ScriptContext.GlobalScriptContext.Invoke();
ScriptContext.GlobalScriptContext.CheckErrors();
}
}
public static T DynamicHookGetReturn<T>(IntPtr hook, int datatype){
lock (ScriptContext.GlobalScriptContext.Lock) {
ScriptContext.GlobalScriptContext.Reset();

View File

@@ -0,0 +1,18 @@
namespace CounterStrikeSharp.API.Core;
public class CUtlSymbolLarge : NativeObject
{
public CUtlSymbolLarge(IntPtr pointer) : base(pointer)
{
}
public bool IsValid => Handle != IntPtr.Zero;
public string String
{
get
{
return NativeAPI.GetStringFromSymbolLarge(Handle);
}
}
}

View File

@@ -1,13 +1,56 @@
namespace CounterStrikeSharp.API.Core;
using System.Reflection.Metadata;
/// <summary>
/// Placeholder for CVariant
/// <see href="https://github.com/alliedmodders/hl2sdk/blob/cs2/public/variant.h"/>
/// <remarks>A lot of entity outputs do not use this value</remarks>
/// </summary>
namespace CounterStrikeSharp.API.Core;
public class CVariant : NativeObject
{
public CVariant(IntPtr pointer) : base(pointer)
{
}
public bool IsValid => Handle != IntPtr.Zero;
public fieldtype_t FieldType => (fieldtype_t)NativeAPI.GetVariantType(Handle);
public T Get<T>()
{
var type = typeof(T);
object result = type switch
{
_ when type == typeof(float) => NativeAPI.GetVariantFloat(Handle),
_ when type == typeof(int) => NativeAPI.GetVariantInt(Handle),
_ when type == typeof(uint) => NativeAPI.GetVariantUint(Handle),
_ when type == typeof(string) => NativeAPI.GetVariantString(Handle),
_ when type == typeof(bool) => NativeAPI.GetVariantBool(Handle),
_ => throw new NotSupportedException(),
};
return (T)result;
}
public void Set<T>(T value)
{
var type = typeof(T);
switch (type)
{
case var _ when value is float f:
NativeAPI.SetVariantFloat(Handle, f);
break;
case var _ when value is int i:
NativeAPI.SetVariantInt(Handle, i);
break;
case var _ when value is uint ui:
NativeAPI.SetVariantUint(Handle, ui);
break;
case var _ when value is bool b:
NativeAPI.SetVariantBool(Handle, b);
break;
case var _ when value is string s:
NativeAPI.SetVariantString(Handle, s);
break;
default:
throw new NotSupportedException();
}
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* This file is part of CounterStrikeSharp.
* CounterStrikeSharp is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CounterStrikeSharp is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
*/
#include <public/entity2/entitysystem.h>
#include <ios>
#include <sstream>
#include "scripting/autonative.h"
#include "scripting/script_engine.h"
#include "utlsymbollarge.h"
namespace counterstrikesharp {
const char* GetStringFromSymbolLarge(ScriptContext& script_context)
{
CUtlSymbolLarge* pSymbolLarge = script_context.GetArgument<CUtlSymbolLarge*>(0);
if (!pSymbolLarge)
{
script_context.ThrowNativeError("Invalid CUtlSymbolLarge pointer");
return "";
}
return pSymbolLarge->String();
}
REGISTER_NATIVES(cutil, { ScriptEngine::RegisterNativeHandler("GET_STRING_FROM_SYMBOL_LARGE", GetStringFromSymbolLarge); })
} // namespace counterstrikesharp

View File

@@ -0,0 +1 @@
GET_STRING_FROM_SYMBOL_LARGE: pointer:pointer -> string

View File

@@ -0,0 +1,224 @@
/*
* This file is part of CounterStrikeSharp.
* CounterStrikeSharp is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CounterStrikeSharp is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
*/
#include <public/entity2/entitysystem.h>
#include <ios>
#include <sstream>
#include "scripting/autonative.h"
#include "scripting/script_engine.h"
namespace counterstrikesharp {
_fieldtypes GetVariantType(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return _fieldtypes::FIELD_TYPEUNKNOWN;
}
return pVariant->m_type;
}
static int GetVariantInt(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return 0;
}
if (pVariant->m_type != _fieldtypes::FIELD_INT32)
{
script_context.ThrowNativeError("Variant type is not int");
return 0.0f;
}
return pVariant->m_int32;
}
static uint GetVariantUInt(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return 0;
}
if (pVariant->m_type != _fieldtypes::FIELD_UINT32)
{
script_context.ThrowNativeError("Variant type is not uint");
return 0.0f;
}
return pVariant->m_uint32;
}
static float GetVariantFloat(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return 0;
}
if (pVariant->m_type != _fieldtypes::FIELD_FLOAT32)
{
script_context.ThrowNativeError("Variant type is not float");
return 0.0f;
}
return pVariant->m_float32;
}
static const char* GetVariantString(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return "";
}
if (pVariant->m_type != _fieldtypes::FIELD_STRING)
{
script_context.ThrowNativeError("Variant type is not string");
return "";
}
return pVariant->m_pszString;
}
static bool GetVariantBool(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return false;
}
if (pVariant->m_type != _fieldtypes::FIELD_BOOLEAN)
{
script_context.ThrowNativeError("Variant type is not boolean");
return 0.0f;
}
return pVariant->m_bool;
}
static void SetVariantInt(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return;
}
if (pVariant->m_type != _fieldtypes::FIELD_INT32)
{
script_context.ThrowNativeError("Variant type is not int");
return;
}
int value = script_context.GetArgument<int>(1);
pVariant->m_int32 = value;
}
static void SetVariantUInt(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return;
}
if (pVariant->m_type != _fieldtypes::FIELD_UINT32)
{
script_context.ThrowNativeError("Variant type is not uint");
return;
}
uint value = script_context.GetArgument<uint>(1);
pVariant->m_uint32 = value;
}
static void SetVariantFloat(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return;
}
if (pVariant->m_type != _fieldtypes::FIELD_FLOAT32)
{
script_context.ThrowNativeError("Variant type is not float");
return;
}
float value = script_context.GetArgument<float>(1);
pVariant->m_float32 = value;
}
static void SetVariantString(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return;
}
if (pVariant->m_type != _fieldtypes::FIELD_STRING)
{
script_context.ThrowNativeError("Variant type is not string");
return;
}
const char* value = script_context.GetArgument<const char*>(1);
pVariant->m_pszString = value;
}
static void SetVariantBool(ScriptContext& script_context)
{
variant_t* pVariant = script_context.GetArgument<variant_t*>(0);
if (!pVariant)
{
script_context.ThrowNativeError("Invalid variant pointer");
return;
}
if (pVariant->m_type != _fieldtypes::FIELD_BOOLEAN)
{
script_context.ThrowNativeError("Variant type is not boolean");
return;
}
bool value = script_context.GetArgument<bool>(1);
pVariant->m_bool = value;
}
REGISTER_NATIVES(cvariant, {
ScriptEngine::RegisterNativeHandler("GET_VARIANT_TYPE", GetVariantType);
ScriptEngine::RegisterNativeHandler("GET_VARIANT_INT", GetVariantInt);
ScriptEngine::RegisterNativeHandler("GET_VARIANT_UINT", GetVariantUInt);
ScriptEngine::RegisterNativeHandler("GET_VARIANT_FLOAT", GetVariantFloat);
ScriptEngine::RegisterNativeHandler("GET_VARIANT_STRING", GetVariantString);
ScriptEngine::RegisterNativeHandler("GET_VARIANT_BOOL", GetVariantBool);
ScriptEngine::RegisterNativeHandler("SET_VARIANT_INT", SetVariantInt);
ScriptEngine::RegisterNativeHandler("SET_VARIANT_UINT", SetVariantUInt);
ScriptEngine::RegisterNativeHandler("SET_VARIANT_FLOAT", SetVariantFloat);
ScriptEngine::RegisterNativeHandler("SET_VARIANT_STRING", SetVariantString);
ScriptEngine::RegisterNativeHandler("SET_VARIANT_BOOL", SetVariantBool);
})
} // namespace counterstrikesharp

View File

@@ -0,0 +1,13 @@
GET_VARIANT_TYPE: pVariant:pointer -> uint
GET_VARIANT_INT: pVariant:pointer -> int
GET_VARIANT_UINT: pVariant:pointer -> uint
GET_VARIANT_FLOAT: pVariant:pointer -> float
GET_VARIANT_STRING: pVariant:pointer -> string
GET_VARIANT_BOOL: pVariant:pointer -> bool
SET_VARIANT_INT: pVariant:pointer, value:int -> void
SET_VARIANT_UINT: pVariant:pointer, value:uint -> void
SET_VARIANT_FLOAT: pVariant:pointer, value:float -> void
SET_VARIANT_STRING: pVariant:pointer, value:string -> void
SET_VARIANT_BOOL: pVariant:pointer, value:bool -> void