From c92fb41e2bc5cfc1ae1aa13f5ab7cb293bb13c67 Mon Sep 17 00:00:00 2001 From: arthurdead Date: Sat, 30 Jul 2022 13:49:36 -0300 Subject: [PATCH] remove std::unique_ptr from packed_entity_data_t, ignore connecting players, fix crash SendTable_CalcDelta when the entity_data vector was empty --- extension.cpp | 93 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 25 deletions(-) diff --git a/extension.cpp b/extension.cpp index 7ec1cae..892dcc2 100644 --- a/extension.cpp +++ b/extension.cpp @@ -586,19 +586,43 @@ private: struct packed_entity_data_t final { - packed_entity_data_t(packed_entity_data_t &&) noexcept = default; - packed_entity_data_t &operator=(packed_entity_data_t &&) noexcept = default; + packed_entity_data_t(packed_entity_data_t &&other) noexcept + { operator=(std::move(other)); } + packed_entity_data_t &operator=(packed_entity_data_t &&other) noexcept { + packedData = other.packedData; + other.packedData = nullptr; + writeBuf = other.writeBuf; + other.writeBuf = nullptr; + objectID = other.objectID; + other.objectID = -1; + return *this; + } - std::unique_ptr packedData{}; - std::unique_ptr writeBuf{}; + char *packedData{nullptr}; + bf_write *writeBuf{nullptr}; int objectID{-1}; packed_entity_data_t() noexcept = default; - ~packed_entity_data_t() noexcept = default; + ~packed_entity_data_t() noexcept { + reset(); + } + + void reset() noexcept { + if(packedData) { + free(packedData); + packedData = nullptr; + } + if(writeBuf) { + delete writeBuf; + writeBuf = nullptr; + } + } void allocate() noexcept { - packedData.reset(static_cast(aligned_alloc(4, MAX_PACKEDENTITY_DATA))); - writeBuf.reset(new bf_write{"SV_PackEntity->writeBuf", packedData.get(), MAX_PACKEDENTITY_DATA}); + reset(); + + packedData = static_cast(aligned_alloc(4, MAX_PACKEDENTITY_DATA)); + writeBuf = new bf_write{"SV_PackEntity->writeBuf", packedData, MAX_PACKEDENTITY_DATA}; } private: @@ -1221,7 +1245,7 @@ DETOUR_DECL_STATIC6(SendTable_Encode, bool, const SendTable *, pTable, const voi packedData.allocate(); sendproxy_client_slot = packentity_params->slots[i]; - const bool encoded{DETOUR_STATIC_CALL(SendTable_Encode)(pTable, pStruct, packedData.writeBuf.get(), objectID, pRecipients, bNonZeroOnly)}; + const bool encoded{DETOUR_STATIC_CALL(SendTable_Encode)(pTable, pStruct, packedData.writeBuf, objectID, pRecipients, bNonZeroOnly)}; sendproxy_client_slot = nullptr; if(!encoded) { Host_Error( "SV_PackEntity: SendTable_Encode returned false (ent %d).\n", objectID ); @@ -1248,9 +1272,14 @@ DETOUR_DECL_STATIC8(SendTable_CalcDelta, int, const SendTable *, pTable, const v int *client_deltaProps{new int[nMaxDeltaProps]{static_cast(-1)}}; for(int i{0}; i < packentity_params->slots.size(); ++i) { - packed_entity_data_t &packedData{packentity_params->entity_data[i].back()}; + std::vector &entity_data{packentity_params->entity_data[i]}; + if(entity_data.size() == 0) { + continue; + } - const int client_nChanges{DETOUR_STATIC_CALL(SendTable_CalcDelta)(pTable, pFromState, nFromBits, packedData.packedData.get(), packedData.writeBuf->GetNumBitsWritten(), client_deltaProps, nMaxDeltaProps, objectID)}; + packed_entity_data_t &packedData{entity_data.back()}; + + const int client_nChanges{DETOUR_STATIC_CALL(SendTable_CalcDelta)(pTable, pFromState, nFromBits, packedData.packedData, packedData.writeBuf->GetNumBitsWritten(), client_deltaProps, nMaxDeltaProps, objectID)}; bool done{false}; @@ -1349,7 +1378,8 @@ DETOUR_DECL_MEMBER2(CFrameSnapshotManager_GetPackedEntity, PackedEntity *, CFram const packed_entity_data_t *packedData{nullptr}; for(int i{0}; i < packentity_params->slots.size(); ++i) { if(packentity_params->slots[i] == slot) { - for(const packed_entity_data_t &it : packentity_params->entity_data[i]) { + const std::vector &entity_data{packentity_params->entity_data[i]}; + for(const packed_entity_data_t &it : entity_data) { if(it.objectID == entity) { packedData = ⁢ break; @@ -1364,7 +1394,7 @@ DETOUR_DECL_MEMBER2(CFrameSnapshotManager_GetPackedEntity, PackedEntity *, CFram packed->FreeData(); } - packed->AllocAndCopyPadded(packedData->packedData.get(), packedData->writeBuf->GetNumBytesWritten()); + packed->AllocAndCopyPadded(packedData->packedData, packedData->writeBuf->GetNumBytesWritten()); } return packed; @@ -1372,12 +1402,28 @@ DETOUR_DECL_MEMBER2(CFrameSnapshotManager_GetPackedEntity, PackedEntity *, CFram static ConVar *sv_stressbots{nullptr}; +static bool is_client_valid(CBaseClient *client) noexcept +{ + if(!sv_stressbots->GetBool()) { + if(client->IsFakeClient() || + client->IsHLTV() || + client->IsReplay()) { + return false; + } + } + + if(!client->IsConnected() || + !client->IsSpawned() || + !client->IsActive()) { + return false; + } + + return true; +} + DETOUR_DECL_MEMBER4(CBaseServer_WriteDeltaEntities, void, CBaseClient *, client, CClientFrame *, to, CClientFrame *, from, bf_write &, pBuf) { - if(!sv_stressbots->GetBool() && - (client->IsFakeClient() || - client->IsHLTV() || - client->IsReplay())) { + if(!is_client_valid(client)) { writedeltaentities_client = nullptr; } else { writedeltaentities_client = client->GetPlayerSlot(); @@ -1422,10 +1468,7 @@ DETOUR_DECL_STATIC3(SV_ComputeClientPacks, void, int, clientCount, CGameClient * slots.reserve(clientCount); for(int i{0}; i < clientCount; ++i) { CGameClient *client{clients[i]}; - if(!sv_stressbots->GetBool() && - (client->IsFakeClient() || - client->IsHLTV() || - client->IsReplay())) { + if(!is_client_valid(client)) { continue; } slots.emplace_back(client->GetPlayerSlot()); @@ -1469,6 +1512,11 @@ DETOUR_DECL_STATIC3(SV_ComputeClientPacks, void, int, clientCount, CGameClient * const bool any_per_client_hook{slots.size() > 0 && entities.size() > 0}; +#if defined _DEBUG && 1 + printf("slots = %i, entities = %i\n", slots.size(), entities.size()); + printf("any_hook = %i, any_per_client_hook = %i, is_parallel_pack_allowed = %i\n", any_hook, any_per_client_hook, g_Sample.is_parallel_pack_allowed()); +#endif + if(any_per_client_hook) { packentity_params.reset(new pack_entity_params_t{std::move(slots), std::move(entities), snapshot->m_ListIndex}); SendTable_Encode_detour->EnableDetour(); @@ -1487,11 +1535,6 @@ DETOUR_DECL_STATIC3(SV_ComputeClientPacks, void, int, clientCount, CGameClient * g_Sample.is_parallel_pack_allowed() ); -#if defined _DEBUG && 0 - printf("slots = %i, entities = %i\n", slots.size(), entities.size()); - printf("any_hook = %i, any_per_client_hook = %i, is_parallel_pack_allowed = %i\n", any_hook, any_per_client_hook, g_Sample.is_parallel_pack_allowed()); -#endif - in_compute_packs = true; DETOUR_STATIC_CALL(SV_ComputeClientPacks)(clientCount, clients, snapshot); in_compute_packs = false;