diff --git a/csgo2/csgo2.vcxproj b/csgo2/csgo2.vcxproj index 35524cf..e464d5e 100644 --- a/csgo2/csgo2.vcxproj +++ b/csgo2/csgo2.vcxproj @@ -216,14 +216,18 @@ + + + + diff --git a/csgo2/csgo2.vcxproj.filters b/csgo2/csgo2.vcxproj.filters index 6d2f618..69d8aeb 100644 --- a/csgo2/csgo2.vcxproj.filters +++ b/csgo2/csgo2.vcxproj.filters @@ -330,6 +330,18 @@ 头文件\native_sdk + + 头文件\sdk\public + + + 头文件\sdk\public + + + 头文件\sdk\tier1 + + + 头文件\sdk\tier1 + diff --git a/csgo2/events.cpp b/csgo2/events.cpp index 307a817..49a7949 100644 --- a/csgo2/events.cpp +++ b/csgo2/events.cpp @@ -1,6 +1,20 @@ #include "events.h" namespace events { +auto OnPlayerSpawnEvent(IGameEvent* event) -> void { + UnkGameEventStruct_t userIdNameParams{"userid"}; + const auto playerPawn = reinterpret_cast( + event->GetPlayerPawn(&userIdNameParams)); + if (playerPawn == nullptr) { + return; + } + const auto player = playerPawn->GetPlayerController(); + if (player == nullptr) { + return; + } + const auto playerIndex = player->GetRefEHandle().GetEntryIndex(); + ScriptCallBacks::luaCall_onPlayerSpawn(playerIndex); +} auto OnPlayerDeathEvent(IGameEvent* event) -> void { UnkGameEventStruct_t userIdNameParams{"userid"}; UnkGameEventStruct_t attackerNameParams{"attacker"}; diff --git a/csgo2/events.h b/csgo2/events.h index 9c6f845..b693cac 100644 --- a/csgo2/events.h +++ b/csgo2/events.h @@ -10,4 +10,5 @@ auto OnPlayerConnect(int slot, const char* pszName, uint64_t xuid, auto OnPlayerDisconnect(int slot, const char* pszName, uint64_t xuid, const char* pszNetworkID, const char* pszAddress, bool bFakePlayer) -> void; +auto OnPlayerSpawnEvent(IGameEvent* event) -> void; } // namespace events diff --git a/csgo2/head.h b/csgo2/head.h index a28841e..4abf661 100644 --- a/csgo2/head.h +++ b/csgo2/head.h @@ -37,28 +37,9 @@ static void DebugPrintA(const char* format, ...) { #include "memory.h" // sdk -#include "sdk/gameevent/IGameEvent.h" -#include "sdk/tier1/bufferstring.h" -#include "sdk/public/eiface.h" -#include "sdk/player/playerslot.h" #include "sdk/sdk.h" -#include "sdk/public/mathlib.h" -#include "sdk/public/string_t.h" -#include "sdk/tier1/UtlMemory.hpp" -#include "sdk/tier1/utlfixedmemory.h" -#include "sdk/tier1/utlblockmemory.h" -#include "sdk/tier1/UtlString.hpp" -#include "sdk/interfaces/interfaces.h" -#include "sdk/public/eiface.h" -#include "sdk/gameevent/IGameEvent.h" -#include "sdk/convar/convar.hpp" -#include "sdk/tier1/bufferstring.h" -#include "sdk/public/bitvec.h" -#include "sdk/public/iserver.h" -#include "sdk/public/utlrbtree.h" -#include "sdk/public/utlmap.h" #include "offset.h" #include "native_sdk.h" diff --git a/csgo2/hooks.cpp b/csgo2/hooks.cpp index b02680b..cb88f61 100644 --- a/csgo2/hooks.cpp +++ b/csgo2/hooks.cpp @@ -1,17 +1,17 @@ #include "hooks.h" extern auto GetGameGlobals() -> CGlobalVars*; + +namespace hooks { +// "player_connect" +VMTHook* VMT_IServerGameClient; +VMTHook* VMT_INetworkServerServiceInteFace; +VMTHook* VMT_ISource2ServerInterFace; FireEventServerSide_t original_FireEventServerSide = NULL; OnClientConnect_t original_OnClientConnected = NULL; OnClientDisconnect_t original_OnClientDisconnect = NULL; Host_Say_t original_Host_Say = NULL; StartupServer_t origin_StartServer = NULL; GameFrame_t origin_GameFrame = NULL; -namespace hooks { -// "player_connect" -VMTHook* VMT_IServerGameClient; -VMTHook* VMT_INetworkServerServiceInteFace; -VMTHook* VMT_ISource2ServerInterFace; - void __fastcall hook_GameFrame(void* rcx, bool simulating, bool bFirstTick, bool bLastTick) { /** @@ -128,11 +128,16 @@ bool __fastcall hook_FireEventServerSide(CGameEventManager* rcx, static constexpr auto player_death = hash_32_fnv1a_const("player_death"); static constexpr auto player_chat = hash_32_fnv1a_const("player_chat"); + static constexpr auto player_spawn = + hash_32_fnv1a_const("player_spawn"); switch (hash_32_fnv1a_const(eventName)) { case player_death: events::OnPlayerDeathEvent(event); break; + case player_spawn: + events::OnPlayerSpawnEvent(event); + break; // VÉçbug,Õâ²»»áÓÐÓà /* case player_chat: diff --git a/csgo2/hooks.h b/csgo2/hooks.h index d1c0447..e65d332 100644 --- a/csgo2/hooks.h +++ b/csgo2/hooks.h @@ -7,10 +7,8 @@ typedef void(__fastcall* OnClientConnect_t)(void*, CPlayerSlot, const char*, uin typedef void(__fastcall* OnClientDisconnect_t)(void*, CPlayerSlot, int, const char*, uint64_t, const char*); typedef void(__fastcall* StartupServer_t)(void*, const GameSessionConfiguration_t&, ISource2WorldSession*, const char*); typedef void(__fastcall* GameFrame_t)(void*, bool, bool, bool); - -extern FireEventServerSide_t original_FireEventServerSide; -extern Host_Say_t original_Host_Say; namespace hooks { + extern Host_Say_t original_Host_Say; auto init() -> bool; auto unload() -> void; } \ No newline at end of file diff --git a/csgo2/native_sdk.cpp b/csgo2/native_sdk.cpp index 0dd66c1..4937536 100644 --- a/csgo2/native_sdk.cpp +++ b/csgo2/native_sdk.cpp @@ -23,7 +23,8 @@ auto CSchemaSystem::FindTypeScopeForModule(const char* module) } auto CBaseEntity::IsBasePlayerController() -> bool { - return CALL_VIRTUAL(bool, 144, this); + return true; + //return CALL_VIRTUAL(bool, 146, this); } auto CBaseEntity::SpawnClientEntity() -> void { CALL_VIRTUAL(void, 19, this); } auto CBasePlayer::ForceRespawn() -> void { diff --git a/csgo2/offset.cpp b/csgo2/offset.cpp index 9d93ec5..6cb149d 100644 --- a/csgo2/offset.cpp +++ b/csgo2/offset.cpp @@ -14,7 +14,10 @@ NetworkStateChanged_t FnNetworkStateChanged; RespawnPlayer_t FnRespawnPlayer; GiveNamedItem_t FnGiveNamedItem; EntityRemove_t FnEntityRemove; -//CreateGameRuleInterFace_t FnCreateCCSGameRulesInterFace; +UTIL_SayTextFilter_t FnUTIL_SayTextFilter; +UTIL_ClientPrintAll_t FnUTIL_ClientPrintAll; +ClientPrint_t FnClientPrint; +// CreateGameRuleInterFace_t FnCreateCCSGameRulesInterFace; bool InitOffsetSuccess = false; namespace InterFaces { CSchemaSystem* SchemaSystem; @@ -30,18 +33,19 @@ CCSGameRules* CCSGameRulesInterFace; }; // namespace InterFaces auto SafeDelayInit(void* ctx) -> void { // ÐèÒªÓÎÏ·µ÷Óú¯Êý³õʼ»¯ - InterFaces::CCSGameRulesInterFace = - reinterpret_cast(Memory::read(CCSGameRulesInterFacePtr)); + InterFaces::CCSGameRulesInterFace = reinterpret_cast( + Memory::read(CCSGameRulesInterFacePtr)); - while (InterFaces::CCSGameRulesInterFace == 0) - { - InterFaces::CCSGameRulesInterFace = - reinterpret_cast(Memory::read(CCSGameRulesInterFacePtr)); + while (InterFaces::CCSGameRulesInterFace == 0) { + InterFaces::CCSGameRulesInterFace = reinterpret_cast( + Memory::read(CCSGameRulesInterFacePtr)); Sleep(100); } InitOffsetSuccess = true; - LOG("[huoji]InterFaces::CCSGameRulesInterFace : %llx \n", InterFaces::CCSGameRulesInterFace); - LOG("m_bForceTeamChangeSilent: %d \n", InterFaces::CCSGameRulesInterFace->m_bForceTeamChangeSilent()); + LOG("[huoji]InterFaces::CCSGameRulesInterFace : %llx \n", + InterFaces::CCSGameRulesInterFace); + LOG("m_bForceTeamChangeSilent: %d \n", + InterFaces::CCSGameRulesInterFace->m_bForceTeamChangeSilent()); } auto Init() -> bool { CModule server("server.dll"); @@ -65,14 +69,15 @@ auto Init() -> bool { server.FindPattern(pattern_CreateCCSGameRulesInterFacePtr) .ToAbsolute(3, 0) .Get(CCSGameRulesInterFacePtr); - server.FindPattern(pattern_FnRespawnPlayer) - .Get(FnRespawnPlayer); - server.FindPattern(pattern_FnEntityRemove) - .Get(FnEntityRemove); - server.FindPattern(pattern_FnGiveNamedItemPtr) - .Get(FnGiveNamedItem); + server.FindPattern(pattern_FnRespawnPlayer).Get(FnRespawnPlayer); + server.FindPattern(pattern_FnEntityRemove).Get(FnEntityRemove); + server.FindPattern(pattern_FnGiveNamedItemPtr).Get(FnGiveNamedItem); server.FindPattern(pattern_fnHost_SayPtr).Get(Host_SayPtr); server.FindPattern(pattern_ServerHashFunctionPtr).Get(FnServerHashFunction); + server.FindPattern(pattern_UTIL_ClientPrintAll).Get(FnUTIL_ClientPrintAll); + server.FindPattern(pattern_FnClientPrint).Get(FnClientPrint); + + server.FindPattern(pattern_FnUTIL_SayTextFilter).Get(FnUTIL_SayTextFilter); InterFaces::SchemaSystem = reinterpret_cast( schemasystem.FindInterface("SchemaSystem_001").Get()); // InterFaces::GameEventManager = reinterpret_cast( @@ -112,6 +117,8 @@ auto Init() -> bool { LOG("[huoji]FnStateChanged : %llx \n", FnStateChanged); LOG("[huoji]FnRespawnPlayer : %llx \n", FnRespawnPlayer); LOG("[huoji]FnGiveNamedItem : %llx \n", FnGiveNamedItem); + LOG("[huoji]FnClientPrint : %llx \n", FnClientPrint); + LOG("[huoji]FnUTIL_ClientPrintAll : %llx \n", FnUTIL_ClientPrintAll); LOG("[huoji]MaxGlobals : %d \n", global::MaxPlayers); @@ -132,13 +139,15 @@ auto Init() -> bool { CGameEntitySystem::GetInstance()); LOG("init offset success !\n"); CreateThread(NULL, 0, - reinterpret_cast(SafeDelayInit), - NULL, 0, NULL); + reinterpret_cast(SafeDelayInit), NULL, + 0, NULL); // LOG("FnServerHashFunction: %llx \n", FnServerHashFunction("here", // sizeof("here") - 1, 0x31415926)); - return FnEntityRemove && FnRespawnPlayer && FnGiveNamedItem && FnServerHashFunction && Host_SayPtr && InterFaces::IVEngineServer && + return FnEntityRemove && FnRespawnPlayer && FnGiveNamedItem && + FnServerHashFunction && Host_SayPtr && InterFaces::IVEngineServer && InterFaces::GameResourceServiceServer && InterFaces::IServerGameClient && InterFaces::GameEventManager && - InterFaces::SchemaSystem && FireEventServerSidePtr && FnNetworkStateChanged; + InterFaces::SchemaSystem && FireEventServerSidePtr && + FnNetworkStateChanged; } } // namespace Offset diff --git a/csgo2/offset.h b/csgo2/offset.h index 3450d6f..5ecd8c0 100644 --- a/csgo2/offset.h +++ b/csgo2/offset.h @@ -4,6 +4,7 @@ class CEntityInstance; class CCSPlayerPawn; class CGameEntitySystem; +class CCSPlayerController; typedef uint64_t(__fastcall* HashFunction_t)(const char*, unsigned int, unsigned int); typedef void(__fastcall* StateChanged_t)(void* networkTransmitComponent, @@ -17,7 +18,13 @@ typedef void(__fastcall* GiveNamedItem_t)(void* itemService, const char* pchName, void* iSubType, void* pScriptItem, void* a5, void* a6); -typedef void* (__fastcall* EntityRemove_t)(CGameEntitySystem*, void*, void*, uint64_t); +typedef void*(__fastcall* EntityRemove_t)(CGameEntitySystem*, void*, void*, + uint64_t); +typedef void*(__fastcall* UTIL_SayTextFilter_t)(IRecipientFilter&, const char*, + CCSPlayerController*, uint64_t); +typedef void(__fastcall* UTIL_ClientPrintAll_t)(int msg_dest, const char* msg_name, const char* param1, const char* param2, const char* param3, const char* param4); +typedef void(__fastcall* ClientPrint_t)(CCSPlayerController* player, int msg_dest, const char* msg_name, const char* param1, const char* param2, const char* param3, const char* param4); + class CSchemaSystem; class CGameResourceService; class CLocalize; @@ -73,7 +80,16 @@ static const auto pattern_FnRespawnPlayer = THE_GAME_SIG( "?? ?? 74 ?? 48 ?? ?? ?? ?? ?? ?? 48 8B CF 48 8B 10 48 8B ?? ?? ?? ?? ?? " "48 8D ?? ?? ?? E8 ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ??"); static const auto pattern_FnEntityRemove = THE_GAME_SIG( - "48 85 D2 0F ?? ?? ?? ?? ?? 57 48 ?? ?? ?? 48 89 ?? ?? ?? 48 8B F9 48 8B ?? ?? 48 85 DB 0F ?? ?? ?? ?? ?? 48 ?? ?? ?? 75 ?? 33 D2 48 8B CB E8 ?? ?? ?? ?? 48 8D ?? ?? 41 ?? ?? 48 8B D3 48 8B ?? ?? ?? 48 ?? ?? ?? 5F E9 ?? ?? ?? ??"); + "48 85 D2 0F ?? ?? ?? ?? ?? 57 48 ?? ?? ?? 48 89 ?? ?? ?? 48 8B F9 48 8B " + "?? ?? 48 85 DB 0F ?? ?? ?? ?? ?? 48 ?? ?? ?? 75 ?? 33 D2 48 8B CB E8 ?? " + "?? ?? ?? 48 8D ?? ?? 41 ?? ?? 48 8B D3 48 8B ?? ?? ?? 48 ?? ?? ?? 5F E9 " + "?? ?? ?? ??"); +static const auto pattern_FnUTIL_SayTextFilter = THE_GAME_SIG( + "48 89 5C 24 ?? 55 56 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 49 8B D8"); +static const auto pattern_UTIL_ClientPrintAll = THE_GAME_SIG( + "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 81 EC 70 01 ?? ?? 8B E9"); +static const auto pattern_FnClientPrint = THE_GAME_SIG( + "48 85 C9 0F 84 ?? ?? ?? ?? 48 8B C4 48 89 58 18"); extern uint64_t GameResourceServicePtr; extern uint64_t FireEventServerSidePtr; extern uint64_t Module_tier0; @@ -85,6 +101,9 @@ extern NetworkStateChanged_t FnNetworkStateChanged; extern RespawnPlayer_t FnRespawnPlayer; extern GiveNamedItem_t FnGiveNamedItem; extern EntityRemove_t FnEntityRemove; +extern UTIL_SayTextFilter_t FnUTIL_SayTextFilter; +extern UTIL_ClientPrintAll_t FnUTIL_ClientPrintAll; +extern ClientPrint_t FnClientPrint; extern bool InitOffsetSuccess; auto Init() -> bool; }; // namespace Offset diff --git a/csgo2/script_apis.cpp b/csgo2/script_apis.cpp index 68b58ad..3e410d0 100644 --- a/csgo2/script_apis.cpp +++ b/csgo2/script_apis.cpp @@ -43,6 +43,7 @@ auto ExcutePlayerAction(int playerIndex, break; } auto player = EntitySystem->GetBaseEntity(playerIndex); + if (player == nullptr) { break; } @@ -119,7 +120,6 @@ auto luaApi_RespawnPlayer(lua_State* luaVm) -> int { if (playerPawn == nullptr) { return; } - LOG("respawn player: %llx \n", playerPawn); Offset::FnRespawnPlayer(playerPawn); }); return 0; @@ -190,12 +190,13 @@ auto luaApi_GetPlayerWeaponInfo(lua_State* luaVm) -> _luaApi_WeaponInfo { if (weapon == nullptr) { continue; } - const auto weaponIndex = + const auto _weaponIndex = weapon->GetRefEHandle().GetEntryIndex(); - if (weaponIndex != weaponIndex) { + if (weaponIndex != _weaponIndex) { continue; } activeWeapon = handle->Get(); + break; } if (activeWeapon == nullptr) { break; @@ -230,6 +231,7 @@ auto luaApi_GetPlayerWeaponInfo(lua_State* luaVm) -> _luaApi_WeaponInfo { ? _luaApi_WeaponType::kGun : _luaApi_WeaponType::kOther)); info.weaponIndex = weaponIndex; + //LOG("luaApi_GetPlayerWeaponInfo: %s %s %s %d \n", info.weaponName.c_str(), info.weaponBaseName.c_str(), checkWeaponName, weaponIndex); } while (false); }); return info; @@ -407,6 +409,65 @@ auto luaApi_GivePlayerWeapon(lua_State* luaVm) -> int { auto luApi_GetPlayerAllWeaponIndex(lua_State* luaVm) -> int { // param: playerIndex:int const auto playerIndex = lua_tointeger(luaVm, 1); + + // Create a new table on the Lua stack + lua_newtable(luaVm); + + ExcutePlayerAction(playerIndex, [&](CCSPlayerController* playerController) { + do { + const auto weaponServices = playerController->m_hPawn() + .Get() + ->m_pWeaponServices(); + if (weaponServices == nullptr) { + break; + } + const auto weapons = weaponServices->m_hMyWeapons(); + int index = 1; // Lua tables start at index 1 + for (CHandle* handle = weapons.begin(); handle < weapons.end(); + ++handle) { + const auto weapon = handle->Get(); + if (weapon == nullptr) { + continue; + } + const auto activeWeapon = handle->Get(); + const auto attributeManager = activeWeapon->m_AttributeManager(); + if (activeWeapon == nullptr) { + break; + } + const auto itemView = attributeManager->m_Item(); + if (itemView == nullptr) { + break; + } + const auto itemStaticData = itemView->GetStaticData(); + if (itemView == nullptr) { + break; + } + const char* checkWeaponName = + Offset::InterFaces::ILocalize->FindSafe( + itemStaticData->m_pszItemBaseName); + if (checkWeaponName == nullptr || strlen(checkWeaponName) < 1) { + break; + } + //printf("weapon name: %s \n", itemStaticData->GetSimpleWeaponName()); + const auto weaponIndex = + weapon->GetRefEHandle().GetEntryIndex(); + + // Push the value onto the stack + lua_pushinteger(luaVm, weaponIndex); + + // Set the table at index position + lua_rawseti(luaVm, -2, index++); + } + } while (false); + }); + + // Return the table regardless of success or failure + return 1; +} +auto luaApi_MakePlayerWeaponDrop(lua_State* luaVm) -> int { + // param: playerIndex:int, itemClass:string + const auto playerIndex = lua_tointeger(luaVm, 1); + const auto weaponIndex = lua_tointeger(luaVm, 2); auto isSuccess = false; ExcutePlayerAction(playerIndex, [&](CCSPlayerController* playerController) { do { @@ -417,38 +478,28 @@ auto luApi_GetPlayerAllWeaponIndex(lua_State* luaVm) -> int { break; } const auto weapons = weaponServices->m_hMyWeapons(); - - // Create a new table on the Lua stack - lua_newtable(luaVm); - - int index = 1; // Lua tables start at index 1 + CBasePlayerWeapon* activeWeapon = 0; for (CHandle* handle = weapons.begin(); handle < weapons.end(); ++handle) { - const auto weapon = handle->Get(); - if (weapon == nullptr) { + if (handle->GetEntryIndex() != weaponIndex) { continue; } - const auto weaponIndex = - weapon->GetRefEHandle().GetEntryIndex(); - - // Push the index and then the value onto the stack - lua_pushinteger(luaVm, index++); - lua_pushinteger(luaVm, weaponIndex); - - // The table is now below the key-value pair in the stack, - // so we use -3 to indicate its position - lua_settable(luaVm, -3); + const auto weapon = handle->Get(); + if (weapon == nullptr) { + break; + } + activeWeapon = weapon; + break; } + if (activeWeapon == nullptr) { + break; + } + weaponServices->RemoveWeapon(activeWeapon); isSuccess = true; } while (false); }); - - if (!isSuccess) { - // If unsuccessful, remove the table from the stack - lua_pop(luaVm, 1); - } + lua_pop(luaVm, 2); lua_pushboolean(luaVm, isSuccess); - // Return the number of results (either the table or false) return 1; } auto luaApi_RemovePlayerWeapon(lua_State* luaVm) -> int { @@ -476,6 +527,7 @@ auto luaApi_RemovePlayerWeapon(lua_State* luaVm) -> int { continue; } activeWeapon = weapon; + break; } if (activeWeapon == nullptr) { break; @@ -488,8 +540,35 @@ auto luaApi_RemovePlayerWeapon(lua_State* luaVm) -> int { }); lua_pop(luaVm, 2); - lua_pushboolean(luaVm, isSuccess); - return 1; + return 0; +} +auto luaApi_SendToPlayerChat(lua_State* luaVm) -> int { + // param: playerIndex:int, message:string + const auto playerIndex = lua_tointeger(luaVm, 1); + const auto hudType = lua_tointeger(luaVm, 2); + const auto message = lua_tostring(luaVm, 3); + if (hudType >= _HubType::kMax || hudType < _HubType::kNotify) { + lua_pop(luaVm, 3); + return 0; + } + ExcutePlayerAction(playerIndex, [&](CCSPlayerController* playerController) { + SdkTools::SentChatToClient(playerController, + static_cast<_HubType>(hudType), message); + }); + lua_pop(luaVm, 3); + return 0; +} +auto luaApi_SentToAllPlayerChat(lua_State* luaVm) -> int { + // param: playerIndex:int, message:string + const auto message = lua_tostring(luaVm, 1); + const auto hudType = lua_tointeger(luaVm, 2); + if (hudType >= _HubType::kMax || hudType < _HubType::kNotify) { + lua_pop(luaVm, 3); + return 0; + } + SdkTools::SendConsoleChat(static_cast<_HubType>(hudType), message); + lua_pop(luaVm, 2); + return 0; } auto initFunciton(lua_State* luaVm) -> void { lua_register(luaVm, "ListenToGameEvent", luaApi_ListenToGameEvent); @@ -514,6 +593,12 @@ auto initFunciton(lua_State* luaVm) -> void { lua_register(luaVm, "luApi_GetPlayerAllWeaponIndex", luApi_GetPlayerAllWeaponIndex); lua_register(luaVm, "luaApi_RemovePlayerWeapon", luaApi_RemovePlayerWeapon); + lua_register(luaVm, "luaApi_MakePlayerWeaponDrop", + luaApi_MakePlayerWeaponDrop); + lua_register(luaVm, "luaApi_SendToPlayerChat", luaApi_SendToPlayerChat); + lua_register(luaVm, "luaApi_SentToAllPlayerChat", + luaApi_SentToAllPlayerChat); + luabridge::getGlobalNamespace(luaVm) .beginClass<_luaApi_WeaponInfo>("WeaponInfo") .addConstructor() diff --git a/csgo2/script_callbacks.cpp b/csgo2/script_callbacks.cpp index f923877..a88e625 100644 --- a/csgo2/script_callbacks.cpp +++ b/csgo2/script_callbacks.cpp @@ -10,6 +10,8 @@ std::unordered_map callbackNameWithEnumMap{ _CallbackNames::kOnPlayerDisconnect}, {hash_32_fnv1a_const("player_death"), _CallbackNames::kOnPlayerDeath}, {hash_32_fnv1a_const("player_chat"), _CallbackNames::kOnPlayerSpeak}, + {hash_32_fnv1a_const("player_spawn"), _CallbackNames::kOnPlayerSpawn}, + }; auto CallBackNameToEnum(const char* name) -> _CallbackNames { if (name == nullptr) { @@ -35,7 +37,7 @@ auto ExcuteCallbackInAllLuaVm(_CallbackNames cbType, if (luaVMCallbackLists.find(cbType) == luaVMCallbackLists.end()) { continue; } - LOG("excute callback %d in %s \n", cbType, pluginName.c_str()); + // LOG("excute callback %d in %s \n", cbType, pluginName.c_str()); const auto luaRefIndex = luaVMCallbackLists.at(cbType); cb(luaVm, luaRefIndex); } @@ -129,4 +131,19 @@ auto luaCall_onPlayerSpeak(int speaker, int chatType, std::string message) }); return result; } +auto luaCall_onPlayerSpawn(int player) -> void { + ExcuteCallbackInAllLuaVm(_CallbackNames::kOnPlayerSpawn, + [&](lua_State* luaVm, int refIndex) -> void { + lua_rawgeti(luaVm, LUA_REGISTRYINDEX, + refIndex); + if (lua_isfunction(luaVm, -1)) { + lua_pushinteger(luaVm, player); + if (lua_pcall(luaVm, 1, 0, 0) != LUA_OK) { + LOG("Error calling Lua callback: %s\n", + lua_tostring(luaVm, -1)); + lua_pop(luaVm, 1); + } + } + }); +} } // namespace ScriptCallBacks diff --git a/csgo2/script_callbacks.h b/csgo2/script_callbacks.h index 180e374..284a70d 100644 --- a/csgo2/script_callbacks.h +++ b/csgo2/script_callbacks.h @@ -7,7 +7,8 @@ enum class _CallbackNames { kOnPlayerConnect, kOnPlayerDisconnect, kOnPlayerDeath, - kOnPlayerSpeak + kOnPlayerSpeak, + kOnPlayerSpawn }; extern std::unordered_map> callbackList; @@ -22,4 +23,5 @@ auto luaCall_onPlayerDisconnect(int player, int slot, const char* pszName, auto luaCall_onPlayerDeath(int victim, int killer, bool isHeadShot) -> void; auto luaCall_onPlayerSpeak(int speaker, int chatType, std::string message) -> bool; +auto luaCall_onPlayerSpawn(int player) -> void; } // namespace ScriptCallBacks diff --git a/csgo2/sdk/convar/convar.cpp b/csgo2/sdk/convar/convar.cpp index 2bc9cca..0e21f48 100644 --- a/csgo2/sdk/convar/convar.cpp +++ b/csgo2/sdk/convar/convar.cpp @@ -1,18 +1,116 @@ #include "convar.hpp" -inline const char** CCommand::ArgV() const -{ - return ArgC() ? (const char**)m_Args.Base() : NULL; +inline const char** CCommand::ArgV() const { + return ArgC() ? (const char**)m_Args.Base() : NULL; } -inline const char* CCommand::ArgS() const -{ - return m_nArgv0Size ? (m_ArgSBuffer.Base() + m_nArgv0Size) : ""; +inline const char* CCommand::ArgS() const { + return m_nArgv0Size ? (m_ArgSBuffer.Base() + m_nArgv0Size) : ""; } - - -inline const char* CCommand::operator[](int nIndex) const -{ - return Arg(nIndex); +inline const char* CCommand::operator[](int nIndex) const { + return Arg(nIndex); +} +static characterset_t s_BreakSet; +static bool s_bBuiltBreakSet = false; +void CharacterSetBuild(characterset_t* pSetBuffer, const char* pszSetString) { + int i = 0; + + // Test our pointers + if (!pSetBuffer || !pszSetString) return; + + memset(pSetBuffer->set, 0, sizeof(pSetBuffer->set)); + + while (pszSetString[i]) { + pSetBuffer->set[static_cast(pszSetString[i])] = 1; + i++; + } +} + +//----------------------------------------------------------------------------- +// Tokenizer class +//----------------------------------------------------------------------------- +CCommand::CCommand() { + if (!s_bBuiltBreakSet) { + s_bBuiltBreakSet = true; + CharacterSetBuild(&s_BreakSet, "{}()':"); + } + + Reset(); +} + +CCommand::CCommand(int nArgC, const char** ppArgV) { + Assert(nArgC > 0); + + if (!s_bBuiltBreakSet) { + s_bBuiltBreakSet = true; + CharacterSetBuild(&s_BreakSet, "{}()':"); + } + + Reset(); + + char* pBuf = m_ArgvBuffer.Base(); + char* pSBuf = m_ArgSBuffer.Base(); + for (int i = 0; i < nArgC; ++i) { + m_Args.AddToTail(pBuf); + int nLen = strlen(ppArgV[i]); + memcpy(pBuf, ppArgV[i], nLen + 1); + if (i == 0) { + m_nArgv0Size = nLen; + } + pBuf += nLen + 1; + + bool bContainsSpace = strchr(ppArgV[i], ' ') != NULL; + if (bContainsSpace) { + *pSBuf++ = '\"'; + } + memcpy(pSBuf, ppArgV[i], nLen); + pSBuf += nLen; + if (bContainsSpace) { + *pSBuf++ = '\"'; + } + + if (i != nArgC - 1) { + *pSBuf++ = ' '; + } + } +} +bool CCommand::Tokenize(const char* pCommand, characterset_t* pBreakSet) { + __debugbreak(); + return false; +} +void CCommand::Reset() { + m_nArgv0Size = 0; + m_ArgSBuffer.RemoveAll(); + m_ArgvBuffer.RemoveAll(); + m_Args.RemoveAll(); +} + +characterset_t* CCommand::DefaultBreakSet() { return &s_BreakSet; } + +//----------------------------------------------------------------------------- +// Helper function to parse arguments to commands. +//----------------------------------------------------------------------------- +int CCommand::FindArg(const char* pName) const { + int nArgC = ArgC(); + for (int i = 1; i < nArgC; i++) { + if (!_stricmp(Arg(i), pName)) return (i + 1) < nArgC ? i + 1 : -1; + } + return -1; +} + +int CCommand::FindArgInt(const char* pName, int nDefaultVal) const { + int idx = FindArg(pName); + if (idx != -1) + return atoi(m_Args[idx]); + else + return nDefaultVal; +} + +//----------------------------------------------------------------------------- +// Default console command autocompletion function +//----------------------------------------------------------------------------- +int DefaultCompletionFunc(const char* partial, + CUtlVector& commands) { + return 0; } diff --git a/csgo2/sdk/convar/convar.hpp b/csgo2/sdk/convar/convar.hpp index d12a36b..2e90146 100644 --- a/csgo2/sdk/convar/convar.hpp +++ b/csgo2/sdk/convar/convar.hpp @@ -1,129 +1,83 @@ #pragma once #include "../sdk.h" -#include "../tier1/UtlVector.hpp" -struct characterset_t -{ - char set[256]; +struct characterset_t { + char set[256]; }; -class ConCommandBase -{ - friend class CCvar; - friend class ConCommand; +class ConCommandBase { + friend class CCvar; + friend class ConCommand; -protected: - ConCommandBase(void); -public: + protected: + ConCommandBase(void); - ~ConCommandBase(void); - // Check flag - bool IsFlagSet(int64_t flag) const; - // Set flag - void AddFlags(int64_t flags); - // Clear flag - void RemoveFlags(int64_t flags); + public: + ~ConCommandBase(void); + // Check flag + bool IsFlagSet(int64_t flag) const; + // Set flag + void AddFlags(int64_t flags); + // Clear flag + void RemoveFlags(int64_t flags); - int64_t GetFlags() const; + int64_t GetFlags() const; - // Return name of cvar - const char* GetName(void) const; + // Return name of cvar + const char* GetName(void) const; - // Return help text for cvar - const char* GetHelpText(void) const; + // Return help text for cvar + const char* GetHelpText(void) const; -private: - // Static data - const char* m_pszName; - const char* m_pszHelpString; + private: + // Static data + const char* m_pszName; + const char* m_pszHelpString; - // ConVar flags - int64_t m_nFlags; + // ConVar flags + int64_t m_nFlags; }; -template< class T, size_t SIZE, class I = int > -class CUtlMemoryFixedGrowable : public CUtlMemory< T, I > -{ - typedef CUtlMemory< T, I > BaseClass; +class CCommand { + public: + CCommand(); + CCommand(int nArgC, const char** ppArgV); + virtual bool Tokenize(const char* pCommand, + characterset_t* pBreakSet = NULL); + virtual void Reset(); -public: - CUtlMemoryFixedGrowable(int nGrowSize = 0, int nInitSize = SIZE) : BaseClass(m_pFixedMemory, SIZE) - { - Assert(nInitSize == 0 || nInitSize == SIZE); - } + int ArgC() const { return m_Args.Count(); } + const char** ArgV() const; + const char* ArgS() + const; // All args that occur after the 0th arg, in string form + const char* GetCommandString() const { + return ArgC() ? m_ArgSBuffer.Base() : ""; + } + const char* operator[](int nIndex) const; // Gets at arguments + const char* Arg(int nIndex) const { + // FIXME: Many command handlers appear to not be particularly careful + // about checking for valid argc range. For now, we're going to + // do the extra check and return an empty string if it's out of range + if (nIndex < 0 || nIndex >= ArgC()) return ""; + return m_Args[nIndex]; + } - void EnsureCapacity(int num) - { - if (CUtlMemory::m_nAllocationCount >= num) - return; + // Helper functions to parse arguments to commands. + // + // Returns index of argument, or -1 if no such argument. + int FindArg(const char* pName) const; - BaseClass::EnsureCapacity(num); - } + int FindArgInt(const char* pName, int nDefaultVal) const; -private: - T m_pFixedMemory[SIZE]; + static int MaxCommandLength() { return COMMAND_MAX_LENGTH - 1; } + static characterset_t* DefaultBreakSet(); + + private: + enum { + COMMAND_MAX_ARGC = 64, + COMMAND_MAX_LENGTH = 512, + }; + + int m_nArgv0Size; + CUtlVectorFixedGrowable m_ArgSBuffer; + CUtlVectorFixedGrowable m_ArgvBuffer; + CUtlVectorFixedGrowable m_Args; }; - -template< class T, size_t MAX_SIZE > -class CUtlVectorFixedGrowable : public CUtlVector< T, CUtlMemoryFixedGrowable > -{ - typedef CUtlVector< T, CUtlMemoryFixedGrowable > BaseClass; - -public: - // constructor, destructor - CUtlVectorFixedGrowable(int growSize = 0) : BaseClass(growSize, MAX_SIZE) {} -}; - - -class CCommand -{ -public: - CCommand(); - CCommand(int nArgC, const char** ppArgV); - virtual bool Tokenize(const char* pCommand, characterset_t* pBreakSet = NULL); - virtual void Reset(); - - int ArgC() const { - return m_Args.Count(); - } - const char** ArgV() const; - const char* ArgS() const; // All args that occur after the 0th arg, in string form - const char* GetCommandString() const - { - return ArgC() ? m_ArgSBuffer.Base() : ""; - } - const char* operator[](int nIndex) const; // Gets at arguments - const char* Arg(int nIndex) const { - // FIXME: Many command handlers appear to not be particularly careful - // about checking for valid argc range. For now, we're going to - // do the extra check and return an empty string if it's out of range - if (nIndex < 0 || nIndex >= ArgC()) - return ""; - return m_Args[nIndex]; - - } - - // Helper functions to parse arguments to commands. - // - // Returns index of argument, or -1 if no such argument. - int FindArg(const char* pName) const; - - int FindArgInt(const char* pName, int nDefaultVal) const; - - static int MaxCommandLength() - { - return COMMAND_MAX_LENGTH - 1; - } - static characterset_t* DefaultBreakSet(); - -private: - enum - { - COMMAND_MAX_ARGC = 64, - COMMAND_MAX_LENGTH = 512, - }; - - int m_nArgv0Size; - CUtlVectorFixedGrowable m_ArgSBuffer; - CUtlVectorFixedGrowable m_ArgvBuffer; - CUtlVectorFixedGrowable m_Args; -}; - diff --git a/csgo2/sdk/public/bitvec.h b/csgo2/sdk/public/bitvec.h index bdbf1d5..ddd55de 100644 --- a/csgo2/sdk/public/bitvec.h +++ b/csgo2/sdk/public/bitvec.h @@ -1,9 +1,3 @@ -//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - #ifndef BITVEC_H #define BITVEC_H #ifdef _WIN32 diff --git a/csgo2/sdk/public/irecipientfilter.h b/csgo2/sdk/public/irecipientfilter.h new file mode 100644 index 0000000..919b5c1 --- /dev/null +++ b/csgo2/sdk/public/irecipientfilter.h @@ -0,0 +1,17 @@ +#pragma once +#include "eiface.h" + +//----------------------------------------------------------------------------- +// Purpose: Generic interface for routing messages to users +//----------------------------------------------------------------------------- +class IRecipientFilter +{ +public: + virtual ~IRecipientFilter() {} + + virtual bool IsReliable(void) const = 0; + virtual bool IsInitMessage(void) const = 0; + + virtual int GetRecipientCount(void) const = 0; + virtual CEntityIndex GetRecipientIndex(int slot) const = 0; +}; \ No newline at end of file diff --git a/csgo2/sdk/public/recipientfilters.h b/csgo2/sdk/public/recipientfilters.h new file mode 100644 index 0000000..eda60dc --- /dev/null +++ b/csgo2/sdk/public/recipientfilters.h @@ -0,0 +1,62 @@ +#pragma once +#include "../sdk.h" + +class CSingleRecipientFilter : public IRecipientFilter +{ +public: + CSingleRecipientFilter(int iRecipient, bool bReliable = true, bool bInitMessage = false) : + m_iRecipient(iRecipient), m_bReliable(bReliable), m_bInitMessage(bInitMessage) {} + + ~CSingleRecipientFilter() override {} + + bool IsReliable(void) const override { return m_bReliable; } + + bool IsInitMessage(void) const override { return m_bInitMessage; } + + int GetRecipientCount(void) const override { return 1; } + + CEntityIndex GetRecipientIndex(int slot) const override { return CEntityIndex(m_iRecipient); } + +private: + bool m_bReliable; + bool m_bInitMessage; + int m_iRecipient; +}; + +class CCopyRecipientFilter : public IRecipientFilter +{ +public: + CCopyRecipientFilter(IRecipientFilter *source, int iExcept) + { + m_bReliable = source->IsReliable(); + m_bInitMessage = source->IsInitMessage(); + m_Recipients.RemoveAll(); + + for (int i = 0; i < source->GetRecipientCount(); i++) + { + if (source->GetRecipientIndex(i).Get() != iExcept) + m_Recipients.AddToTail(source->GetRecipientIndex(i)); + } + } + + ~CCopyRecipientFilter() override {} + + bool IsReliable(void) const override { return m_bReliable; } + + bool IsInitMessage(void) const override { return m_bInitMessage; } + + int GetRecipientCount(void) const override { return m_Recipients.Count(); } + + CEntityIndex GetRecipientIndex(int slot) const override + { + if (slot < 0 || slot >= GetRecipientCount()) + return CEntityIndex(-1); + + return m_Recipients[slot]; + } + +private: + bool m_bReliable; + bool m_bInitMessage; + CUtlVectorFixed m_Recipients; +}; \ No newline at end of file diff --git a/csgo2/sdk/public/utlrbtree.h b/csgo2/sdk/public/utlrbtree.h index 1cf8fae..182096e 100644 --- a/csgo2/sdk/public/utlrbtree.h +++ b/csgo2/sdk/public/utlrbtree.h @@ -1,11 +1,3 @@ -//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Header: $ -// $NoKeywords: $ -//=============================================================================// - #ifndef UTLRBTREE_H #define UTLRBTREE_H diff --git a/csgo2/sdk/sdk.h b/csgo2/sdk/sdk.h index 9838b4d..b3bbd01 100644 --- a/csgo2/sdk/sdk.h +++ b/csgo2/sdk/sdk.h @@ -1,61 +1,109 @@ #pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #define CORRECT_PATH_SEPARATOR '\\' #define CORRECT_PATH_SEPARATOR_S "\\" #define INCORRECT_PATH_SEPARATOR '/' #define INCORRECT_PATH_SEPARATOR_S "/" -#define FMTFUNCTION( a, b ) -enum EStringConvertErrorPolicy -{ - _STRINGCONVERTFLAG_SKIP = 1, - _STRINGCONVERTFLAG_FAIL = 2, - _STRINGCONVERTFLAG_ASSERT = 4, +#define FMTFUNCTION(a, b) +enum EStringConvertErrorPolicy { + _STRINGCONVERTFLAG_SKIP = 1, + _STRINGCONVERTFLAG_FAIL = 2, + _STRINGCONVERTFLAG_ASSERT = 4, - STRINGCONVERT_REPLACE = 0, - STRINGCONVERT_SKIP = _STRINGCONVERTFLAG_SKIP, - STRINGCONVERT_FAIL = _STRINGCONVERTFLAG_FAIL, + STRINGCONVERT_REPLACE = 0, + STRINGCONVERT_SKIP = _STRINGCONVERTFLAG_SKIP, + STRINGCONVERT_FAIL = _STRINGCONVERTFLAG_FAIL, - STRINGCONVERT_ASSERT_REPLACE = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_REPLACE, - STRINGCONVERT_ASSERT_SKIP = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_SKIP, - STRINGCONVERT_ASSERT_FAIL = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_FAIL, + STRINGCONVERT_ASSERT_REPLACE = + _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_REPLACE, + STRINGCONVERT_ASSERT_SKIP = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_SKIP, + STRINGCONVERT_ASSERT_FAIL = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_FAIL, }; -enum EUniverse -{ - k_EUniverseInvalid = 0, - k_EUniversePublic = 1, - k_EUniverseBeta = 2, - k_EUniverseInternal = 3, - k_EUniverseDev = 4, - // k_EUniverseRC = 5, // no such universe anymore - k_EUniverseMax +enum EUniverse { + k_EUniverseInvalid = 0, + k_EUniversePublic = 1, + k_EUniverseBeta = 2, + k_EUniverseInternal = 3, + k_EUniverseDev = 4, + // k_EUniverseRC = 5, // no such universe anymore + k_EUniverseMax }; #define Plat_FastMemset memset #define Plat_FastMemcpy memcpy -#define RESTRICT __restrict -#define RESTRICT_FUNC __declspec(restrict) -#define FORCEINLINE_TEMPLATE __forceinline +#define RESTRICT __restrict +#define RESTRICT_FUNC __declspec(restrict) +#define FORCEINLINE_TEMPLATE __forceinline #define PAD_NUMBER(number, boundary) \ - ( ((number) + ((boundary)-1)) / (boundary) ) * (boundary) + (((number) + ((boundary)-1)) / (boundary)) * (boundary) typedef __int64 intp; -#ifndef Assert +typedef unsigned __int64 uintp; // (ie, sizeof(intp) >= sizeof(int) && + // sizeof(intp) >= sizeof(void *) +typedef unsigned char uint8; +typedef signed char int8; +typedef __int16 int16; +typedef unsigned __int16 uint16; +typedef __int32 int32; +typedef unsigned __int32 uint32; +typedef __int64 int64; +typedef unsigned __int64 uint64; +typedef unsigned int uint; #define Assert -#endif // !Assert template -inline T* Construct(T* pMemory) -{ - return ::new(pMemory) T; +inline T* Construct(T* pMemory) { + return ::new (pMemory) T; } template -inline void Destruct(T* pMemory) -{ - pMemory->~T(); +inline void Destruct(T* pMemory) { + pMemory->~T(); #ifdef _DEBUG - memset((void*)pMemory, 0xDD, sizeof(T)); + memset((void*)pMemory, 0xDD, sizeof(T)); #endif } -#include "../head.h" \ No newline at end of file +template +inline T AlignValue(T val, uintptr_t alignment) { + return (T)(((uintptr_t)val + alignment - 1) & ~(alignment - 1)); +} + +#include "player/playerslot.h" + +#include "public/mathlib.h" +#include "public/string_t.h" +#include "tier1/UtlMemory.hpp" +#include "tier1/utlfixedmemory.h" +#include "tier1/utlblockmemory.h" +#include "tier1/UtlString.hpp" +#include "tier1/UtlVector.hpp" +#include "tier1/bufferstring.h" +#include "tier1/cbyteswap.h" + +#include "tier1/utlbuffer.h" + +#include "public/eiface.h" +#include "public/bitvec.h" +#include "public/iserver.h" +#include "public/utlrbtree.h" +#include "public/utlmap.h" +#include "public/IRecipientFilter.h" +#include "public/recipientfilters.h" +#include "interfaces/interfaces.h" +#include "gameevent/IGameEvent.h" +#include "convar/convar.hpp" + +#include "gameevent/IGameEvent.h" +#include "tier1/bufferstring.h" +#include "public/eiface.h" diff --git a/csgo2/sdk/tier1/UtlMemory.hpp b/csgo2/sdk/tier1/UtlMemory.hpp index 59039ce..f856b1a 100644 --- a/csgo2/sdk/tier1/UtlMemory.hpp +++ b/csgo2/sdk/tier1/UtlMemory.hpp @@ -4,10 +4,11 @@ #define UTLMEMORY_TRACK_ALLOC() #define MEM_ALLOC_CREDIT_CLASS() #define UTLMEMORY_TRACK_FREE() -template< class T, class I = int > -class CUtlMemory -{ -public: +#define Assert + +template +class CUtlMemory { + public: // constructor, destructor CUtlMemory(int nGrowSize = 0, int nInitSize = 0); CUtlMemory(T* pMemory, int numElements); @@ -17,20 +18,26 @@ public: // Set the size by which the memory grows void Init(int nGrowSize = 0, int nInitSize = 0); - class Iterator_t - { - public: + class Iterator_t { + public: Iterator_t(I i) : index(i) {} I index; bool operator==(const Iterator_t it) const { return index == it.index; } bool operator!=(const Iterator_t it) const { return index != it.index; } }; - Iterator_t First() const { return Iterator_t(IsIdxValid(0) ? 0 : InvalidIndex()); } - Iterator_t Next(const Iterator_t &it) const { return Iterator_t(IsIdxValid(it.index + 1) ? it.index + 1 : InvalidIndex()); } - I GetIndex(const Iterator_t &it) const { return it.index; } - bool IsIdxAfter(I i, const Iterator_t &it) const { return i > it.index; } - bool IsValidIterator(const Iterator_t &it) const { return IsIdxValid(it.index); } + Iterator_t First() const { + return Iterator_t(IsIdxValid(0) ? 0 : InvalidIndex()); + } + Iterator_t Next(const Iterator_t& it) const { + return Iterator_t(IsIdxValid(it.index + 1) ? it.index + 1 + : InvalidIndex()); + } + I GetIndex(const Iterator_t& it) const { return it.index; } + bool IsIdxAfter(I i, const Iterator_t& it) const { return i > it.index; } + bool IsValidIterator(const Iterator_t& it) const { + return IsIdxValid(it.index); + } Iterator_t InvalidIterator() const { return Iterator_t(InvalidIndex()); } // element access @@ -41,7 +48,7 @@ public: bool IsIdxValid(I i) const; - static const I INVALID_INDEX = (I)-1; // For use with COMPILE_TIME_ASSERT + static const I INVALID_INDEX = (I)-1; // For use with COMPILE_TIME_ASSERT static I InvalidIndex() { return INVALID_INDEX; } T* Base(); @@ -49,11 +56,11 @@ public: void SetExternalBuffer(T* pMemory, int numElements); void SetExternalBuffer(const T* pMemory, int numElements); - void AssumeMemory(T *pMemory, int nSize); + void AssumeMemory(T* pMemory, int nSize); T* Detach(); - void *DetachMemory(); + void* DetachMemory(); - void Swap(CUtlMemory< T, I > &mem); + void Swap(CUtlMemory& mem); void ConvertToGrowableMemory(int nGrowSize); int NumAllocated() const; int Count() const; @@ -65,14 +72,10 @@ public: bool IsReadOnly() const; void SetGrowSize(int size); -protected: - void ValidateGrowSize() - { + protected: + void ValidateGrowSize() {} - } - - enum - { + enum { EXTERNAL_BUFFER_MARKER = -1, EXTERNAL_CONST_BUFFER_MARKER = -2, }; @@ -86,48 +89,45 @@ protected: // constructor, destructor //----------------------------------------------------------------------------- -template< class T, class I > -CUtlMemory::CUtlMemory(int nGrowSize, int nInitAllocationCount) : m_pMemory(0), -m_nAllocationCount(nInitAllocationCount), m_nGrowSize(nGrowSize) -{ +template +CUtlMemory::CUtlMemory(int nGrowSize, int nInitAllocationCount) + : m_pMemory(0), + m_nAllocationCount(nInitAllocationCount), + m_nGrowSize(nGrowSize) { ValidateGrowSize(); - if(m_nAllocationCount) { + if (m_nAllocationCount) { m_pMemory = (T*)new unsigned char[m_nAllocationCount * sizeof(T)]; - //m_pMemory = (T*)malloc(m_nAllocationCount * sizeof(T)); + // m_pMemory = (T*)malloc(m_nAllocationCount * sizeof(T)); } } -template< class T, class I > -CUtlMemory::CUtlMemory(T* pMemory, int numElements) : m_pMemory(pMemory), -m_nAllocationCount(numElements) -{ +template +CUtlMemory::CUtlMemory(T* pMemory, int numElements) + : m_pMemory(pMemory), m_nAllocationCount(numElements) { // Special marker indicating externally supplied modifyable memory m_nGrowSize = EXTERNAL_BUFFER_MARKER; } -template< class T, class I > -CUtlMemory::CUtlMemory(const T* pMemory, int numElements) : m_pMemory((T*)pMemory), -m_nAllocationCount(numElements) -{ +template +CUtlMemory::CUtlMemory(const T* pMemory, int numElements) + : m_pMemory((T*)pMemory), m_nAllocationCount(numElements) { // Special marker indicating externally supplied modifyable memory m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER; } -template< class T, class I > -CUtlMemory::~CUtlMemory() -{ +template +CUtlMemory::~CUtlMemory() { Purge(); } -template< class T, class I > -void CUtlMemory::Init(int nGrowSize /*= 0*/, int nInitSize /*= 0*/) -{ +template +void CUtlMemory::Init(int nGrowSize /*= 0*/, int nInitSize /*= 0*/) { Purge(); m_nGrowSize = nGrowSize; m_nAllocationCount = nInitSize; ValidateGrowSize(); - if(m_nAllocationCount) { + if (m_nAllocationCount) { UTLMEMORY_TRACK_ALLOC(); MEM_ALLOC_CREDIT_CLASS(); m_pMemory = (T*)malloc(m_nAllocationCount * sizeof(T)); @@ -137,28 +137,24 @@ void CUtlMemory::Init(int nGrowSize /*= 0*/, int nInitSize /*= 0*/) //----------------------------------------------------------------------------- // Fast swap //----------------------------------------------------------------------------- -template< class T, class I > -void CUtlMemory::Swap(CUtlMemory &mem) -{ +template +void CUtlMemory::Swap(CUtlMemory& mem) { V_swap(m_nGrowSize, mem.m_nGrowSize); V_swap(m_pMemory, mem.m_pMemory); V_swap(m_nAllocationCount, mem.m_nAllocationCount); } - //----------------------------------------------------------------------------- // Switches the buffer from an external memory buffer to a reallocatable buffer //----------------------------------------------------------------------------- -template< class T, class I > -void CUtlMemory::ConvertToGrowableMemory(int nGrowSize) -{ - if(!IsExternallyAllocated()) - return; +template +void CUtlMemory::ConvertToGrowableMemory(int nGrowSize) { + if (!IsExternallyAllocated()) return; m_nGrowSize = nGrowSize; - if(m_nAllocationCount) { + if (m_nAllocationCount) { int nNumBytes = m_nAllocationCount * sizeof(T); - T *pMemory = (T*)malloc(nNumBytes); + T* pMemory = (T*)malloc(nNumBytes); memcpy(pMemory, m_pMemory, nNumBytes); m_pMemory = pMemory; } else { @@ -166,13 +162,11 @@ void CUtlMemory::ConvertToGrowableMemory(int nGrowSize) } } - //----------------------------------------------------------------------------- // Attaches the buffer to external memory.... //----------------------------------------------------------------------------- -template< class T, class I > -void CUtlMemory::SetExternalBuffer(T* pMemory, int numElements) -{ +template +void CUtlMemory::SetExternalBuffer(T* pMemory, int numElements) { // Blow away any existing allocated memory Purge(); @@ -183,9 +177,8 @@ void CUtlMemory::SetExternalBuffer(T* pMemory, int numElements) m_nGrowSize = EXTERNAL_BUFFER_MARKER; } -template< class T, class I > -void CUtlMemory::SetExternalBuffer(const T* pMemory, int numElements) -{ +template +void CUtlMemory::SetExternalBuffer(const T* pMemory, int numElements) { // Blow away any existing allocated memory Purge(); @@ -196,9 +189,8 @@ void CUtlMemory::SetExternalBuffer(const T* pMemory, int numElements) m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER; } -template< class T, class I > -void CUtlMemory::AssumeMemory(T* pMemory, int numElements) -{ +template +void CUtlMemory::AssumeMemory(T* pMemory, int numElements) { // Blow away any existing allocated memory Purge(); @@ -207,121 +199,100 @@ void CUtlMemory::AssumeMemory(T* pMemory, int numElements) m_nAllocationCount = numElements; } -template< class T, class I > -void *CUtlMemory::DetachMemory() -{ - if(IsExternallyAllocated()) - return NULL; +template +void* CUtlMemory::DetachMemory() { + if (IsExternallyAllocated()) return NULL; - void *pMemory = m_pMemory; + void* pMemory = m_pMemory; m_pMemory = 0; m_nAllocationCount = 0; return pMemory; } -template< class T, class I > -inline T* CUtlMemory::Detach() -{ +template +inline T* CUtlMemory::Detach() { return (T*)DetachMemory(); } - //----------------------------------------------------------------------------- // element access //----------------------------------------------------------------------------- -template< class T, class I > -inline T& CUtlMemory::operator[](I i) -{ +template +inline T& CUtlMemory::operator[](I i) { return m_pMemory[i]; } -template< class T, class I > -inline const T& CUtlMemory::operator[](I i) const -{ +template +inline const T& CUtlMemory::operator[](I i) const { return m_pMemory[i]; } -template< class T, class I > -inline T& CUtlMemory::Element(I i) -{ +template +inline T& CUtlMemory::Element(I i) { return m_pMemory[i]; } -template< class T, class I > -inline const T& CUtlMemory::Element(I i) const -{ +template +inline const T& CUtlMemory::Element(I i) const { return m_pMemory[i]; } - //----------------------------------------------------------------------------- // is the memory externally allocated? //----------------------------------------------------------------------------- -template< class T, class I > -bool CUtlMemory::IsExternallyAllocated() const -{ +template +bool CUtlMemory::IsExternallyAllocated() const { return (m_nGrowSize < 0); } - //----------------------------------------------------------------------------- // is the memory read only? //----------------------------------------------------------------------------- -template< class T, class I > -bool CUtlMemory::IsReadOnly() const -{ +template +bool CUtlMemory::IsReadOnly() const { return (m_nGrowSize == EXTERNAL_CONST_BUFFER_MARKER); } - -template< class T, class I > -void CUtlMemory::SetGrowSize(int nSize) -{ +template +void CUtlMemory::SetGrowSize(int nSize) { m_nGrowSize = nSize; ValidateGrowSize(); } - //----------------------------------------------------------------------------- // Gets the base address (can change when adding elements!) //----------------------------------------------------------------------------- -template< class T, class I > -inline T* CUtlMemory::Base() -{ +template +inline T* CUtlMemory::Base() { return m_pMemory; } -template< class T, class I > -inline const T *CUtlMemory::Base() const -{ +template +inline const T* CUtlMemory::Base() const { return m_pMemory; } - //----------------------------------------------------------------------------- // Size //----------------------------------------------------------------------------- -template< class T, class I > -inline int CUtlMemory::NumAllocated() const -{ +template +inline int CUtlMemory::NumAllocated() const { return m_nAllocationCount; } -template< class T, class I > -inline int CUtlMemory::Count() const -{ +template +inline int CUtlMemory::Count() const { return m_nAllocationCount; } - //----------------------------------------------------------------------------- // Is element index valid? //----------------------------------------------------------------------------- -template< class T, class I > -inline bool CUtlMemory::IsIdxValid(I i) const -{ - // GCC warns if I is an unsigned type and we do a ">= 0" against it (since the comparison is always 0). - // We Get the warning even if we cast inside the expression. It only goes away if we assign to another variable. +template +inline bool CUtlMemory::IsIdxValid(I i) const { + // GCC warns if I is an unsigned type and we do a ">= 0" against it (since + // the comparison is always 0). We Get the warning even if we cast inside + // the expression. It only goes away if we assign to another variable. long x = i; return (x >= 0) && (x < m_nAllocationCount); } @@ -329,22 +300,22 @@ inline bool CUtlMemory::IsIdxValid(I i) const //----------------------------------------------------------------------------- // Grows the memory //----------------------------------------------------------------------------- -inline int UtlMemory_CalcNewAllocationCount(int nAllocationCount, int nGrowSize, int nNewSize, int nBytesItem) -{ - if(nGrowSize) { +inline int UtlMemory_CalcNewAllocationCount(int nAllocationCount, int nGrowSize, + int nNewSize, int nBytesItem) { + if (nGrowSize) { nAllocationCount = ((1 + ((nNewSize - 1) / nGrowSize)) * nGrowSize); } else { - if(!nAllocationCount) { + if (!nAllocationCount) { // Compute an allocation which is at least as big as a cache line... nAllocationCount = (31 + nBytesItem) / nBytesItem; } - while(nAllocationCount < nNewSize) { + while (nAllocationCount < nNewSize) { #ifndef _X360 nAllocationCount *= 2; #else - int nNewAllocationCount = (nAllocationCount * 9) / 8; // 12.5 % - if(nNewAllocationCount > nAllocationCount) + int nNewAllocationCount = (nAllocationCount * 9) / 8; // 12.5 % + if (nNewAllocationCount > nAllocationCount) nAllocationCount = nNewAllocationCount; else nAllocationCount *= 2; @@ -355,40 +326,43 @@ inline int UtlMemory_CalcNewAllocationCount(int nAllocationCount, int nGrowSize, return nAllocationCount; } -template< class T, class I > -void CUtlMemory::Grow(int num) -{ - if(IsExternallyAllocated()) { - // Can't grow a buffer whose memory was externally allocated +template +void CUtlMemory::Grow(int num) { + if (IsExternallyAllocated()) { + // Can't grow a buffer whose memory was externally allocated return; } - auto oldAllocationCount = m_nAllocationCount; // Make sure we have at least numallocated + num allocations. // Use the grow rules specified for this memory (in m_nGrowSize) int nAllocationRequested = m_nAllocationCount + num; - int nNewAllocationCount = UtlMemory_CalcNewAllocationCount(m_nAllocationCount, m_nGrowSize, nAllocationRequested, sizeof(T)); + int nNewAllocationCount = UtlMemory_CalcNewAllocationCount( + m_nAllocationCount, m_nGrowSize, nAllocationRequested, sizeof(T)); // if m_nAllocationRequested wraps index type I, recalculate - if((int)(I)nNewAllocationCount < nAllocationRequested) { - if((int)(I)nNewAllocationCount == 0 && (int)(I)(nNewAllocationCount - 1) >= nAllocationRequested) { - --nNewAllocationCount; // deal w/ the common case of m_nAllocationCount == MAX_USHORT + 1 + if ((int)(I)nNewAllocationCount < nAllocationRequested) { + if ((int)(I)nNewAllocationCount == 0 && + (int)(I)(nNewAllocationCount - 1) >= nAllocationRequested) { + --nNewAllocationCount; // deal w/ the common case of + // m_nAllocationCount == MAX_USHORT + 1 } else { - if((int)(I)nAllocationRequested != nAllocationRequested) { - // we've been asked to grow memory to a size s.t. the index type can't address the requested amount of memory + if ((int)(I)nAllocationRequested != nAllocationRequested) { + // we've been asked to grow memory to a size s.t. the index type + // can't address the requested amount of memory return; } - while((int)(I)nNewAllocationCount < nAllocationRequested) { - nNewAllocationCount = (nNewAllocationCount + nAllocationRequested) / 2; + while ((int)(I)nNewAllocationCount < nAllocationRequested) { + nNewAllocationCount = + (nNewAllocationCount + nAllocationRequested) / 2; } } } m_nAllocationCount = nNewAllocationCount; - if(m_pMemory) { + if (m_pMemory) { auto ptr = new unsigned char[m_nAllocationCount * sizeof(T)]; memcpy(ptr, m_pMemory, oldAllocationCount * sizeof(T)); @@ -398,38 +372,33 @@ void CUtlMemory::Grow(int num) } } - //----------------------------------------------------------------------------- // Makes sure we've got at least this much memory //----------------------------------------------------------------------------- -template< class T, class I > -inline void CUtlMemory::EnsureCapacity(int num) -{ - if(m_nAllocationCount >= num) - return; +template +inline void CUtlMemory::EnsureCapacity(int num) { + if (m_nAllocationCount >= num) return; - if(IsExternallyAllocated()) { - // Can't grow a buffer whose memory was externally allocated + if (IsExternallyAllocated()) { + // Can't grow a buffer whose memory was externally allocated return; } m_nAllocationCount = num; - if(m_pMemory) { + if (m_pMemory) { m_pMemory = (T*)realloc(m_pMemory, m_nAllocationCount * sizeof(T)); } else { m_pMemory = (T*)malloc(m_nAllocationCount * sizeof(T)); } } - //----------------------------------------------------------------------------- // Memory deallocation //----------------------------------------------------------------------------- -template< class T, class I > -void CUtlMemory::Purge() -{ - if(!IsExternallyAllocated()) { - if(m_pMemory) { +template +void CUtlMemory::Purge() { + if (!IsExternallyAllocated()) { + if (m_pMemory) { free((void*)m_pMemory); m_pMemory = 0; } @@ -437,33 +406,32 @@ void CUtlMemory::Purge() } } -template< class T, class I > -void CUtlMemory::Purge(int numElements) -{ - - if(numElements > m_nAllocationCount) { +template +void CUtlMemory::Purge(int numElements) { + if (numElements > m_nAllocationCount) { // Ensure this isn't a grow request in disguise. return; } // If we have zero elements, simply do a purge: - if(numElements == 0) { + if (numElements == 0) { Purge(); return; } - if(IsExternallyAllocated()) { - // Can't shrink a buffer whose memory was externally allocated, fail silently like purge + if (IsExternallyAllocated()) { + // Can't shrink a buffer whose memory was externally allocated, fail + // silently like purge return; } - // If the number of elements is the same as the allocation count, we are done. - if(numElements == m_nAllocationCount) { + // If the number of elements is the same as the allocation count, we are + // done. + if (numElements == m_nAllocationCount) { return; } - - if(!m_pMemory) { + if (!m_pMemory) { // Allocation count is non zero, but memory is null. assert(m_pMemory); return; @@ -476,10 +444,9 @@ void CUtlMemory::Purge(int numElements) // The CUtlMemory class: // A growable memory class which doubles in size by default. //----------------------------------------------------------------------------- -template< class T, int nAlignment > -class CUtlMemoryAligned : public CUtlMemory -{ -public: +template +class CUtlMemoryAligned : public CUtlMemory { + public: // constructor, destructor CUtlMemoryAligned(int nGrowSize = 0, int nInitSize = 0); CUtlMemoryAligned(T* pMemory, int numElements); @@ -499,31 +466,29 @@ public: // Memory deallocation void Purge(); - // Purge all but the given number of elements (NOT IMPLEMENTED IN CUtlMemoryAligned) + // Purge all but the given number of elements (NOT IMPLEMENTED IN + // CUtlMemoryAligned) void Purge(int numElements) { __debugbreak(); } -private: - void *Align(const void *pAddr); + private: + void* Align(const void* pAddr); }; - //----------------------------------------------------------------------------- // Aligns a pointer //----------------------------------------------------------------------------- -template< class T, int nAlignment > -void *CUtlMemoryAligned::Align(const void *pAddr) -{ +template +void* CUtlMemoryAligned::Align(const void* pAddr) { size_t nAlignmentMask = nAlignment - 1; return (void*)(((size_t)pAddr + nAlignmentMask) & (~nAlignmentMask)); } - //----------------------------------------------------------------------------- // constructor, destructor //----------------------------------------------------------------------------- -template< class T, int nAlignment > -CUtlMemoryAligned::CUtlMemoryAligned(int nGrowSize, int nInitAllocationCount) -{ +template +CUtlMemoryAligned::CUtlMemoryAligned(int nGrowSize, + int nInitAllocationCount) { CUtlMemory::m_pMemory = 0; CUtlMemory::m_nAllocationCount = nInitAllocationCount; CUtlMemory::m_nGrowSize = nGrowSize; @@ -531,78 +496,83 @@ CUtlMemoryAligned::CUtlMemoryAligned(int nGrowSize, int nInitAllo // Alignment must be a power of two COMPILE_TIME_ASSERT((nAlignment & (nAlignment - 1)) == 0); - if(CUtlMemory::m_nAllocationCount) { + if (CUtlMemory::m_nAllocationCount) { UTLMEMORY_TRACK_ALLOC(); MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_malloc(nInitAllocationCount * sizeof(T), nAlignment); + CUtlMemory::m_pMemory = + (T*)_aligned_malloc(nInitAllocationCount * sizeof(T), nAlignment); } } -template< class T, int nAlignment > -CUtlMemoryAligned::CUtlMemoryAligned(T* pMemory, int numElements) -{ +template +CUtlMemoryAligned::CUtlMemoryAligned(T* pMemory, + int numElements) { // Special marker indicating externally supplied memory CUtlMemory::m_nGrowSize = CUtlMemory::EXTERNAL_BUFFER_MARKER; CUtlMemory::m_pMemory = (T*)Align(pMemory); - CUtlMemory::m_nAllocationCount = ((int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory) / sizeof(T); + CUtlMemory::m_nAllocationCount = + ((int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory) / + sizeof(T); } -template< class T, int nAlignment > -CUtlMemoryAligned::CUtlMemoryAligned(const T* pMemory, int numElements) -{ +template +CUtlMemoryAligned::CUtlMemoryAligned(const T* pMemory, + int numElements) { // Special marker indicating externally supplied memory CUtlMemory::m_nGrowSize = CUtlMemory::EXTERNAL_CONST_BUFFER_MARKER; CUtlMemory::m_pMemory = (T*)Align(pMemory); - CUtlMemory::m_nAllocationCount = ((int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory) / sizeof(T); + CUtlMemory::m_nAllocationCount = + ((int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory) / + sizeof(T); } -template< class T, int nAlignment > -CUtlMemoryAligned::~CUtlMemoryAligned() -{ +template +CUtlMemoryAligned::~CUtlMemoryAligned() { Purge(); } - //----------------------------------------------------------------------------- // Attaches the buffer to external memory.... //----------------------------------------------------------------------------- -template< class T, int nAlignment > -void CUtlMemoryAligned::SetExternalBuffer(T* pMemory, int numElements) -{ +template +void CUtlMemoryAligned::SetExternalBuffer(T* pMemory, + int numElements) { // Blow away any existing allocated memory Purge(); CUtlMemory::m_pMemory = (T*)Align(pMemory); - CUtlMemory::m_nAllocationCount = ((int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory) / sizeof(T); + CUtlMemory::m_nAllocationCount = + ((int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory) / + sizeof(T); // Indicate that we don't own the memory CUtlMemory::m_nGrowSize = CUtlMemory::EXTERNAL_BUFFER_MARKER; } -template< class T, int nAlignment > -void CUtlMemoryAligned::SetExternalBuffer(const T* pMemory, int numElements) -{ +template +void CUtlMemoryAligned::SetExternalBuffer(const T* pMemory, + int numElements) { // Blow away any existing allocated memory Purge(); CUtlMemory::m_pMemory = (T*)Align(pMemory); - CUtlMemory::m_nAllocationCount = ((int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory) / sizeof(T); + CUtlMemory::m_nAllocationCount = + ((int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory) / + sizeof(T); // Indicate that we don't own the memory CUtlMemory::m_nGrowSize = CUtlMemory::EXTERNAL_CONST_BUFFER_MARKER; } - //----------------------------------------------------------------------------- // Grows the memory //----------------------------------------------------------------------------- -template< class T, int nAlignment > -void CUtlMemoryAligned::Grow(int num) -{ - if(this->IsExternallyAllocated()) { - // Can't grow a buffer whose memory was externally allocated +template +void CUtlMemoryAligned::Grow(int num) { + if (this->IsExternallyAllocated()) { + // Can't grow a buffer whose memory was externally allocated return; } @@ -612,31 +582,33 @@ void CUtlMemoryAligned::Grow(int num) // Use the grow rules specified for this memory (in m_nGrowSize) int nAllocationRequested = CUtlMemory::m_nAllocationCount + num; - CUtlMemory::m_nAllocationCount = UtlMemory_CalcNewAllocationCount(CUtlMemory::m_nAllocationCount, CUtlMemory::m_nGrowSize, nAllocationRequested, sizeof(T)); + CUtlMemory::m_nAllocationCount = UtlMemory_CalcNewAllocationCount( + CUtlMemory::m_nAllocationCount, CUtlMemory::m_nGrowSize, + nAllocationRequested, sizeof(T)); UTLMEMORY_TRACK_ALLOC(); - if(CUtlMemory::m_pMemory) { + if (CUtlMemory::m_pMemory) { MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)MemAlloc_ReallocAligned(CUtlMemory::m_pMemory, CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment); + CUtlMemory::m_pMemory = (T*)MemAlloc_ReallocAligned( + CUtlMemory::m_pMemory, + CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment); } else { MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)MemAlloc_AllocAligned(CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment); + CUtlMemory::m_pMemory = (T*)MemAlloc_AllocAligned( + CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment); } } - //----------------------------------------------------------------------------- // Makes sure we've got at least this much memory //----------------------------------------------------------------------------- -template< class T, int nAlignment > -inline void CUtlMemoryAligned::EnsureCapacity(int num) -{ - if(CUtlMemory::m_nAllocationCount >= num) - return; +template +inline void CUtlMemoryAligned::EnsureCapacity(int num) { + if (CUtlMemory::m_nAllocationCount >= num) return; - if(this->IsExternallyAllocated()) { - // Can't grow a buffer whose memory was externally allocated + if (this->IsExternallyAllocated()) { + // Can't grow a buffer whose memory was externally allocated return; } @@ -646,28 +618,131 @@ inline void CUtlMemoryAligned::EnsureCapacity(int num) UTLMEMORY_TRACK_ALLOC(); - if(CUtlMemory::m_pMemory) { + if (CUtlMemory::m_pMemory) { MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)MemAlloc_ReallocAligned(CUtlMemory::m_pMemory, CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment); + CUtlMemory::m_pMemory = (T*)MemAlloc_ReallocAligned( + CUtlMemory::m_pMemory, + CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment); } else { MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)MemAlloc_AllocAligned(CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment); + CUtlMemory::m_pMemory = (T*)MemAlloc_AllocAligned( + CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment); } } - //----------------------------------------------------------------------------- // Memory deallocation //----------------------------------------------------------------------------- -template< class T, int nAlignment > -void CUtlMemoryAligned::Purge() -{ - if(!this->IsExternallyAllocated()) { - if(CUtlMemory::m_pMemory) { +template +void CUtlMemoryAligned::Purge() { + if (!this->IsExternallyAllocated()) { + if (CUtlMemory::m_pMemory) { UTLMEMORY_TRACK_FREE(); MemAlloc_FreeAligned(CUtlMemory::m_pMemory); CUtlMemory::m_pMemory = 0; } CUtlMemory::m_nAllocationCount = 0; } -} \ No newline at end of file +} + +//----------------------------------------------------------------------------- +// The CUtlMemoryFixed class: +// A fixed memory class +//----------------------------------------------------------------------------- +template +class CUtlMemoryFixed { + public: + // constructor, destructor + CUtlMemoryFixed(int nGrowSize = 0, int nInitSize = 0) { + } + CUtlMemoryFixed(T* pMemory, int numElements) { ; } + + // Can we use this index? + bool IsIdxValid(int i) const { return (i >= 0) && (i < SIZE); } + + // Specify the invalid ('null') index that we'll only return on failure + static const int INVALID_INDEX = -1; // For use with COMPILE_TIME_ASSERT + static int InvalidIndex() { return INVALID_INDEX; } + + // Gets the base address + T* Base() { + if (nAlignment == 0) + return (T*)(&m_Memory[0]); + else + return (T*)AlignValue(&m_Memory[0], nAlignment); + } + const T* Base() const { + if (nAlignment == 0) + return (T*)(&m_Memory[0]); + else + return (T*)AlignValue(&m_Memory[0], nAlignment); + } + + // element access + T& operator[](int i) { + Assert(IsIdxValid(i)); + return Base()[i]; + } + const T& operator[](int i) const { + Assert(IsIdxValid(i)); + return Base()[i]; + } + T& Element(int i) { + Assert(IsIdxValid(i)); + return Base()[i]; + } + const T& Element(int i) const { + Assert(IsIdxValid(i)); + return Base()[i]; + } + + // Attaches the buffer to external memory.... + void SetExternalBuffer(T* pMemory, int numElements) { } + + // Size + int NumAllocated() const { return SIZE; } + int Count() const { return SIZE; } + + // Grows the memory, so that at least allocated + num elements are allocated + void Grow(int num = 1) { Assert(0); } + + // Makes sure we've got at least this much memory + void EnsureCapacity(int num) { Assert(num <= SIZE); } + + // Memory deallocation + void Purge() {} + + // Purge all but the given number of elements (NOT IMPLEMENTED IN + // CUtlMemoryFixed) + void Purge(int numElements) { Assert(0); } + + // is the memory externally allocated? + bool IsExternallyAllocated() const { return false; } + + // Set the size by which the memory grows + void SetGrowSize(int size) {} + + class Iterator_t { + public: + Iterator_t(int i) : index(i) {} + int index; + bool operator==(const Iterator_t it) const { return index == it.index; } + bool operator!=(const Iterator_t it) const { return index != it.index; } + }; + Iterator_t First() const { + return Iterator_t(IsIdxValid(0) ? 0 : InvalidIndex()); + } + Iterator_t Next(const Iterator_t& it) const { + return Iterator_t(IsIdxValid(it.index + 1) ? it.index + 1 + : InvalidIndex()); + } + int GetIndex(const Iterator_t& it) const { return it.index; } + bool IsIdxAfter(int i, const Iterator_t& it) const { return i > it.index; } + bool IsValidIterator(const Iterator_t& it) const { + return IsIdxValid(it.index); + } + Iterator_t InvalidIterator() const { return Iterator_t(InvalidIndex()); } + + private: + char m_Memory[SIZE * sizeof(T) + nAlignment]; +}; diff --git a/csgo2/sdk/tier1/UtlVector.hpp b/csgo2/sdk/tier1/UtlVector.hpp index 2e77cd1..dfaa9ee 100644 --- a/csgo2/sdk/tier1/UtlVector.hpp +++ b/csgo2/sdk/tier1/UtlVector.hpp @@ -1,21 +1,18 @@ #pragma once -#include -#include -#include "UtlMemory.hpp" +#include "../sdk.h" #define _Utl_Vector_assert template -inline T* CopyConstruct(T* pMemory, T const& src) -{ - return ::new(pMemory) T(src); +inline T* CopyConstruct(T* pMemory, T const& src) { + return ::new (pMemory) T(src); } -template< class T, class A = CUtlMemory > -class CUtlVector -{ - typedef T *iterator; - typedef const T *const_iterator; +template > +class CUtlVector { + typedef T* iterator; + typedef const T* const_iterator; typedef A CAllocator; -public: + + public: typedef T ElemType_t; // constructor, destructor @@ -24,7 +21,7 @@ public: ~CUtlVector(); // Copy the array. - CUtlVector& operator=(const CUtlVector &other); + CUtlVector& operator=(const CUtlVector& other); // element access T& operator[](int i); @@ -57,52 +54,60 @@ public: // Adds multiple elements, uses default constructor int AddMultipleToHead(int num); int AddMultipleToTail(int num); - int AddMultipleToTail(int num, const T *pToCopy); + int AddMultipleToTail(int num, const T* pToCopy); int InsertMultipleBefore(int elem, int num); - int InsertMultipleBefore(int elem, int num, const T *pToCopy); + int InsertMultipleBefore(int elem, int num, const T* pToCopy); int InsertMultipleAfter(int elem, int num); // Calls RemoveAll() then AddMultipleToTail. void SetSize(int size); void SetCount(int count); - void SetCountNonDestructively(int count); //sets count by adding or removing elements to tail TODO: This should probably be the default behavior for SetCount - void CopyArray(const T *pArray, int size); //Calls SetSize and copies each element. - // Fast swap - void Swap(CUtlVector< T, A > &vec); + void SetCountNonDestructively( + int count); // sets count by adding or removing elements to tail TODO: + // This should probably be the default behavior for + // SetCount + void CopyArray(const T* pArray, + int size); // Calls SetSize and copies each element. + // Fast swap + void Swap(CUtlVector& vec); // Add the specified array to the tail. - int AddVectorToTail(CUtlVector const &src); + int AddVectorToTail(CUtlVector const& src); // Finds an element (element needs operator== defined) int GetOffset(const T& src) const; void FillWithValue(const T& src); bool HasElement(const T& src) const; - // Makes sure we have enough memory allocated to store a requested # of elements + // Makes sure we have enough memory allocated to store a requested # of + // elements void EnsureCapacity(int num); // Makes sure we have at least this many elements void EnsureCount(int num); // Element removal - void FastRemove(int elem); // doesn't preserve order - void Remove(int elem); // preserves order, shifts elements - bool FindAndRemove(const T& src); // removes first occurrence of src, preserves order, shifts elements - bool FindAndFastRemove(const T& src); // removes first occurrence of src, doesn't preserve order - void RemoveMultiple(int elem, int num); // preserves order, shifts elements - void RemoveMultipleFromHead(int num); // removes num elements from tail - void RemoveMultipleFromTail(int num); // removes num elements from tail - void RemoveAll(); // doesn't deallocate memory - void Purge(); // Memory deallocation - // Purges the list and calls delete on each element in it. + void FastRemove(int elem); // doesn't preserve order + void Remove(int elem); // preserves order, shifts elements + bool FindAndRemove(const T& src); // removes first occurrence of src, + // preserves order, shifts elements + bool FindAndFastRemove(const T& src); // removes first occurrence of src, + // doesn't preserve order + void RemoveMultiple(int elem, int num); // preserves order, shifts elements + void RemoveMultipleFromHead(int num); // removes num elements from tail + void RemoveMultipleFromTail(int num); // removes num elements from tail + void RemoveAll(); // doesn't deallocate memory + void Purge(); // Memory deallocation + // Purges the list and calls delete on each element in it. void PurgeAndDeleteElements(); - // Compacts the vector to the number of elements actually in use + // Compacts the vector to the number of elements actually in use void Compact(); // Set the size by which it grows when it needs to allocate more memory. void SetGrowSize(int size) { m_Memory.SetGrowSize(size); } - int NumAllocated() const; // Only use this if you really know what you're doing! - void Sort(int(__cdecl *pfnCompare)(const T *, const T *)); + int NumAllocated() + const; // Only use this if you really know what you're doing! + void Sort(int(__cdecl* pfnCompare)(const T*, const T*)); - iterator begin() { return Base(); } - const_iterator begin() const { return Base(); } - iterator end() { return Base() + Count(); } - const_iterator end() const { return Base() + Count(); } + iterator begin() { return Base(); } + const_iterator begin() const { return Base(); } + iterator end() { return Base() + Count(); } + const_iterator end() const { return Base() + Count(); } -protected: + protected: // Can't copy this unless we explicitly do it! CUtlVector(CUtlVector const& vec) { _Utl_Vector_assert(0); } @@ -113,153 +118,130 @@ protected: void ShiftElementsRight(int elem, int num = 1); void ShiftElementsLeft(int elem, int num = 1); -public: + public: CAllocator m_Memory; int m_Size; // For easier access to the elements through the debugger // it's in release builds so this can be used in libraries correctly - T *m_pElements; + T* m_pElements; - inline void ResetDbgInfo() - { - m_pElements = Base(); - } + inline void ResetDbgInfo() { m_pElements = Base(); } }; - //----------------------------------------------------------------------------- // constructor, destructor //----------------------------------------------------------------------------- -template< typename T, class A > -inline CUtlVector::CUtlVector(int growSize, int initSize) : - m_Memory(growSize, initSize), m_Size(0) -{ +template +inline CUtlVector::CUtlVector(int growSize, int initSize) + : m_Memory(growSize, initSize), m_Size(0) { ResetDbgInfo(); } -template< typename T, class A > -inline CUtlVector::CUtlVector(T* pMemory, int allocationCount, int numElements) : - m_Memory(pMemory, allocationCount), m_Size(numElements) -{ +template +inline CUtlVector::CUtlVector(T* pMemory, int allocationCount, + int numElements) + : m_Memory(pMemory, allocationCount), m_Size(numElements) { ResetDbgInfo(); } -template< typename T, class A > -inline CUtlVector::~CUtlVector() -{ +template +inline CUtlVector::~CUtlVector() { Purge(); } -template< typename T, class A > -inline CUtlVector& CUtlVector::operator=(const CUtlVector &other) -{ +template +inline CUtlVector& CUtlVector::operator=( + const CUtlVector& other) { int nCount = other.Count(); SetSize(nCount); - for(int i = 0; i < nCount; i++) { + for (int i = 0; i < nCount; i++) { (*this)[i] = other[i]; } return *this; } - //----------------------------------------------------------------------------- // element access //----------------------------------------------------------------------------- -template< typename T, class A > -inline T& CUtlVector::operator[](int i) -{ +template +inline T& CUtlVector::operator[](int i) { _Utl_Vector_assert(i < m_Size); return m_Memory[i]; } -template< typename T, class A > -inline const T& CUtlVector::operator[](int i) const -{ +template +inline const T& CUtlVector::operator[](int i) const { _Utl_Vector_assert(i < m_Size); return m_Memory[i]; } -template< typename T, class A > -inline T& CUtlVector::Element(int i) -{ +template +inline T& CUtlVector::Element(int i) { _Utl_Vector_assert(i < m_Size); return m_Memory[i]; } -template< typename T, class A > -inline const T& CUtlVector::Element(int i) const -{ +template +inline const T& CUtlVector::Element(int i) const { _Utl_Vector_assert(i < m_Size); return m_Memory[i]; } -template< typename T, class A > -inline T& CUtlVector::Head() -{ +template +inline T& CUtlVector::Head() { _Utl_Vector_assert(m_Size > 0); return m_Memory[0]; } -template< typename T, class A > -inline const T& CUtlVector::Head() const -{ +template +inline const T& CUtlVector::Head() const { _Utl_Vector_assert(m_Size > 0); return m_Memory[0]; } -template< typename T, class A > -inline T& CUtlVector::Tail() -{ +template +inline T& CUtlVector::Tail() { _Utl_Vector_assert(m_Size > 0); return m_Memory[m_Size - 1]; } -template< typename T, class A > -inline const T& CUtlVector::Tail() const -{ +template +inline const T& CUtlVector::Tail() const { _Utl_Vector_assert(m_Size > 0); return m_Memory[m_Size - 1]; } - //----------------------------------------------------------------------------- // Count //----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::Count() const -{ +template +inline int CUtlVector::Count() const { return m_Size; } - //----------------------------------------------------------------------------- // Is element index valid? //----------------------------------------------------------------------------- -template< typename T, class A > -inline bool CUtlVector::IsValidIndex(int i) const -{ +template +inline bool CUtlVector::IsValidIndex(int i) const { return (i >= 0) && (i < m_Size); } - //----------------------------------------------------------------------------- // Returns in invalid index //----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::InvalidIndex() -{ +template +inline int CUtlVector::InvalidIndex() { return -1; } - //----------------------------------------------------------------------------- // Grows the vector //----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::GrowVector(int num) -{ - if(m_Size + num > m_Memory.NumAllocated()) { +template +void CUtlVector::GrowVector(int num) { + if (m_Size + num > m_Memory.NumAllocated()) { m_Memory.Grow(m_Size + num - m_Memory.NumAllocated()); } @@ -267,29 +249,27 @@ void CUtlVector::GrowVector(int num) ResetDbgInfo(); } - //----------------------------------------------------------------------------- // Sorts the vector //----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::Sort(int(__cdecl *pfnCompare)(const T *, const T *)) -{ - typedef int(__cdecl *QSortCompareFunc_t)(const void *, const void *); - if(Count() <= 1) - return; +template +void CUtlVector::Sort(int(__cdecl* pfnCompare)(const T*, const T*)) { + typedef int(__cdecl * QSortCompareFunc_t)(const void*, const void*); + if (Count() <= 1) return; - if(Base()) { + if (Base()) { qsort(Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare)); } else { _Utl_Vector_assert(0); // this path is untested - // if you want to sort vectors that use a non-sequential memory allocator, - // you'll probably want to patch in a quicksort algorithm here - // I just threw in this bubble sort to have something just in case... + // if you want to sort vectors that use a non-sequential memory + // allocator, you'll probably want to patch in a quicksort algorithm + // here I just threw in this bubble sort to have something just in + // case... - for(int i = m_Size - 1; i >= 0; --i) { - for(int j = 1; j <= i; ++j) { - if(pfnCompare(&Element(j - 1), &Element(j)) < 0) { + for (int i = m_Size - 1; i >= 0; --i) { + for (int j = 1; j <= i; ++j) { + if (pfnCompare(&Element(j - 1), &Element(j)) < 0) { V_swap(Element(j - 1), Element(j)); } } @@ -300,45 +280,39 @@ void CUtlVector::Sort(int(__cdecl *pfnCompare)(const T *, const T *)) //----------------------------------------------------------------------------- // Makes sure we have enough memory allocated to store a requested # of elements //----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::EnsureCapacity(int num) -{ +template +void CUtlVector::EnsureCapacity(int num) { MEM_ALLOC_CREDIT_CLASS(); m_Memory.EnsureCapacity(num); ResetDbgInfo(); } - //----------------------------------------------------------------------------- // Makes sure we have at least this many elements //----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::EnsureCount(int num) -{ - if(Count() < num) { +template +void CUtlVector::EnsureCount(int num) { + if (Count() < num) { AddMultipleToTail(num - Count()); } } - //----------------------------------------------------------------------------- // Shifts elements //----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::ShiftElementsRight(int elem, int num) -{ +template +void CUtlVector::ShiftElementsRight(int elem, int num) { _Utl_Vector_assert(IsValidIndex(elem) || (m_Size == 0) || (num == 0)); int numToMove = m_Size - elem - num; - if((numToMove > 0) && (num > 0)) + if ((numToMove > 0) && (num > 0)) memmove(&Element(elem + num), &Element(elem), numToMove * sizeof(T)); } -template< typename T, class A > -void CUtlVector::ShiftElementsLeft(int elem, int num) -{ +template +void CUtlVector::ShiftElementsLeft(int elem, int num) { _Utl_Vector_assert(IsValidIndex(elem) || (m_Size == 0) || (num == 0)); int numToMove = m_Size - elem - num; - if((numToMove > 0) && (num > 0)) { + if ((numToMove > 0) && (num > 0)) { memmove(&Element(elem), &Element(elem + num), numToMove * sizeof(T)); #ifdef _DEBUG @@ -347,31 +321,26 @@ void CUtlVector::ShiftElementsLeft(int elem, int num) } } - //----------------------------------------------------------------------------- // Adds an element, uses default constructor //----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::AddToHead() -{ +template +inline int CUtlVector::AddToHead() { return InsertBefore(0); } -template< typename T, class A > -inline int CUtlVector::AddToTail() -{ +template +inline int CUtlVector::AddToTail() { return InsertBefore(m_Size); } -template< typename T, class A > -inline int CUtlVector::InsertAfter(int elem) -{ +template +inline int CUtlVector::InsertAfter(int elem) { return InsertBefore(elem + 1); } -template< typename T, class A > -int CUtlVector::InsertBefore(int elem) -{ +template +int CUtlVector::InsertBefore(int elem) { // Can insert at the end _Utl_Vector_assert((elem == Count()) || IsValidIndex(elem)); @@ -381,39 +350,38 @@ int CUtlVector::InsertBefore(int elem) return elem; } - //----------------------------------------------------------------------------- // Adds an element, uses copy constructor //----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::AddToHead(const T& src) -{ +template +inline int CUtlVector::AddToHead(const T& src) { // Can't insert something that's in the list... reallocation may hose us - _Utl_Vector_assert((Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()))); + _Utl_Vector_assert((Base() == NULL) || (&src < Base()) || + (&src >= (Base() + Count()))); return InsertBefore(0, src); } -template< typename T, class A > -inline int CUtlVector::AddToTail(const T& src) -{ +template +inline int CUtlVector::AddToTail(const T& src) { // Can't insert something that's in the list... reallocation may hose us - _Utl_Vector_assert((Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()))); + _Utl_Vector_assert((Base() == NULL) || (&src < Base()) || + (&src >= (Base() + Count()))); return InsertBefore(m_Size, src); } -template< typename T, class A > -inline int CUtlVector::InsertAfter(int elem, const T& src) -{ +template +inline int CUtlVector::InsertAfter(int elem, const T& src) { // Can't insert something that's in the list... reallocation may hose us - _Utl_Vector_assert((Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()))); + _Utl_Vector_assert((Base() == NULL) || (&src < Base()) || + (&src >= (Base() + Count()))); return InsertBefore(elem + 1, src); } -template< typename T, class A > -int CUtlVector::InsertBefore(int elem, const T& src) -{ +template +int CUtlVector::InsertBefore(int elem, const T& src) { // Can't insert something that's in the list... reallocation may hose us - _Utl_Vector_assert((Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()))); + _Utl_Vector_assert((Base() == NULL) || (&src < Base()) || + (&src >= (Base() + Count()))); // Can insert at the end _Utl_Vector_assert((elem == Count()) || IsValidIndex(elem)); @@ -424,74 +392,69 @@ int CUtlVector::InsertBefore(int elem, const T& src) return elem; } - //----------------------------------------------------------------------------- // Adds multiple elements, uses default constructor //----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::AddMultipleToHead(int num) -{ +template +inline int CUtlVector::AddMultipleToHead(int num) { return InsertMultipleBefore(0, num); } -template< typename T, class A > -inline int CUtlVector::AddMultipleToTail(int num) -{ +template +inline int CUtlVector::AddMultipleToTail(int num) { return InsertMultipleBefore(m_Size, num); } -template< typename T, class A > -inline int CUtlVector::AddMultipleToTail(int num, const T *pToCopy) -{ +template +inline int CUtlVector::AddMultipleToTail(int num, const T* pToCopy) { // Can't insert something that's in the list... reallocation may hose us - _Utl_Vector_assert((Base() == NULL) || !pToCopy || (pToCopy + num <= Base()) || (pToCopy >= (Base() + Count()))); + _Utl_Vector_assert((Base() == NULL) || !pToCopy || + (pToCopy + num <= Base()) || + (pToCopy >= (Base() + Count()))); return InsertMultipleBefore(m_Size, num, pToCopy); } -template< typename T, class A > -int CUtlVector::InsertMultipleAfter(int elem, int num) -{ +template +int CUtlVector::InsertMultipleAfter(int elem, int num) { return InsertMultipleBefore(elem + 1, num); } - -template< typename T, class A > -void CUtlVector::SetCount(int count) -{ +template +void CUtlVector::SetCount(int count) { RemoveAll(); AddMultipleToTail(count); } -template< typename T, class A > -inline void CUtlVector::SetSize(int size) -{ +template +inline void CUtlVector::SetSize(int size) { SetCount(size); } -template< typename T, class A > -void CUtlVector::SetCountNonDestructively(int count) -{ +template +void CUtlVector::SetCountNonDestructively(int count) { int delta = count - m_Size; - if(delta > 0) AddMultipleToTail(delta); - else if(delta < 0) RemoveMultipleFromTail(-delta); + if (delta > 0) + AddMultipleToTail(delta); + else if (delta < 0) + RemoveMultipleFromTail(-delta); } -template< typename T, class A > -void CUtlVector::CopyArray(const T *pArray, int size) -{ +template +void CUtlVector::CopyArray(const T* pArray, int size) { // Can't insert something that's in the list... reallocation may hose us - _Utl_Vector_assert((Base() == NULL) || !pArray || (Base() >= (pArray + size)) || (pArray >= (Base() + Count()))); + _Utl_Vector_assert((Base() == NULL) || !pArray || + (Base() >= (pArray + size)) || + (pArray >= (Base() + Count()))); SetSize(size); - for(int i = 0; i < size; i++) { + for (int i = 0; i < size; i++) { (*this)[i] = pArray[i]; } } -template< typename T, class A > -void CUtlVector::Swap(CUtlVector< T, A > &vec) -{ +template +void CUtlVector::Swap(CUtlVector& vec) { m_Memory.Swap(vec.m_Memory); V_swap(m_Size, vec.m_Size); #ifndef _X360 @@ -499,9 +462,8 @@ void CUtlVector::Swap(CUtlVector< T, A > &vec) #endif } -template< typename T, class A > -int CUtlVector::AddVectorToTail(CUtlVector const &src) -{ +template +int CUtlVector::AddVectorToTail(CUtlVector const& src) { _Utl_Vector_assert(&src != this); int base = Count(); @@ -510,19 +472,17 @@ int CUtlVector::AddVectorToTail(CUtlVector const &src) int nSrcCount = src.Count(); EnsureCapacity(base + nSrcCount); - // Copy the elements. + // Copy the elements. m_Size += nSrcCount; - for(int i = 0; i < nSrcCount; i++) { + for (int i = 0; i < nSrcCount; i++) { CopyConstruct(&Element(base + i), src[i]); } return base; } -template< typename T, class A > -inline int CUtlVector::InsertMultipleBefore(int elem, int num) -{ - if(num == 0) - return elem; +template +inline int CUtlVector::InsertMultipleBefore(int elem, int num) { + if (num == 0) return elem; // Can insert at the end _Utl_Vector_assert((elem == Count()) || IsValidIndex(elem)); @@ -531,18 +491,17 @@ inline int CUtlVector::InsertMultipleBefore(int elem, int num) ShiftElementsRight(elem, num); // Invoke default constructors - for(int i = 0; i < num; ++i) { + for (int i = 0; i < num; ++i) { Construct(&Element(elem + i)); } return elem; } -template< typename T, class A > -inline int CUtlVector::InsertMultipleBefore(int elem, int num, const T *pToInsert) -{ - if(num == 0) - return elem; +template +inline int CUtlVector::InsertMultipleBefore(int elem, int num, + const T* pToInsert) { + if (num == 0) return elem; // Can insert at the end _Utl_Vector_assert((elem == Count()) || IsValidIndex(elem)); @@ -551,12 +510,12 @@ inline int CUtlVector::InsertMultipleBefore(int elem, int num, const T *pT ShiftElementsRight(elem, num); // Invoke default constructors - if(!pToInsert) { - for(int i = 0; i < num; ++i) { + if (!pToInsert) { + for (int i = 0; i < num; ++i) { Construct(&Element(elem + i)); } } else { - for(int i = 0; i < num; i++) { + for (int i = 0; i < num; i++) { CopyConstruct(&Element(elem + i), pToInsert[i]); } } @@ -564,204 +523,215 @@ inline int CUtlVector::InsertMultipleBefore(int elem, int num, const T *pT return elem; } - //----------------------------------------------------------------------------- // Finds an element (element needs operator== defined) //----------------------------------------------------------------------------- -template< typename T, class A > -int CUtlVector::GetOffset(const T& src) const -{ - for(int i = 0; i < Count(); ++i) { - if(Element(i) == src) - return i; +template +int CUtlVector::GetOffset(const T& src) const { + for (int i = 0; i < Count(); ++i) { + if (Element(i) == src) return i; } return -1; } -template< typename T, class A > -void CUtlVector::FillWithValue(const T& src) -{ - for(int i = 0; i < Count(); i++) { +template +void CUtlVector::FillWithValue(const T& src) { + for (int i = 0; i < Count(); i++) { Element(i) = src; } } -template< typename T, class A > -bool CUtlVector::HasElement(const T& src) const -{ +template +bool CUtlVector::HasElement(const T& src) const { return (GetOffset(src) >= 0); } - //----------------------------------------------------------------------------- // Element removal //----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::FastRemove(int elem) -{ +template +void CUtlVector::FastRemove(int elem) { _Utl_Vector_assert(IsValidIndex(elem)); Destruct(&Element(elem)); - if(m_Size > 0) { - if(elem != m_Size - 1) + if (m_Size > 0) { + if (elem != m_Size - 1) memcpy(&Element(elem), &Element(m_Size - 1), sizeof(T)); --m_Size; } } -template< typename T, class A > -void CUtlVector::Remove(int elem) -{ +template +void CUtlVector::Remove(int elem) { Destruct(&Element(elem)); ShiftElementsLeft(elem); --m_Size; } -template< typename T, class A > -bool CUtlVector::FindAndRemove(const T& src) -{ +template +bool CUtlVector::FindAndRemove(const T& src) { int elem = GetOffset(src); - if(elem != -1) { + if (elem != -1) { Remove(elem); return true; } return false; } -template< typename T, class A > -bool CUtlVector::FindAndFastRemove(const T& src) -{ +template +bool CUtlVector::FindAndFastRemove(const T& src) { int elem = GetOffset(src); - if(elem != -1) { + if (elem != -1) { FastRemove(elem); return true; } return false; } -template< typename T, class A > -void CUtlVector::RemoveMultiple(int elem, int num) -{ +template +void CUtlVector::RemoveMultiple(int elem, int num) { _Utl_Vector_assert(elem >= 0); _Utl_Vector_assert(elem + num <= Count()); - for(int i = elem + num; --i >= elem; ) - Destruct(&Element(i)); + for (int i = elem + num; --i >= elem;) Destruct(&Element(i)); ShiftElementsLeft(elem, num); m_Size -= num; } -template< typename T, class A > -void CUtlVector::RemoveMultipleFromHead(int num) -{ +template +void CUtlVector::RemoveMultipleFromHead(int num) { _Utl_Vector_assert(num <= Count()); - for(int i = num; --i >= 0; ) - Destruct(&Element(i)); + for (int i = num; --i >= 0;) Destruct(&Element(i)); ShiftElementsLeft(0, num); m_Size -= num; } -template< typename T, class A > -void CUtlVector::RemoveMultipleFromTail(int num) -{ +template +void CUtlVector::RemoveMultipleFromTail(int num) { _Utl_Vector_assert(num <= Count()); - for(int i = m_Size - num; i < m_Size; i++) - Destruct(&Element(i)); + for (int i = m_Size - num; i < m_Size; i++) Destruct(&Element(i)); m_Size -= num; } -template< typename T, class A > -void CUtlVector::RemoveAll() -{ - for(int i = m_Size; --i >= 0; ) { +template +void CUtlVector::RemoveAll() { + for (int i = m_Size; --i >= 0;) { Destruct(&Element(i)); } m_Size = 0; } - //----------------------------------------------------------------------------- // Memory deallocation //----------------------------------------------------------------------------- -template< typename T, class A > -inline void CUtlVector::Purge() -{ +template +inline void CUtlVector::Purge() { RemoveAll(); m_Memory.Purge(); ResetDbgInfo(); } - -template< typename T, class A > -inline void CUtlVector::PurgeAndDeleteElements() -{ - for(int i = 0; i < m_Size; i++) { +template +inline void CUtlVector::PurgeAndDeleteElements() { + for (int i = 0; i < m_Size; i++) { delete Element(i); } Purge(); } -template< typename T, class A > -inline void CUtlVector::Compact() -{ +template +inline void CUtlVector::Compact() { m_Memory.Purge(m_Size); } -template< typename T, class A > -inline int CUtlVector::NumAllocated() const -{ +template +inline int CUtlVector::NumAllocated() const { return m_Memory.NumAllocated(); } - //----------------------------------------------------------------------------- // Data and memory validation //----------------------------------------------------------------------------- #ifdef DBGFLAG_VALIDATE -template< typename T, class A > -void CUtlVector::Validate(CValidator &validator, char *pchName) -{ +template +void CUtlVector::Validate(CValidator& validator, char* pchName) { validator.Push(typeid(*this).name(), this, pchName); m_Memory.Validate(validator, "m_Memory"); validator.Pop(); } -#endif // DBGFLAG_VALIDATE +#endif // DBGFLAG_VALIDATE -// A vector class for storing pointers, so that the elements pointed to by the pointers are deleted -// on exit. -template class CUtlVectorAutoPurge : public CUtlVector< T, CUtlMemory< T, int> > -{ -public: - ~CUtlVectorAutoPurge(void) - { - this->PurgeAndDeleteElements(); - } +// A vector class for storing pointers, so that the elements pointed to by the +// pointers are deleted on exit. +template +class CUtlVectorAutoPurge : public CUtlVector > { + public: + ~CUtlVectorAutoPurge(void) { this->PurgeAndDeleteElements(); } }; -// easy string list class with dynamically allocated strings. For use with V_SplitString, etc. -// Frees the dynamic strings in destructor. -class CUtlStringList : public CUtlVectorAutoPurge< char *> -{ -public: - void CopyAndAddToTail(char const *pString) // clone the string and add to the end +// easy string list class with dynamically allocated strings. For use with +// V_SplitString, etc. Frees the dynamic strings in destructor. +class CUtlStringList : public CUtlVectorAutoPurge { + public: + void CopyAndAddToTail( + char const* pString) // clone the string and add to the end { - char *pNewStr = new char[1 + strlen(pString)]; + char* pNewStr = new char[1 + strlen(pString)]; strcpy_s(pNewStr, 1 + strlen(pString), pString); AddToTail(pNewStr); } - static int __cdecl SortFunc(char * const * sz1, char * const * sz2) - { + static int __cdecl SortFunc(char* const* sz1, char* const* sz2) { return strcmp(*sz1, *sz2); } +}; +template +class CUtlVectorFixed : public CUtlVector > { + typedef CUtlVector > BaseClass; -}; \ No newline at end of file + public: + // constructor, destructor + CUtlVectorFixed(int growSize = 0, int initSize = 0) + : BaseClass(growSize, initSize) {} + CUtlVectorFixed(T* pMemory, int numElements) + : BaseClass(pMemory, numElements) {} +}; + +template +class CUtlMemoryFixedGrowable : public CUtlMemory { + typedef CUtlMemory BaseClass; + + public: + CUtlMemoryFixedGrowable(int nGrowSize = 0, int nInitSize = SIZE) + : BaseClass(m_pFixedMemory, SIZE) { + Assert(nInitSize == 0 || nInitSize == SIZE); + } + + void EnsureCapacity(int num) { + if (CUtlMemory::m_nAllocationCount >= num) return; + + BaseClass::EnsureCapacity(num); + } + + private: + T m_pFixedMemory[SIZE]; +}; + +template +class CUtlVectorFixedGrowable + : public CUtlVector > { + typedef CUtlVector > BaseClass; + + public: + // constructor, destructor + CUtlVectorFixedGrowable(int growSize = 0) : BaseClass(growSize, MAX_SIZE) {} +}; diff --git a/csgo2/sdk/tier1/cbyteswap.cpp b/csgo2/sdk/tier1/cbyteswap.cpp new file mode 100644 index 0000000..4b3181f --- /dev/null +++ b/csgo2/sdk/tier1/cbyteswap.cpp @@ -0,0 +1,8 @@ +//========= Copyright � 1996-2006, Valve LLC, All rights reserved. ============ +// +// Purpose: Low level byte swapping routines. +// +// $NoKeywords: $ +//============================================================================= + +#include "cbyteswap.h" diff --git a/csgo2/sdk/tier1/cbyteswap.h b/csgo2/sdk/tier1/cbyteswap.h new file mode 100644 index 0000000..60a7f78 --- /dev/null +++ b/csgo2/sdk/tier1/cbyteswap.h @@ -0,0 +1,492 @@ +//========= Copyright ?1996-2006, Valve LLC, All rights reserved. ============ +// +// Purpose: Low level byte swapping routines. +// +// $NoKeywords: $ +//============================================================================= +#ifndef BYTESWAP_H +#define BYTESWAP_H +#if defined(_WIN32) +#pragma once +#endif + +#include "../sdk.h" + +typedef enum _fieldtypes { + FIELD_VOID = 0, // No type or value + FIELD_FLOAT, // Any floating point value + FIELD_STRING, // A string ID (return from ALLOC_STRING) + FIELD_VECTOR, // Any vector, QAngle, or AngularImpulse + FIELD_QUATERNION, // A quaternion + FIELD_INTEGER, // Any integer or enum + FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint + // for compression + FIELD_SHORT, // 2 byte integer + FIELD_CHARACTER, // a byte + FIELD_COLOR32, // 8-bit per channel r,g,b,a (32bit color) + FIELD_EMBEDDED, // an embedded object with a datadesc, recursively traverse + // and embedded class/structure based on an additional + // typedescription + FIELD_CUSTOM, // special type that contains function pointers to it's + // read/write/parse functions + + FIELD_CLASSPTR, // CBaseEntity * + FIELD_EHANDLE, // Entity handle + + FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across + // level transitions automagically) + FIELD_TIME, // a floating point time (these are fixed up automatically + // too!) + FIELD_TICK, // an integer tick count( fixed up similarly to time) + FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache) + + FIELD_INPUT, // a list of inputed data fields (all derived from + // CMultiInputVar) + FIELD_FUNCTION, // A class function pointer (Think, Use, etc) + + FIELD_VMATRIX, // a vmatrix (output coords are NOT worldspace) + + // NOTE: Use float arrays for local transformations that don't need to be + // fixed up. + FIELD_VMATRIX_WORLDSPACE, // A VMatrix that maps some local space to world + // space (translation is fixed up on level + // transitions) + FIELD_MATRIX3X4_WORLDSPACE, // matrix3x4_t that maps some local space to + // world space (translation is fixed up on + // level transitions) + + FIELD_INTERVAL, // a start and range floating point interval ( + // e.g., 3.2->3.6 == 3.2 and 0.4 ) + FIELD_UNUSED, + + FIELD_VECTOR2D, // 2 floats + FIELD_INTEGER64, // 64bit integer + + FIELD_VECTOR4D, // 4 floats + + FIELD_RESOURCE, + + FIELD_TYPEUNKNOWN, + + FIELD_CSTRING, + FIELD_HSCRIPT, + FIELD_VARIANT, + FIELD_UINT64, + FIELD_FLOAT64, + FIELD_POSITIVEINTEGER_OR_NULL, + FIELD_HSCRIPT_NEW_INSTANCE, + FIELD_UINT, + FIELD_UTLSTRINGTOKEN, + FIELD_QANGLE, + FIELD_NETWORK_ORIGIN_CELL_QUANTIZED_VECTOR, + FIELD_HMATERIAL, + FIELD_HMODEL, + FIELD_NETWORK_QUANTIZED_VECTOR, + FIELD_NETWORK_QUANTIZED_FLOAT, + FIELD_DIRECTION_VECTOR_WORLDSPACE, + FIELD_QANGLE_WORLDSPACE, + FIELD_QUATERNION_WORLDSPACE, + FIELD_HSCRIPT_LIGHTBINDING, + FIELD_V8_VALUE, + FIELD_V8_OBJECT, + FIELD_V8_ARRAY, + FIELD_V8_CALLBACK_INFO, + FIELD_UTLSTRING, + + FIELD_NETWORK_ORIGIN_CELL_QUANTIZED_POSITION_VECTOR, + FIELD_HRENDERTEXTURE, + + FIELD_HPARTICLESYSTEMDEFINITION, + FIELD_UINT8, + FIELD_UINT16, + FIELD_CTRANSFORM, + FIELD_CTRANSFORM_WORLDSPACE, + FIELD_HPOSTPROCESSING, + FIELD_MATRIX3X4, + FIELD_SHIM, + FIELD_CMOTIONTRANSFORM, + FIELD_CMOTIONTRANSFORM_WORLDSPACE, + FIELD_ATTACHMENT_HANDLE, + FIELD_AMMO_INDEX, + FIELD_CONDITION_ID, + FIELD_AI_SCHEDULE_BITS, + FIELD_MODIFIER_HANDLE, + FIELD_ROTATION_VECTOR, + FIELD_ROTATION_VECTOR_WORLDSPACE, + FIELD_HVDATA, + FIELD_SCALE32, + FIELD_STRING_AND_TOKEN, + FIELD_ENGINE_TIME, + FIELD_ENGINE_TICK, + FIELD_WORLD_GROUP_ID, + + FIELD_TYPECOUNT +} fieldtype_t; +struct inputdata_t; + +class ISaveRestoreOps; +typedef void(__fastcall *inputfunc_t)(inputdata_t &data); + +enum { + PC_NON_NETWORKED_ONLY = 0, + PC_NETWORKED_ONLY, + + PC_COPYTYPE_COUNT, + PC_EVERYTHING = PC_COPYTYPE_COUNT, +}; + +enum { + TD_OFFSET_NORMAL = 0, + TD_OFFSET_PACKED = 1, + + // Must be last + TD_OFFSET_COUNT, +}; +struct datarun_t; +struct typedescription_t; +struct datacopyruns_t +{ +public: + CUtlVector< datarun_t > m_vecRuns; +}; + +struct flattenedoffsets_t +{ + CUtlVector< typedescription_t > m_Flattened; + int m_nPackedSize; // Contiguous memory to pack all of these together for TD_OFFSET_PACKED + int m_nPackedStartOffset; +}; + +struct datamapinfo_t +{ + // Flattened list, with FIELD_EMBEDDED, FTYPEDESC_PRIVATE, + // and FTYPEDESC_OVERRIDE (overridden) fields removed + flattenedoffsets_t m_Flat; + datacopyruns_t m_CopyRuns; +}; + +struct optimized_datamap_t +{ + // Optimized info for PC_NON_NETWORKED and PC_NETWORKED data + datamapinfo_t m_Info[PC_COPYTYPE_COUNT]; +}; + + +struct datamap_t +{ + typedescription_t* dataDesc; + int dataNumFields; + char const* dataClassName; + datamap_t* baseMap; + + int m_nPackedSize; + optimized_datamap_t* m_pOptimizedDataMap; + +#if defined( _DEBUG ) + bool bValidityChecked; +#endif // _DEBUG +}; + +struct typedescription_t { + fieldtype_t fieldType; + const char *fieldName; + int fieldOffset; // Local offset value + unsigned short fieldSize; + short flags; + // the name of the variable in the map/fgd data, or the name of the action + const char *externalName; + // pointer to the function set for save/restoring of custom data types + ISaveRestoreOps *pSaveRestoreOps; + // for associating function with string names + inputfunc_t inputFunc; + // For embedding additional datatables inside this one + datamap_t *td; + + // Stores the actual member variable size in bytes + int fieldSizeInBytes; + + // FTYPEDESC_OVERRIDE point to first baseclass instance if chains_validated + // has occurred + struct typedescription_t *override_field; + + // Used to track exclusion of baseclass fields + int override_count; + + // Tolerance for field errors for float fields + float fieldTolerance; + + // For raw fields (including children of embedded stuff) this is the + // flattened offset + int flatOffset[TD_OFFSET_COUNT]; + unsigned short flatGroup; +}; +struct datarun_t +{ + datarun_t() : m_nStartFlatField(0), m_nEndFlatField(0), m_nLength(0) + { + for (int i = 0; i < TD_OFFSET_COUNT; ++i) + { + m_nStartOffset[i] = 0; + } + } + + // Indices of start/end fields in the flattened typedescription_t list + int m_nStartFlatField; + int m_nEndFlatField; + + // Offsets for run in the packed/unpacked data (I think the run starts need to be properly aligned) + int m_nStartOffset[TD_OFFSET_COUNT]; + + int m_nLength; +}; + +class CByteswap { + public: + CByteswap() { + // Default behavior sets the target endian to match the machine native + // endian (no swap). + SetTargetBigEndian(IsMachineBigEndian()); + } + + //----------------------------------------------------------------------------- + // Write a single field. + //----------------------------------------------------------------------------- + void SwapFieldToTargetEndian(void *pOutputBuffer, void *pData, + typedescription_t *pField); + + //----------------------------------------------------------------------------- + // Write a block of fields. Works a bit like the saverestore code. + //----------------------------------------------------------------------------- + void SwapFieldsToTargetEndian(void *pOutputBuffer, void *pBaseData, + datamap_t *pDataMap); + + // Swaps fields for the templated type to the output buffer. + template + inline void SwapFieldsToTargetEndian(T *pOutputBuffer, void *pBaseData, + unsigned int objectCount = 1) { + for (unsigned int i = 0; i < objectCount; ++i, ++pOutputBuffer) { + SwapFieldsToTargetEndian((void *)pOutputBuffer, pBaseData, + &T::m_DataMap); + pBaseData = (byte *)pBaseData + sizeof(T); + } + } + + // Swaps fields for the templated type in place. + template + inline void SwapFieldsToTargetEndian(T *pOutputBuffer, + unsigned int objectCount = 1) { + SwapFieldsToTargetEndian(pOutputBuffer, (void *)pOutputBuffer, + objectCount); + } + + //----------------------------------------------------------------------------- + // True if the current machine is detected as big endian. + // (Endienness is effectively detected at compile time when optimizations + // are enabled) + //----------------------------------------------------------------------------- + static bool IsMachineBigEndian() { + short nIsBigEndian = 1; + + // if we are big endian, the first byte will be a 0, if little endian, + // it will be a one. + return (bool)(0 == *(char *)&nIsBigEndian); + } + + //----------------------------------------------------------------------------- + // Sets the target byte ordering we are swapping to or from. + // + // Braindead Endian Reference: + // x86 is LITTLE Endian + // PowerPC is BIG Endian + //----------------------------------------------------------------------------- + inline void SetTargetBigEndian(bool bigEndian) { + m_bBigEndian = bigEndian; + m_bSwapBytes = IsMachineBigEndian() != bigEndian; + } + + // Changes target endian + inline void FlipTargetEndian(void) { + m_bSwapBytes = !m_bSwapBytes; + m_bBigEndian = !m_bBigEndian; + } + + // Forces byte swapping state, regardless of endianess + inline void ActivateByteSwapping(bool bActivate) { + SetTargetBigEndian(IsMachineBigEndian() != bActivate); + } + + //----------------------------------------------------------------------------- + // Returns true if the target machine is the same as this one in endianness. + // + // Used to determine when a byteswap needs to take place. + //----------------------------------------------------------------------------- + inline bool IsSwappingBytes(void) // Are bytes being swapped? + { + return m_bSwapBytes; + } + + inline bool IsTargetBigEndian(void) // What is the current target endian? + { + return m_bBigEndian; + } + + //----------------------------------------------------------------------------- + // IsByteSwapped() + // + // When supplied with a chunk of input data and a constant or magic number + // (in native format) determines the endienness of the current machine in + // relation to the given input data. + // + // Returns: + // 1 if input is the same as nativeConstant. + // 0 if input is byteswapped relative to nativeConstant. + // -1 if input is not the same as nativeConstant and not byteswapped + // either. + // + // ( This is useful for detecting byteswapping in magic numbers in structure + // headers for example. ) + //----------------------------------------------------------------------------- + template + inline int SourceIsNativeEndian(T input, T nativeConstant) { + // If it's the same, it isn't byteswapped: + if (input == nativeConstant) return 1; + + int output; + LowLevelByteSwap(&output, &input); + if (output == nativeConstant) return 0; + + Assert(0); // if we get here, input is neither a swapped nor unswapped + // version of nativeConstant. + return -1; + } + + //----------------------------------------------------------------------------- + // Swaps an input buffer full of type T into the given output buffer. + // + // Swaps [count] items from the inputBuffer to the outputBuffer. + // If inputBuffer is omitted or NULL, then it is assumed to be the same as + // outputBuffer - effectively swapping the contents of the buffer in place. + //----------------------------------------------------------------------------- + template + inline void SwapBuffer(T *outputBuffer, T *inputBuffer = NULL, + int count = 1) { + Assert(count >= 0); + Assert(outputBuffer); + + // Fail gracefully in release: + if (count <= 0 || !outputBuffer) return; + + // Optimization for the case when we are swapping in place. + if (inputBuffer == NULL) { + inputBuffer = outputBuffer; + } + + // Swap everything in the buffer: + for (int i = 0; i < count; i++) { + LowLevelByteSwap(&outputBuffer[i], &inputBuffer[i]); + } + } + + //----------------------------------------------------------------------------- + // Swaps an input buffer full of type T into the given output buffer. + // + // Swaps [count] items from the inputBuffer to the outputBuffer. + // If inputBuffer is omitted or NULL, then it is assumed to be the same as + // outputBuffer - effectively swapping the contents of the buffer in place. + //----------------------------------------------------------------------------- + template + inline void SwapBufferToTargetEndian(T *outputBuffer, T *inputBuffer = NULL, + int count = 1) { + Assert(count >= 0); + Assert(outputBuffer); + + // Fail gracefully in release: + if (count <= 0 || !outputBuffer) return; + + // Optimization for the case when we are swapping in place. + if (inputBuffer == NULL) { + inputBuffer = outputBuffer; + } + + // Are we already the correct endienness? ( or are we swapping 1 byte + // items? ) + if (!m_bSwapBytes || (sizeof(T) == 1)) { + // If we were just going to swap in place then return. + if (!inputBuffer) return; + + // Otherwise copy the inputBuffer to the outputBuffer: + if (outputBuffer != inputBuffer) + memcpy(outputBuffer, inputBuffer, count * sizeof(T)); + return; + } + + // Swap everything in the buffer: + for (int i = 0; i < count; i++) { + LowLevelByteSwap(&outputBuffer[i], &inputBuffer[i]); + } + } + + private: + //----------------------------------------------------------------------------- + // The lowest level byte swapping workhorse of doom. output always contains + // the swapped version of input. ( Doesn't compare machine to target + // endianness ) + //----------------------------------------------------------------------------- + template + static void LowLevelByteSwap(T *output, T *input) { + T temp = *output; +#if defined(_X360) + // Intrinsics need the source type to be fixed-point + DWORD *word = (DWORD *)input; + switch (sizeof(T)) { + case 8: { + __storewordbytereverse(*(word + 1), 0, &temp); + __storewordbytereverse(*(word + 0), 4, &temp); + } break; + + case 4: + __storewordbytereverse(*word, 0, &temp); + break; + + case 2: + __storeshortbytereverse(*input, 0, &temp); + break; + + case 1: + Q_memcpy(&temp, input, 1); + break; + + default: + Assert("Invalid size in CByteswap::LowLevelByteSwap" && 0); + } +#else + for (size_t i = 0; i < sizeof(T); i++) { + ((unsigned char *)&temp)[i] = + ((unsigned char *)input)[sizeof(T) - (i + 1)]; + } +#endif + memcpy(output, &temp, sizeof(T)); + } + +#if defined(_X360) + // specialized for void * to get 360 XDK compile working despite changelist + // 281331 + //----------------------------------------------------------------------------- + // The lowest level byte swapping workhorse of doom. output always contains + // the swapped version of input. ( Doesn't compare machine to target + // endianness ) + //----------------------------------------------------------------------------- + template <> + static void LowLevelByteSwap(void **output, void **input) { + AssertMsgOnce(sizeof(void *) == sizeof(unsigned int), + "void *'s on this platform are not four bytes!"); + __storewordbytereverse(*reinterpret_cast(input), 0, + output); + } +#endif + + unsigned int m_bSwapBytes : 1; + unsigned int m_bBigEndian : 1; +}; + +#endif /* !BYTESWAP_H */ diff --git a/csgo2/sdk/tier1/utlblockmemory.h b/csgo2/sdk/tier1/utlblockmemory.h index cb00e7e..a73a6c8 100644 --- a/csgo2/sdk/tier1/utlblockmemory.h +++ b/csgo2/sdk/tier1/utlblockmemory.h @@ -1,12 +1,3 @@ -//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -// A growable memory class. -//===========================================================================// - #ifndef UTLBLOCKMEMORY_H #define UTLBLOCKMEMORY_H diff --git a/csgo2/sdk/tier1/utlbuffer.h b/csgo2/sdk/tier1/utlbuffer.h new file mode 100644 index 0000000..cf0fc69 --- /dev/null +++ b/csgo2/sdk/tier1/utlbuffer.h @@ -0,0 +1,1355 @@ +//====== Copyright ?1996-2005, Valve Corporation, All rights reserved. =======// +// +// Purpose: +// +// $NoKeywords: $ +// +// Serialization/unserialization buffer +//=============================================================================// + +#ifndef UTLBUFFER_H +#define UTLBUFFER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "../sdk.h" +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +struct characterset_t; + + +//----------------------------------------------------------------------------- +// Description of character conversions for string output +// Here's an example of how to use the macros to define a character conversion +// BEGIN_CHAR_CONVERSION( CStringConversion, '\\' ) +// { '\n', "n" }, +// { '\t', "t" } +// END_CHAR_CONVERSION( CStringConversion, '\\' ) +//----------------------------------------------------------------------------- +class CUtlCharConversion +{ +public: + struct ConversionArray_t + { + char m_nActualChar; + const char *m_pReplacementString; + }; + + CUtlCharConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray ); + char GetEscapeChar() const; + const char *GetDelimiter() const; + int GetDelimiterLength() const; + + const char *GetConversionString( char c ) const; + int GetConversionLength( char c ) const; + int MaxConversionLength() const; + + // Finds a conversion for the passed-in string, returns length + virtual char FindConversion( const char *pString, int *pLength ); + +protected: + struct ConversionInfo_t + { + int m_nLength; + const char *m_pReplacementString; + }; + + char m_nEscapeChar; + const char *m_pDelimiter; + int m_nDelimiterLength; + int m_nCount; + int m_nMaxConversionLength; + char m_pList[255]; + ConversionInfo_t m_pReplacements[255]; +}; + +#define BEGIN_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \ + static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = { + +#define END_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \ + }; \ + CUtlCharConversion _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name ); + +#define BEGIN_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \ + static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = { + +#define END_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \ + }; \ + _className _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name ); + +//----------------------------------------------------------------------------- +// Character conversions for C strings +//----------------------------------------------------------------------------- +CUtlCharConversion *GetCStringCharConversion(); + +//----------------------------------------------------------------------------- +// Character conversions for quoted strings, with no escape sequences +//----------------------------------------------------------------------------- +CUtlCharConversion *GetNoEscCharConversion(); + + +//----------------------------------------------------------------------------- +// Macro to set overflow functions easily +//----------------------------------------------------------------------------- +#define SetUtlBufferOverflowFuncs( _get, _put ) \ + SetOverflowFuncs( static_cast ( _get ), static_cast ( _put ) ) + + + +typedef unsigned short ushort; + +template < class A > +static const char *GetFmtStr( int nRadix = 10, bool bPrint = true ) { Assert( 0 ); return ""; } + +template <> inline const char *GetFmtStr< short > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hd"; } +template <> inline const char *GetFmtStr< ushort > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hu"; } +template <> inline const char *GetFmtStr< int > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%d"; } +template <> inline const char *GetFmtStr< unsigned int > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 || nRadix == 16 ); return nRadix == 16 ? "%x" : "%u"; } +template <> inline const char *GetFmtStr< int64_t > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%lld"; } +template <> inline const char *GetFmtStr< float > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%f"; } +template <> inline const char *GetFmtStr< double > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return bPrint ? "%.15lf" : "%lf"; } // force Printf to print DBL_DIG=15 digits of precision for doubles - defaults to FLT_DIG=6 + + +//----------------------------------------------------------------------------- +// Command parsing.. +//----------------------------------------------------------------------------- +class CUtlBuffer +{ +// Brian has on his todo list to revisit this as there are issues in some cases with CUtlVector using operator = instead of copy construtor in InsertMultiple, etc. +// The unsafe case is something like this: +// CUtlVector< CUtlBuffer > vecFoo; +// +// CUtlBuffer buf; +// buf.Put( xxx ); +// vecFoo.Insert( buf ); +// +// This will cause memory corruption when vecFoo is cleared +// +//private: +// // Disallow copying +// CUtlBuffer( const CUtlBuffer & );// { Assert( 0 ); } +// CUtlBuffer &operator=( const CUtlBuffer & );// { Assert( 0 ); return *this; } + +public: + enum SeekType_t + { + SEEK_HEAD = 0, + SEEK_CURRENT, + SEEK_TAIL + }; + + // flags + enum BufferFlags_t + { + TEXT_BUFFER = 0x1, // Describes how get + put work (as strings, or binary) + EXTERNAL_GROWABLE = 0x2, // This is used w/ external buffers and causes the utlbuf to switch to reallocatable memory if an overflow happens when Putting. + CONTAINS_CRLF = 0x4, // For text buffers only, does this contain \n or \n\r? + READ_ONLY = 0x8, // For external buffers; prevents null termination from happening. + AUTO_TABS_DISABLED = 0x10, // Used to disable/enable push/pop tabs + }; + + // Overflow functions when a get or put overflows + typedef bool (CUtlBuffer::*UtlBufferOverflowFunc_t)( int nSize ); + + // Constructors for growable + external buffers for serialization/unserialization + DLL_CLASS_IMPORT CUtlBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 ); + DLL_CLASS_IMPORT CUtlBuffer( const void* pBuffer, int size, int nFlags = 0 ); + // This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param. + CUtlBuffer( const void *pBuffer, int size, bool crap ); + + unsigned char GetFlags() const; + + // NOTE: This will assert if you attempt to recast it in a way that + // is not compatible. The only valid conversion is binary-> text w/CRLF + DLL_CLASS_IMPORT void SetBufferType( bool bIsText, bool bContainsCRLF ); + + // Makes sure we've got at least this much memory + DLL_CLASS_IMPORT void EnsureCapacity( int num ); + + // Access for direct read into buffer + void * AccessForDirectRead( int nBytes ); + + // Attaches the buffer to external memory.... + DLL_CLASS_IMPORT void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 ); + bool IsExternallyAllocated() const; + DLL_CLASS_IMPORT void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 ); + void *Detach(); + void* DetachMemory(); + + FORCEINLINE void ActivateByteSwappingIfBigEndian( void ) + { +#if defined( _X360 ) + ActivateByteSwapping( true ); +#endif + } + + + // Controls endian-ness of binary utlbufs - default matches the current platform + DLL_CLASS_IMPORT void ActivateByteSwapping( bool bActivate ); + DLL_CLASS_IMPORT void SetBigEndian( bool bigEndian ); + DLL_CLASS_IMPORT bool IsBigEndian( void ); + + // Resets the buffer; but doesn't free memory + void Clear(); + + // Clears out the buffer; frees memory + void Purge(); + + // Dump the buffer to stdout + void Spew( ); + + // Read stuff out. + // Binary mode: it'll just read the bits directly in, and characters will be + // read for strings until a null character is reached. + // Text mode: it'll parse the file, turning text #s into real numbers. + // GetString will read a string until a space is reached + char GetChar( ); + unsigned char GetUnsignedChar( ); + short GetShort( ); + unsigned short GetUnsignedShort( ); + int GetInt( ); + int64_t Getint64_t( ); + unsigned int GetIntHex( ); + unsigned int GetUnsignedInt( ); + float GetFloat( ); + double GetDouble( ); + void * GetPtr(); + DLL_CLASS_IMPORT void GetString( char* pString, int nMaxChars = 0 ); + DLL_CLASS_IMPORT void Get( void* pMem, int size ); + DLL_CLASS_IMPORT void GetLine( char* pLine, int nMaxChars = 0 ); + + // Used for getting objects that have a byteswap datadesc defined + template void GetObjects( T *dest, int count = 1 ); + + // This will get at least 1 byte and up to nSize bytes. + // It will return the number of bytes actually read. + DLL_CLASS_IMPORT int GetUpTo( void *pMem, int nSize ); + + // This version of GetString converts \" to \\ and " to \, etc. + // It also reads a " at the beginning and end of the string + DLL_CLASS_IMPORT void GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars = 0 ); + DLL_CLASS_IMPORT char GetDelimitedChar( CUtlCharConversion *pConv ); + + // This will return the # of characters of the string about to be read out + // NOTE: The count will *include* the terminating 0!! + // In binary mode, it's the number of characters until the next 0 + // In text mode, it's the number of characters until the next space. + DLL_CLASS_IMPORT int PeekStringLength(); + + // This version of PeekStringLength converts \" to \\ and " to \, etc. + // It also reads a " at the beginning and end of the string + // NOTE: The count will *include* the terminating 0!! + // In binary mode, it's the number of characters until the next 0 + // In text mode, it's the number of characters between "s (checking for \") + // Specifying false for bActualSize will return the pre-translated number of characters + // including the delimiters and the escape characters. So, \n counts as 2 characters when bActualSize == false + // and only 1 character when bActualSize == true + DLL_CLASS_IMPORT int PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize = true ); + + // Just like scanf, but doesn't work in binary mode + DLL_CLASS_IMPORT int Scanf( const char* pFmt, ... ); + DLL_CLASS_IMPORT int VaScanf( const char* pFmt, va_list list ); + + // Eats white space, advances Get index + DLL_CLASS_IMPORT void EatWhiteSpace(); + + // Eats C++ style comments + DLL_CLASS_IMPORT bool EatCPPComment(); + + // (For text buffers only) + // Parse a token from the buffer: + // Grab all text that lies between a starting delimiter + ending delimiter + // (skipping whitespace that leads + trails both delimiters). + // If successful, the get index is advanced and the function returns true, + // otherwise the index is not advanced and the function returns false. + DLL_CLASS_IMPORT bool ParseToken( const char *pStartingDelim, const char *pEndingDelim, char *pString, int nMaxLen ); + DLL_CLASS_IMPORT bool ParseToken( const char* pStartingDelim, const char* pEndingDelim, CBufferString &str ); + + // Advance the get index until after the particular string is found + // Do not eat whitespace before starting. Return false if it failed + // String test is case-insensitive. + DLL_CLASS_IMPORT bool GetToken( const char *pToken ); + + // Parses the next token, given a set of character breaks to stop at + // Returns the length of the token parsed in bytes (-1 if none parsed) + DLL_CLASS_IMPORT int ParseToken( const characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments = true ); + DLL_CLASS_IMPORT int ParseToken( const characterset_t* pBreaks, CBufferString &str, bool bParseComments = true ); + + // Write stuff in + // Binary mode: it'll just write the bits directly in, and strings will be + // written with a null terminating character + // Text mode: it'll convert the numbers to text versions + // PutString will not write a terminating character + void PutChar( char c ); + void PutUnsignedChar( unsigned char uc ); + void PutShort( short s ); + void PutUnsignedShort( unsigned short us ); + void PutInt( int i ); + void Putint64_t( int64_t i ); + void PutUnsignedInt( unsigned int u ); + void PutFloat( float f ); + void PutDouble( double d ); + void PutPtr( void * ); // Writes the pointer, not the pointed to + DLL_CLASS_IMPORT void PutString( const char* pString ); + DLL_CLASS_IMPORT void Put( const void* pMem, int size ); + + // Used for putting objects that have a byteswap datadesc defined + template void PutObjects( T *src, int count = 1 ); + + // This version of PutString converts \ to \\ and " to \", etc. + // It also places " at the beginning and end of the string + DLL_CLASS_IMPORT void PutDelimitedString( CUtlCharConversion *pConv, const char *pString ); + DLL_CLASS_IMPORT void PutDelimitedChar( CUtlCharConversion *pConv, char c ); + + // Just like printf, writes a terminating zero in binary mode + DLL_CLASS_IMPORT void Printf( const char* pFmt, ... ) FMTFUNCTION( 2, 3 ); + DLL_CLASS_IMPORT void VaPrintf( const char* pFmt, va_list list ); + + // What am I writing (put)/reading (get)? + void* PeekPut( int offset = 0 ); + const void* PeekGet( int offset = 0 ) const; + DLL_CLASS_IMPORT const void* PeekGet( int nMaxSize, int nOffset ); + + // Where am I writing (put)/reading (get)? + int TellPut( ) const; + int TellGet( ) const; + + // What's the most I've ever written? + int TellMaxPut( ) const; + + // How many bytes remain to be read? + // NOTE: This is not accurate for streaming text files; it overshoots + int GetBytesRemaining() const; + + // Change where I'm writing (put)/reading (get) + DLL_CLASS_IMPORT void SeekPut( SeekType_t type, int offset ); + DLL_CLASS_IMPORT void SeekGet( SeekType_t type, int offset ); + + // Buffer base + const void* Base() const; + void* Base(); + + // memory allocation size, does *not* reflect size written or read, + // use TellPut or TellGet for that + int Size() const; + + // Am I a text buffer? + bool IsText() const; + + // Can I grow if I'm externally allocated? + bool IsGrowable() const; + + // Am I valid? (overflow or underflow error), Once invalid it stays invalid + bool IsValid() const; + + // Do I contain carriage return/linefeeds? + bool ContainsCRLF() const; + + // Am I read-only + bool IsReadOnly() const; + + // Converts a buffer from a CRLF buffer to a CR buffer (and back) + // Returns false if no conversion was necessary (and outBuf is left untouched) + // If the conversion occurs, outBuf will be cleared. + DLL_CLASS_IMPORT bool ConvertCRLF( CUtlBuffer &outBuf ); + + // Push/pop pretty-printing tabs + void PushTab(); + void PopTab(); + + // Temporarily disables pretty print + void EnableTabs( bool bEnable ); + +protected: + // error flags + enum + { + PUT_OVERFLOW = 0x1, + GET_OVERFLOW = 0x2, + MAX_ERROR_FLAG = GET_OVERFLOW, + }; + + DLL_CLASS_IMPORT void SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc ); + + DLL_CLASS_IMPORT bool OnPutOverflow( int nSize ); + DLL_CLASS_IMPORT bool OnGetOverflow( int nSize ); + +protected: + // Checks if a get/put is ok + DLL_CLASS_IMPORT bool CheckPut( int size ); + DLL_CLASS_IMPORT bool CheckGet( int size ); + + DLL_CLASS_IMPORT void AddNullTermination( ); + + // Methods to help with pretty-printing + bool WasLastCharacterCR(); + void PutTabs(); + + // Help with delimited stuff + DLL_CLASS_IMPORT char GetDelimitedCharInternal( CUtlCharConversion *pConv ); + DLL_CLASS_IMPORT void PutDelimitedCharInternal( CUtlCharConversion *pConv, char c ); + + // Default overflow funcs + DLL_CLASS_IMPORT bool PutOverflow( int nSize ); + DLL_CLASS_IMPORT bool GetOverflow( int nSize ); + + // Does the next bytes of the buffer match a pattern? + DLL_CLASS_IMPORT bool PeekStringMatch( int nOffset, const char *pString, int nLen ); + + // Peek size of line to come, check memory bound + DLL_CLASS_IMPORT int PeekLineLength(); + + // How much whitespace should I skip? + DLL_CLASS_IMPORT int PeekWhiteSpace( int nOffset ); + + // Checks if a peek get is ok + DLL_CLASS_IMPORT bool CheckPeekGet( int nOffset, int nSize ); + + // Call this to peek arbitrarily long into memory. It doesn't fail unless + // it can't read *anything* new + DLL_CLASS_IMPORT bool CheckArbitraryPeekGet( int nOffset, int &nIncrement ); + + template void GetType( T& dest ); + template void GetTypeBin( T& dest ); + template bool GetTypeText( T &value, int nRadix = 10 ); + template void GetObject( T *src ); + + template void PutType( T src ); + template void PutTypeBin( T src ); + template void PutObject( T *src ); + + CUtlMemory m_Memory; + int m_Get; + int m_Put; + + unsigned char m_Error; + unsigned char m_Flags; + unsigned char m_Reserved; +#if defined( _X360 ) + unsigned char pad; +#endif + + int m_nTab; + int m_nMaxPut; + int m_nOffset; + + UtlBufferOverflowFunc_t m_GetOverflowFunc; + UtlBufferOverflowFunc_t m_PutOverflowFunc; + + CByteswap m_Byteswap; +}; + + +// Stream style output operators for CUtlBuffer +inline CUtlBuffer &operator<<( CUtlBuffer &b, char v ) +{ + b.PutChar( v ); + return b; +} + +inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned char v ) +{ + b.PutUnsignedChar( v ); + return b; +} + +inline CUtlBuffer &operator<<( CUtlBuffer &b, short v ) +{ + b.PutShort( v ); + return b; +} + +inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned short v ) +{ + b.PutUnsignedShort( v ); + return b; +} + +inline CUtlBuffer &operator<<( CUtlBuffer &b, int v ) +{ + b.PutInt( v ); + return b; +} + +inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned int v ) +{ + b.PutUnsignedInt( v ); + return b; +} + +inline CUtlBuffer &operator<<( CUtlBuffer &b, float v ) +{ + b.PutFloat( v ); + return b; +} + +inline CUtlBuffer &operator<<( CUtlBuffer &b, double v ) +{ + b.PutDouble( v ); + return b; +} + +inline CUtlBuffer &operator<<( CUtlBuffer &b, const char *pv ) +{ + b.PutString( pv ); + return b; +} + + + +class CUtlInplaceBuffer : public CUtlBuffer +{ +public: + DLL_CLASS_IMPORT CUtlInplaceBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 ); + + // + // Routines returning buffer-inplace-pointers + // +public: + // + // Upon success, determines the line length, fills out the pointer to the + // beginning of the line and the line length, advances the "get" pointer + // offset by the line length and returns "true". + // + // If end of file is reached or upon error returns "false". + // + // Note: the returned length of the line is at least one character because the + // trailing newline characters are also included as part of the line. + // + // Note: the pointer returned points into the local memory of this buffer, in + // case the buffer gets relocated or destroyed the pointer becomes invalid. + // + // e.g.: ------------- + // + // char *pszLine; + // int nLineLen; + // while ( pUtlInplaceBuffer->InplaceGetLinePtr( &pszLine, &nLineLen ) ) + // { + // ... + // } + // + // ------------- + // + // @param ppszInBufferPtr on return points into this buffer at start of line + // @param pnLineLength on return holds num bytes accessible via (*ppszInBufferPtr) + // + // @returns true if line was successfully read + // false when EOF is reached or error occurs + // + DLL_CLASS_IMPORT bool InplaceGetLinePtr( /* out */ char **ppszInBufferPtr, /* out */ int *pnLineLength ); + + // + // Determines the line length, advances the "get" pointer offset by the line length, + // replaces the newline character with null-terminator and returns the initial pointer + // to now null-terminated line. + // + // If end of file is reached or upon error returns NULL. + // + // Note: the pointer returned points into the local memory of this buffer, in + // case the buffer gets relocated or destroyed the pointer becomes invalid. + // + // e.g.: ------------- + // + // while ( char *pszLine = pUtlInplaceBuffer->InplaceGetLinePtr() ) + // { + // ... + // } + // + // ------------- + // + // @returns ptr-to-zero-terminated-line if line was successfully read and buffer modified + // NULL when EOF is reached or error occurs + // + DLL_CLASS_IMPORT char * InplaceGetLinePtr( void ); +}; + + +//----------------------------------------------------------------------------- +// Where am I reading? +//----------------------------------------------------------------------------- +inline int CUtlBuffer::TellGet( ) const +{ + return m_Get; +} + + +//----------------------------------------------------------------------------- +// How many bytes remain to be read? +//----------------------------------------------------------------------------- +inline int CUtlBuffer::GetBytesRemaining() const +{ + return m_nMaxPut - TellGet(); +} + + +//----------------------------------------------------------------------------- +// What am I reading? +//----------------------------------------------------------------------------- +inline const void* CUtlBuffer::PeekGet( int offset ) const +{ + return &m_Memory[ m_Get + offset - m_nOffset ]; +} + + +//----------------------------------------------------------------------------- +// Unserialization +//----------------------------------------------------------------------------- + +template +inline void CUtlBuffer::GetObject( T *dest ) +{ + if ( CheckGet( sizeof(T) ) ) + { + if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) + { + *dest = *(T *)PeekGet(); + } + else + { + m_Byteswap.SwapFieldsToTargetEndian( dest, (T*)PeekGet() ); + } + m_Get += sizeof(T); + } + else + { + Q_memset( &dest, 0, sizeof(T) ); + } +} + + +template +inline void CUtlBuffer::GetObjects( T *dest, int count ) +{ + for ( int i = 0; i < count; ++i, ++dest ) + { + GetObject( dest ); + } +} + + +template +inline void CUtlBuffer::GetTypeBin( T &dest ) +{ + if ( CheckGet( sizeof(T) ) ) + { + if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) + { + dest = *(T *)PeekGet(); + } + else + { + m_Byteswap.SwapBufferToTargetEndian( &dest, (T*)PeekGet() ); + } + m_Get += sizeof(T); + } + else + { + dest = 0; + } +} + +template <> +inline void CUtlBuffer::GetTypeBin< float >( float &dest ) +{ + if ( CheckGet( sizeof( float ) ) ) + { + uintp pData = (uintp)PeekGet(); +#if defined( _X360 ) + if ( pData & 0x03 ) + { + // handle unaligned read + ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0]; + ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1]; + ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2]; + ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3]; + } + else + { + // aligned read + dest = *(float *)pData; + } +#else + dest = *(float *)pData; +#endif + if ( m_Byteswap.IsSwappingBytes() ) + { + m_Byteswap.SwapBufferToTargetEndian< float >( &dest, &dest ); + } + m_Get += sizeof( float ); + } + else + { + dest = 0; + } +} + +template <> +inline void CUtlBuffer::GetTypeBin< double >( double &dest ) +{ + if ( CheckGet( sizeof( double ) ) ) + { + uintp pData = (uintp)PeekGet(); +#if defined( _X360 ) + if ( pData & 0x07 ) + { + // handle unaligned read + ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0]; + ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1]; + ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2]; + ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3]; + ((unsigned char*)&dest)[4] = ((unsigned char*)pData)[4]; + ((unsigned char*)&dest)[5] = ((unsigned char*)pData)[5]; + ((unsigned char*)&dest)[6] = ((unsigned char*)pData)[6]; + ((unsigned char*)&dest)[7] = ((unsigned char*)pData)[7]; + } + else + { + // aligned read + dest = *(double *)pData; + } +#else + dest = *(double *)pData; +#endif + if ( m_Byteswap.IsSwappingBytes() ) + { + m_Byteswap.SwapBufferToTargetEndian< double >( &dest, &dest ); + } + m_Get += sizeof( double ); + } + else + { + dest = 0; + } +} + +template < class T > +inline T StringToNumber( char *pString, char **ppEnd, int nRadix ) +{ + Assert( 0 ); + *ppEnd = pString; + return 0; +} + +template <> +inline int8 StringToNumber( char *pString, char **ppEnd, int nRadix ) +{ + return ( int8 )strtol( pString, ppEnd, nRadix ); +} + +template <> +inline uint8_t StringToNumber( char *pString, char **ppEnd, int nRadix ) +{ + return ( uint8_t )strtoul( pString, ppEnd, nRadix ); +} + +template <> +inline int16 StringToNumber( char *pString, char **ppEnd, int nRadix ) +{ + return ( int16 )strtol( pString, ppEnd, nRadix ); +} + +template <> +inline uint16 StringToNumber( char *pString, char **ppEnd, int nRadix ) +{ + return ( uint16 )strtoul( pString, ppEnd, nRadix ); +} + +template <> +inline int32 StringToNumber( char *pString, char **ppEnd, int nRadix ) +{ + return ( int32 )strtol( pString, ppEnd, nRadix ); +} + +template <> +inline uint32 StringToNumber( char *pString, char **ppEnd, int nRadix ) +{ + return ( uint32 )strtoul( pString, ppEnd, nRadix ); +} + +template <> +inline int64_t StringToNumber( char *pString, char **ppEnd, int nRadix ) +{ + return ( int64_t )_strtoi64( pString, ppEnd, nRadix ); +} + +template <> +inline float StringToNumber( char *pString, char **ppEnd, int nRadix ) +{ + // /*UNUSED*/( nRadix ); + return ( float )strtod( pString, ppEnd ); +} + +template <> +inline double StringToNumber( char *pString, char **ppEnd, int nRadix ) +{ + // /*UNUSED*/( nRadix ); + return ( double )strtod( pString, ppEnd ); +} + +template +inline bool CUtlBuffer::GetTypeText( T &value, int nRadix /*= 10*/ ) +{ + // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters + int nLength = 128; + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + { + value = 0; + return false; + } + + char *pStart = (char*)PeekGet(); + char* pEnd = pStart; + value = StringToNumber< T >( pStart, &pEnd, nRadix ); + + int nBytesRead = (int)( pEnd - pStart ); + if ( nBytesRead == 0 ) + return false; + + m_Get += nBytesRead; + return true; +} + +template +inline void CUtlBuffer::GetType( T &dest ) +{ + if (!IsText()) + { + GetTypeBin( dest ); + } + else + { + GetTypeText( dest ); + } +} + +inline char CUtlBuffer::GetChar( ) +{ + // LEGACY WARNING: this behaves differently than GetUnsignedChar() + char c; + GetTypeBin( c ); // always reads as binary + return c; +} + +inline unsigned char CUtlBuffer::GetUnsignedChar( ) +{ + // LEGACY WARNING: this behaves differently than GetChar() + unsigned char c; + if (!IsText()) + { + GetTypeBin( c ); + } + else + { + c = ( unsigned char )GetUnsignedShort(); + } + return c; +} + +inline short CUtlBuffer::GetShort( ) +{ + short s; + GetType( s ); + return s; +} + +inline unsigned short CUtlBuffer::GetUnsignedShort( ) +{ + unsigned short s; + GetType( s ); + return s; +} + +inline int CUtlBuffer::GetInt( ) +{ + int i; + GetType( i ); + return i; +} + +inline int64_t CUtlBuffer::Getint64_t( ) +{ + int64_t i; + GetType( i ); + return i; +} + +inline unsigned int CUtlBuffer::GetIntHex( ) +{ + unsigned int i; + if (!IsText()) + { + GetTypeBin( i ); + } + else + { + GetTypeText( i, 16 ); + } + return i; +} + +inline unsigned int CUtlBuffer::GetUnsignedInt( ) +{ + unsigned int i; + GetType( i ); + return i; +} + +inline float CUtlBuffer::GetFloat( ) +{ + float f; + GetType( f ); + return f; +} + +inline double CUtlBuffer::GetDouble( ) +{ + double d; + GetType( d ); + return d; +} + +inline void *CUtlBuffer::GetPtr( ) +{ + void *p; + // LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal +#ifndef X64BITS + p = ( void* )GetUnsignedInt(); +#else + p = ( void* )Getint64_t(); +#endif + return p; +} + +//----------------------------------------------------------------------------- +// Where am I writing? +//----------------------------------------------------------------------------- +inline unsigned char CUtlBuffer::GetFlags() const +{ + return m_Flags; +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +inline bool CUtlBuffer::IsExternallyAllocated() const +{ + return m_Memory.IsExternallyAllocated(); +} + + +//----------------------------------------------------------------------------- +// Where am I writing? +//----------------------------------------------------------------------------- +inline int CUtlBuffer::TellPut( ) const +{ + return m_Put; +} + + +//----------------------------------------------------------------------------- +// What's the most I've ever written? +//----------------------------------------------------------------------------- +inline int CUtlBuffer::TellMaxPut( ) const +{ + return m_nMaxPut; +} + + +//----------------------------------------------------------------------------- +// What am I reading? +//----------------------------------------------------------------------------- +inline void* CUtlBuffer::PeekPut( int offset ) +{ + return &m_Memory[m_Put + offset - m_nOffset]; +} + + +//----------------------------------------------------------------------------- +// Various put methods +//----------------------------------------------------------------------------- + +template +inline void CUtlBuffer::PutObject( T *src ) +{ + if ( CheckPut( sizeof(T) ) ) + { + if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) + { + *(T *)PeekPut() = *src; + } + else + { + m_Byteswap.SwapFieldsToTargetEndian( (T*)PeekPut(), src ); + } + m_Put += sizeof(T); + AddNullTermination(); + } +} + + +template +inline void CUtlBuffer::PutObjects( T *src, int count ) +{ + for ( int i = 0; i < count; ++i, ++src ) + { + PutObject( src ); + } +} + + +template +inline void CUtlBuffer::PutTypeBin( T src ) +{ + if ( CheckPut( sizeof(T) ) ) + { + if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) + { + *(T *)PeekPut() = src; + } + else + { + m_Byteswap.SwapBufferToTargetEndian( (T*)PeekPut(), &src ); + } + m_Put += sizeof(T); + AddNullTermination(); + } +} + +#if defined( _X360 ) +template <> +inline void CUtlBuffer::PutTypeBin< float >( float src ) +{ + if ( CheckPut( sizeof( src ) ) ) + { + if ( m_Byteswap.IsSwappingBytes() ) + { + m_Byteswap.SwapBufferToTargetEndian( &src, &src ); + } + + // + // Write the data + // + unsigned pData = (unsigned)PeekPut(); + if ( pData & 0x03 ) + { + // handle unaligned write + byte* dst = (byte*)pData; + byte* srcPtr = (byte*)&src; + dst[0] = srcPtr[0]; + dst[1] = srcPtr[1]; + dst[2] = srcPtr[2]; + dst[3] = srcPtr[3]; + } + else + { + *(float *)pData = src; + } + + m_Put += sizeof(float); + AddNullTermination(); + } +} + +template <> +inline void CUtlBuffer::PutTypeBin< double >( double src ) +{ + if ( CheckPut( sizeof( src ) ) ) + { + if ( m_Byteswap.IsSwappingBytes() ) + { + m_Byteswap.SwapBufferToTargetEndian( &src, &src ); + } + + // + // Write the data + // + unsigned pData = (unsigned)PeekPut(); + if ( pData & 0x07 ) + { + // handle unaligned write + byte* dst = (byte*)pData; + byte* srcPtr = (byte*)&src; + dst[0] = srcPtr[0]; + dst[1] = srcPtr[1]; + dst[2] = srcPtr[2]; + dst[3] = srcPtr[3]; + dst[4] = srcPtr[4]; + dst[5] = srcPtr[5]; + dst[6] = srcPtr[6]; + dst[7] = srcPtr[7]; + } + else + { + *(double *)pData = src; + } + + m_Put += sizeof(double); + AddNullTermination(); + } +} +#endif + +template +inline void CUtlBuffer::PutType( T src ) +{ + if (!IsText()) + { + PutTypeBin( src ); + } + else + { + Printf( GetFmtStr< T >(), src ); + } +} + +//----------------------------------------------------------------------------- +// Methods to help with pretty-printing +//----------------------------------------------------------------------------- +inline bool CUtlBuffer::WasLastCharacterCR() +{ + if ( !IsText() || (TellPut() == 0) ) + return false; + return ( *( const char * )PeekPut( -1 ) == '\n' ); +} + +inline void CUtlBuffer::PutTabs() +{ + int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab; + for (int i = nTabCount; --i >= 0; ) + { + PutTypeBin( '\t' ); + } +} + + +//----------------------------------------------------------------------------- +// Push/pop pretty-printing tabs +//----------------------------------------------------------------------------- +inline void CUtlBuffer::PushTab( ) +{ + ++m_nTab; +} + +inline void CUtlBuffer::PopTab() +{ + if ( --m_nTab < 0 ) + { + m_nTab = 0; + } +} + + +//----------------------------------------------------------------------------- +// Temporarily disables pretty print +//----------------------------------------------------------------------------- +inline void CUtlBuffer::EnableTabs( bool bEnable ) +{ + if ( bEnable ) + { + m_Flags &= ~AUTO_TABS_DISABLED; + } + else + { + m_Flags |= AUTO_TABS_DISABLED; + } +} + +inline void CUtlBuffer::PutChar( char c ) +{ + if ( WasLastCharacterCR() ) + { + PutTabs(); + } + + PutTypeBin( c ); +} + +inline void CUtlBuffer::PutUnsignedChar( unsigned char c ) +{ + if (!IsText()) + { + PutTypeBin( c ); + } + else + { + PutUnsignedShort( c ); + } +} + +inline void CUtlBuffer::PutShort( short s ) +{ + PutType( s ); +} + +inline void CUtlBuffer::PutUnsignedShort( unsigned short s ) +{ + PutType( s ); +} + +inline void CUtlBuffer::PutInt( int i ) +{ + PutType( i ); +} + +inline void CUtlBuffer::Putint64_t( int64_t i ) +{ + PutType( i ); +} + +inline void CUtlBuffer::PutUnsignedInt( unsigned int u ) +{ + PutType( u ); +} + +inline void CUtlBuffer::PutFloat( float f ) +{ + PutType( f ); +} + +inline void CUtlBuffer::PutDouble( double d ) +{ + PutType( d ); +} + +inline void CUtlBuffer::PutPtr( void *p ) +{ + // LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal + if (!IsText()) + { + PutTypeBin( p ); + } + else + { + Printf( "0x%p", p ); + } +} + +//----------------------------------------------------------------------------- +// Am I a text buffer? +//----------------------------------------------------------------------------- +inline bool CUtlBuffer::IsText() const +{ + return (m_Flags & TEXT_BUFFER) != 0; +} + + +//----------------------------------------------------------------------------- +// Can I grow if I'm externally allocated? +//----------------------------------------------------------------------------- +inline bool CUtlBuffer::IsGrowable() const +{ + return (m_Flags & EXTERNAL_GROWABLE) != 0; +} + + +//----------------------------------------------------------------------------- +// Am I valid? (overflow or underflow error), Once invalid it stays invalid +//----------------------------------------------------------------------------- +inline bool CUtlBuffer::IsValid() const +{ + return m_Error == 0; +} + + +//----------------------------------------------------------------------------- +// Do I contain carriage return/linefeeds? +//----------------------------------------------------------------------------- +inline bool CUtlBuffer::ContainsCRLF() const +{ + return IsText() && ((m_Flags & CONTAINS_CRLF) != 0); +} + + +//----------------------------------------------------------------------------- +// Am I read-only +//----------------------------------------------------------------------------- +inline bool CUtlBuffer::IsReadOnly() const +{ + return (m_Flags & READ_ONLY) != 0; +} + + +//----------------------------------------------------------------------------- +// Buffer base and size +//----------------------------------------------------------------------------- +inline const void* CUtlBuffer::Base() const +{ + return m_Memory.Base(); +} + +inline void* CUtlBuffer::Base() +{ + return m_Memory.Base(); +} + +inline int CUtlBuffer::Size() const +{ + return m_Memory.NumAllocated(); +} + + +//----------------------------------------------------------------------------- +// Clears out the buffer; frees memory +//----------------------------------------------------------------------------- +inline void CUtlBuffer::Clear() +{ + m_Get = 0; + m_Put = 0; + m_Error = 0; + m_nOffset = 0; + m_nMaxPut = -1; + AddNullTermination(); +} + +inline void CUtlBuffer::Purge() +{ + m_Get = 0; + m_Put = 0; + m_nOffset = 0; + m_nMaxPut = 0; + m_Error = 0; + m_Memory.Purge(); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +inline void *CUtlBuffer::AccessForDirectRead( int nBytes ) +{ + Assert( m_Get == 0 && m_Put == 0 && m_nMaxPut == 0 ); + EnsureCapacity( nBytes ); + m_nMaxPut = nBytes; + return Base(); +} + +inline void *CUtlBuffer::Detach() +{ + void *p = m_Memory.Detach(); + Clear(); + return p; +} + +//----------------------------------------------------------------------------- + +inline void CUtlBuffer::Spew( ) +{ + SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); + + char pTmpLine[1024]; + while( IsValid() && GetBytesRemaining() ) + { + memset( pTmpLine, 0, sizeof(pTmpLine) ); + Get( pTmpLine, min( (unsigned int)GetBytesRemaining(), sizeof(pTmpLine)-1 ) ); + } +} + + +#endif // UTLBUFFER_H + diff --git a/csgo2/sdk/tier1/utlfixedmemory.h b/csgo2/sdk/tier1/utlfixedmemory.h index 390b2c8..9999741 100644 --- a/csgo2/sdk/tier1/utlfixedmemory.h +++ b/csgo2/sdk/tier1/utlfixedmemory.h @@ -1,11 +1,3 @@ -//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -// A growable memory class. -//===========================================================================// #ifndef UTLFIXEDMEMORY_H #define UTLFIXEDMEMORY_H diff --git a/csgo2/sdk_tools.cpp b/csgo2/sdk_tools.cpp index 7312bd5..8207867 100644 --- a/csgo2/sdk_tools.cpp +++ b/csgo2/sdk_tools.cpp @@ -1,34 +1,55 @@ #include "sdk_tools.h" namespace SdkTools { - auto ProcessChatString(const std::string& input) -> std::tuple - { - _ChatType chatType; - std::string content; - bool success = true; - // ¼ì²éÊäÈëÊÇ·ñÒÔ "say_team" »ò "say" ¿ªÍ· - if (input.size() >= 9 && input.substr(0, 9) == "say_team ") { - chatType = _ChatType::kTeam; - content = input.substr(9); - } - else if (input.size() >= 5 && input.substr(0, 4) == "say ") { - chatType = _ChatType::kAll; - content = input.substr(4); - } - else { +auto ProcessChatString(const std::string& input) + -> std::tuple { + _ChatType chatType; + std::string content; + bool success = true; + // ¼ì²éÊäÈëÊÇ·ñÒÔ "say_team" »ò "say" ¿ªÍ· + if (input.size() >= 9 && input.substr(0, 9) == "say_team ") { + chatType = _ChatType::kTeam; + content = input.substr(9); + } else if (input.size() >= 5 && input.substr(0, 4) == "say ") { + chatType = _ChatType::kAll; + content = input.substr(4); + } else { + success = false; + } + if (success == true) { + // ¼ì²éÄÚÈÝÊÇ·ñ±»ÒýºÅ°üΧ + if (content.front() != '"' || content.back() != '"') { success = false; + } else { + // ÒÆ³ýÒýºÅ + content = content.substr(1, content.size() - 2); } - if (success == true) { - // ¼ì²éÄÚÈÝÊÇ·ñ±»ÒýºÅ°üΧ - if (content.front() != '"' || content.back() != '"') { - success = false; - } - else { - // ÒÆ³ýÒýºÅ - content = content.substr(1, content.size() - 2); - } - } + } - return std::make_tuple(success, chatType, content); - } -}; \ No newline at end of file + return std::make_tuple(success, chatType, content); +} + +auto SentChatToClient(CCSPlayerController* player, _HubType hubtype, const char* msg, ...) -> void { + va_list args; + va_start(args, msg); + + char buf[256]; + vsnprintf(buf, sizeof(buf), msg, args); + + va_end(args); + + Offset::FnClientPrint(player, hubtype, buf, nullptr, nullptr, nullptr, nullptr); +} +auto SendConsoleChat(_HubType hubtype, const char* msg, ...) -> void +{ + va_list args; + va_start(args, msg); + + char buf[256]; + vsnprintf(buf, sizeof(buf), msg, args); + + va_end(args); + + Offset::FnUTIL_ClientPrintAll(hubtype, buf, nullptr, nullptr, nullptr, nullptr); +} +}; // namespace SdkTools diff --git a/csgo2/sdk_tools.h b/csgo2/sdk_tools.h index ea8abee..86894fd 100644 --- a/csgo2/sdk_tools.h +++ b/csgo2/sdk_tools.h @@ -1,12 +1,19 @@ #pragma once #include "head.h" inline int PlayerSlot_to_EntityIndex(int PlayerSlot) { return PlayerSlot + 1; } -inline int EntityIndex_to_PlayerSlot(int EntityIndex) { return EntityIndex - 1; } -enum _ChatType -{ - kTeam, - kAll -}; +inline int EntityIndex_to_PlayerSlot(int EntityIndex) { + return EntityIndex - 1; +} +#define HUD_PRINTNOTIFY 1 +#define HUD_PRINTCONSOLE 2 +#define HUD_PRINTTALK 3 +#define HUD_PRINTCENTER 4 +enum _ChatType { kTeam, kAll }; +enum _HubType { kNotify = 1, kConsole, kTalk, kCenter, kMax }; + namespace SdkTools { - auto ProcessChatString(const std::string& input) -> std::tuple; -}; \ No newline at end of file +auto ProcessChatString(const std::string& input) + -> std::tuple; +auto SentChatToClient(CCSPlayerController* player, _HubType hubtype, const char* msg, ...) -> void; +auto SendConsoleChat(_HubType hubtype, const char* msg, ...) -> void; +}; // namespace SdkTools diff --git a/csgo2/timer.cpp b/csgo2/timer.cpp index c709ff2..2dfd99c 100644 --- a/csgo2/timer.cpp +++ b/csgo2/timer.cpp @@ -4,15 +4,15 @@ extern auto TimerCallBack(_GameTimer* timer) -> void; extern auto RunTickCallBack(_GameTickRunTime* timer) -> void; }; // namespace ScriptApis namespace GameTimer { -std::shared_mutex mutex_timerList; +std::recursive_mutex mutex_timerList; std::vector<_GameTimer*> timerList; auto AddTimer(_GameTimer* timer) -> int { - std::unique_lock lock(mutex_timerList); + std::unique_lock lock(mutex_timerList); timerList.push_back(timer); return timerList.size() - 1; }; auto CleanUpTimers() -> void { - std::unique_lock lock(mutex_timerList); + std::unique_lock lock(mutex_timerList); for (auto it = timerList.begin(); it != timerList.end();) { if ((*it)->m_bPreserveMapChange) { ++it; @@ -23,7 +23,7 @@ auto CleanUpTimers() -> void { } }; auto ExcuteTimers() -> void { - std::shared_lock lock(mutex_timerList); + std::unique_lock lock(mutex_timerList); for (auto it = timerList.begin(); it != timerList.end();) { if ((*it)->m_flLastExecute == -1) { (*it)->m_flLastExecute = global::m_flUniversalTime; @@ -44,21 +44,21 @@ auto ExcuteTimers() -> void { } }; // namespace GameTimer namespace GameTickRunTime { -std::shared_mutex mutex_tickRunList; +std::recursive_mutex mutex_tickRunList; std::vector<_GameTickRunTime*> tickRunList; auto AddTickFunction(_GameTickRunTime* timer) -> void { - std::unique_lock lock(mutex_tickRunList); + std::unique_lock lock(mutex_tickRunList); tickRunList.push_back(timer); }; auto CleanUpTickFunctions() -> void { - std::unique_lock lock(mutex_tickRunList); + std::unique_lock lock(mutex_tickRunList); for (auto it = tickRunList.begin(); it != tickRunList.end();) { delete (*it); it = tickRunList.erase(it); } }; auto ExcuteTickFunctions() -> void { - std::shared_lock lock(mutex_tickRunList); + std::unique_lock lock(mutex_tickRunList); for (auto it = tickRunList.begin(); it != tickRunList.end();) { ScriptApis::RunTickCallBack(*it); delete (*it);