Files
CounterStrikeSharp/src/scripting/natives/natives_schema.cpp
2025-08-04 09:28:05 +10:00

247 lines
11 KiB
C++

/*
* 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 <ios>
#include <sstream>
#include "scripting/autonative.h"
#include "scripting/script_engine.h"
#include "core/memory.h"
#include "core/log.h"
#include "schema.h"
#include "core/function.h"
#include "core/coreconfig.h"
#include "interfaces/cs2_interfaces.h"
#include <schemasystem.h>
namespace counterstrikesharp {
int16 GetSchemaOffset(ScriptContext& script_context)
{
auto className = script_context.GetArgument<const char*>(0);
auto memberName = script_context.GetArgument<const char*>(1);
auto classKey = hash_32_fnv1a_const(className);
auto memberKey = hash_32_fnv1a_const(memberName);
const auto m_key = schema::GetOffset(className, classKey, memberName, memberKey);
return m_key.offset;
}
bool IsSchemaFieldNetworked(ScriptContext& script_context)
{
auto className = script_context.GetArgument<const char*>(0);
auto memberName = script_context.GetArgument<const char*>(1);
auto classKey = hash_32_fnv1a_const(className);
auto memberKey = hash_32_fnv1a_const(memberName);
const auto m_key = schema::GetOffset(className, classKey, memberName, memberKey);
return m_key.networked;
}
int GetSchemaClassSize(ScriptContext& script_context)
{
auto className = script_context.GetArgument<const char*>(0);
CSchemaSystemTypeScope* pType = globals::schemaSystem->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT);
SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className).Get();
if (!pClassInfo) return -1;
return pClassInfo->m_nSize;
}
void GetSchemaValueByName(ScriptContext& script_context)
{
auto instancePointer = script_context.GetArgument<void*>(0);
auto returnType = script_context.GetArgument<DataType_t>(1);
auto className = script_context.GetArgument<const char*>(2);
auto memberName = script_context.GetArgument<const char*>(3);
auto classKey = hash_32_fnv1a_const(className);
auto memberKey = hash_32_fnv1a_const(memberName);
const auto m_key = schema::GetOffset(className, classKey, memberName, memberKey);
switch (returnType)
{
case DATA_TYPE_BOOL:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<bool>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_CHAR:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<char>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_UCHAR:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<unsigned char>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_SHORT:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<short>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_USHORT:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<unsigned short>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_INT:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<int>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_UINT:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<unsigned int>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_LONG:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<long>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_ULONG:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<unsigned long>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_LONG_LONG:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<long long>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_ULONG_LONG:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<uint64_t>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_FLOAT:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<float>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_DOUBLE:
script_context.SetResult(*reinterpret_cast<std::add_pointer_t<double>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_POINTER:
script_context.SetResult(reinterpret_cast<std::add_pointer_t<void>>((uintptr_t)(instancePointer) + m_key.offset));
break;
case DATA_TYPE_STRING:
script_context.SetResult(reinterpret_cast<std::add_pointer_t<char>>((uintptr_t)(instancePointer) + m_key.offset));
break;
default:
assert(!"Unknown function return type!");
break;
}
}
void SetSchemaValueByName(ScriptContext& script_context)
{
auto instancePointer = script_context.GetArgument<void*>(0);
auto dataType = script_context.GetArgument<DataType_t>(1);
auto className = script_context.GetArgument<const char*>(2);
auto memberName = script_context.GetArgument<const char*>(3);
if (globals::coreConfig->FollowCS2ServerGuidelines &&
std::find(schema::CS2BadList.begin(), schema::CS2BadList.end(), memberName) != schema::CS2BadList.end())
{
CSSHARP_CORE_ERROR("Cannot set '{}::{}' with \"FollowCS2ServerGuidelines\" option enabled.", className, memberName);
return;
}
auto classKey = hash_32_fnv1a_const(className);
auto memberKey = hash_32_fnv1a_const(memberName);
const auto m_key = schema::GetOffset(className, classKey, memberName, memberKey);
switch (dataType)
{
case DATA_TYPE_BOOL:
*reinterpret_cast<std::add_pointer_t<bool>>((uintptr_t)(instancePointer) + m_key.offset) = script_context.GetArgument<bool>(4);
break;
case DATA_TYPE_CHAR:
*reinterpret_cast<std::add_pointer_t<char>>((uintptr_t)(instancePointer) + m_key.offset) = script_context.GetArgument<char>(4);
break;
case DATA_TYPE_UCHAR:
*reinterpret_cast<std::add_pointer_t<unsigned char>>((uintptr_t)(instancePointer) + m_key.offset) =
script_context.GetArgument<unsigned char>(4);
break;
case DATA_TYPE_SHORT:
*reinterpret_cast<std::add_pointer_t<short>>((uintptr_t)(instancePointer) + m_key.offset) =
script_context.GetArgument<short>(4);
break;
case DATA_TYPE_USHORT:
*reinterpret_cast<std::add_pointer_t<unsigned short>>((uintptr_t)(instancePointer) + m_key.offset) =
script_context.GetArgument<unsigned short>(4);
break;
case DATA_TYPE_INT:
*reinterpret_cast<std::add_pointer_t<int>>((uintptr_t)(instancePointer) + m_key.offset) = script_context.GetArgument<int>(4);
break;
case DATA_TYPE_UINT:
*reinterpret_cast<std::add_pointer_t<unsigned int>>((uintptr_t)(instancePointer) + m_key.offset) =
script_context.GetArgument<unsigned int>(4);
break;
case DATA_TYPE_LONG:
*reinterpret_cast<std::add_pointer_t<long>>((uintptr_t)(instancePointer) + m_key.offset) = script_context.GetArgument<long>(4);
break;
case DATA_TYPE_ULONG:
*reinterpret_cast<std::add_pointer_t<unsigned long>>((uintptr_t)(instancePointer) + m_key.offset) =
script_context.GetArgument<unsigned long>(4);
break;
case DATA_TYPE_LONG_LONG:
*reinterpret_cast<std::add_pointer_t<long long>>((uintptr_t)(instancePointer) + m_key.offset) =
script_context.GetArgument<long long>(4);
break;
case DATA_TYPE_ULONG_LONG:
*reinterpret_cast<std::add_pointer_t<uint64_t>>((uintptr_t)(instancePointer) + m_key.offset) =
script_context.GetArgument<uint64_t>(4);
break;
case DATA_TYPE_FLOAT:
*reinterpret_cast<std::add_pointer_t<float>>((uintptr_t)(instancePointer) + m_key.offset) =
script_context.GetArgument<float>(4);
break;
case DATA_TYPE_DOUBLE:
*reinterpret_cast<std::add_pointer_t<double>>((uintptr_t)(instancePointer) + m_key.offset) =
script_context.GetArgument<double>(4);
break;
case DATA_TYPE_POINTER:
*reinterpret_cast<void**>((uintptr_t)(instancePointer) + m_key.offset) = script_context.GetArgument<void*>(4);
break;
case DATA_TYPE_STRING:
{
auto duplicated = strdup(script_context.GetArgument<const char*>(4));
*reinterpret_cast<char**>((uintptr_t)(instancePointer) + m_key.offset) = duplicated;
break;
}
default:
assert(!"Unknown function data type!");
break;
}
}
void SchemaSetStateChanged(ScriptContext& script_context)
{
auto instancePointer = script_context.GetArgument<void*>(0);
auto offset = script_context.GetArgument<uint32_t>(1);
auto nArrayIndex = script_context.GetArgument<uint32_t>(2);
auto nPathIndex = script_context.GetArgument<uint32_t>(3);
SetStateChanged(reinterpret_cast<uintptr_t>(instancePointer), offset, nArrayIndex, nPathIndex);
}
void SchemaNetworkStateChanged(ScriptContext& script_context)
{
auto instancePointer = script_context.GetArgument<void*>(0);
auto offset = script_context.GetArgument<uint32_t>(1);
auto nArrayIndex = script_context.GetArgument<uint32_t>(2);
auto nPathIndex = script_context.GetArgument<uint32_t>(3);
NetworkStateChanged(reinterpret_cast<uintptr_t>(instancePointer), offset, nArrayIndex, nPathIndex);
} // namespace counterstrikesharp
REGISTER_NATIVES(schema, {
ScriptEngine::RegisterNativeHandler("GET_SCHEMA_OFFSET", GetSchemaOffset);
ScriptEngine::RegisterNativeHandler("IS_SCHEMA_FIELD_NETWORKED", IsSchemaFieldNetworked);
ScriptEngine::RegisterNativeHandler("GET_SCHEMA_VALUE_BY_NAME", GetSchemaValueByName);
ScriptEngine::RegisterNativeHandler("SET_SCHEMA_VALUE_BY_NAME", SetSchemaValueByName);
ScriptEngine::RegisterNativeHandler("GET_SCHEMA_CLASS_SIZE", GetSchemaClassSize);
ScriptEngine::RegisterNativeHandler("SCHEMA_SET_STATE_CHANGED", SchemaSetStateChanged);
ScriptEngine::RegisterNativeHandler("SCHEMA_NETWORK_STATE_CHANGED", SchemaNetworkStateChanged);
})
} // namespace counterstrikesharp