From 1e348c5abb4ac602ce29fc12bbc079da2ca15f50 Mon Sep 17 00:00:00 2001 From: ericek111 Date: Mon, 10 Aug 2026 17:02:48 +0200 Subject: [PATCH] clean up debugging outputs --- README.md | 16 +++-- .../SendProxyConcealedCarryPlugin.cs | 54 +++++--------- src/detour.cpp | 34 --------- src/overrides.cpp | 72 ------------------- src/overrides.h | 2 - 5 files changed, 27 insertions(+), 151 deletions(-) diff --git a/README.md b/README.md index 0615622..c255432 100644 --- a/README.md +++ b/README.md @@ -97,19 +97,23 @@ It demonstrates: - Coloring dropped AK-47s red for Terrorist viewers. - Coloring dropped M4A1-S blue for CT viewers. -Concealed-carry handle spoof: +Concealed-carry weapon-list spoof: ```text examples/CounterStrikeSharp/SendProxyConcealedCarry/ ``` -It hides owned primary weapons, secondary weapons, and grenades from every recipient except the owning player by spoofing weapon-related handles to `0xffffffff`: +It hides a player's non-active carried weapons from every recipient except the owning player by spoofing the player/weapon association: -- `CBasePlayerPawn::m_pWeaponServices.m_hActiveWeapon` -- `CBasePlayerPawn::m_pWeaponServices.m_hLastWeapon` -- `CBaseEntity::m_hOwnerEntity` on carried weapon entities +- `CBasePlayerPawn::m_pWeaponServices.m_hMyWeapons` +- source handle: `CBasePlayerPawn::m_pWeaponServices.m_hActiveWeapon` +- `CBaseEntity::m_hOwnerEntity = INVALID_EHANDLE` on non-active carried weapon entities +- `CBaseEntity::m_CBodyComponent.m_pSceneNode.m_hParent = INVALID_EHANDLE` +- `CBaseEntity::m_CBodyComponent.m_pSceneNode.m_hierarchyAttachName = 0` +- `CCSWeaponBase::m_hPrevOwner = INVALID_EHANDLE` +- `CBaseCSGrenade::m_bIsHeldByPlayer = false` for non-active grenades -It intentionally does not set `EF_NODRAW` and does not remove or drop the real weapons. +This corresponds to CounterStrikeSharp's `player.PlayerPawn.Value.WeaponServices?.MyWeapons`, plus the weapon entity relationship fields that attach carried weapons to the owning pawn. During packing for non-owner recipients, native code temporarily masks non-active `m_hMyWeapons` elements to `INVALID_EHANDLE`; the CSS sample also spoofs non-active carried weapon entities as detached/unowned. It intentionally does not set `EF_NODRAW`, use render mode tricks, or remove/drop the real weapons. This sample periodically reconciles desired rules and diffs them against active rule IDs. For production, prefer event-driven updates on player connect/disconnect/team changes/spawn/death and weapon pickup/drop/create/delete. diff --git a/examples/CounterStrikeSharp/SendProxyConcealedCarry/SendProxyConcealedCarryPlugin.cs b/examples/CounterStrikeSharp/SendProxyConcealedCarry/SendProxyConcealedCarryPlugin.cs index bc4e18a..6e143b8 100644 --- a/examples/CounterStrikeSharp/SendProxyConcealedCarry/SendProxyConcealedCarryPlugin.cs +++ b/examples/CounterStrikeSharp/SendProxyConcealedCarry/SendProxyConcealedCarryPlugin.cs @@ -10,6 +10,11 @@ public sealed class SendProxyConcealedCarryPlugin : BasePlugin { private const string WeaponListField = "m_pWeaponServices.m_hMyWeapons"; private const string ActiveWeaponField = "m_pWeaponServices.m_hActiveWeapon"; + private const string EntityClass = "CBaseEntity"; + private static readonly byte[] InvalidHandle = UInt32Bytes(0xffffffff); + private static readonly byte[] EmptyToken = UInt32Bytes(0); + private static readonly byte[] NoAttachment = Int16Bytes(-1); + private static readonly byte[] FalseByte = [0]; private readonly Dictionary _activeRules = new(); private SendProxyNative? _sendProxy; @@ -110,36 +115,8 @@ public sealed class SendProxyConcealedCarryPlugin : BasePlugin if (viewer.Slot == weapon.OwnerSlot) continue; - desired[new RuleKey( - ToEngineSlot(viewer), - weapon.EntityIndex, - "CBaseEntity", - "m_hOwnerEntity")] = UInt32Bytes(0xffffffff); - desired[new RuleKey( - ToEngineSlot(viewer), - weapon.EntityIndex, - "CBaseEntity", - "m_CBodyComponent.m_pSceneNode.m_hParent.m_hOwner")] = UInt32Bytes(0xffffffff); - desired[new RuleKey( - ToEngineSlot(viewer), - weapon.EntityIndex, - "CBaseEntity", - "m_CBodyComponent.m_pSceneNode.m_hParent.m_name")] = UInt32Bytes(0); - desired[new RuleKey( - ToEngineSlot(viewer), - weapon.EntityIndex, - "CBaseEntity", - "m_CBodyComponent.m_pSceneNode.m_nParentAttachmentOrBone")] = Int16Bytes(-1); - desired[new RuleKey( - ToEngineSlot(viewer), - weapon.EntityIndex, - "CBaseEntity", - "m_CBodyComponent.m_pSceneNode.m_hierarchyAttachName")] = UInt32Bytes(0); - desired[new RuleKey( - ToEngineSlot(viewer), - weapon.EntityIndex, - "CBaseEntity", - "m_CBodyComponent.m_pSceneNode.m_bForceParentToBeNetworked")] = new byte[] { 0 }; + int recipient = ToEngineSlot(viewer); + AddAssociationDisconnectRules(desired, recipient, weapon.EntityIndex); } } @@ -206,13 +183,6 @@ public sealed class SendProxyConcealedCarryPlugin : BasePlugin } } - private static byte[] UInt16Bytes(ushort value) - { - byte[] bytes = new byte[2]; - BitConverter.TryWriteBytes(bytes, value); - return bytes; - } - private static byte[] Int16Bytes(short value) { byte[] bytes = new byte[2]; @@ -227,6 +197,16 @@ public sealed class SendProxyConcealedCarryPlugin : BasePlugin return bytes; } + private static void AddAssociationDisconnectRules(Dictionary desired, int recipientSlot, int weaponEntityIndex) + { + desired[new RuleKey(recipientSlot, weaponEntityIndex, EntityClass, "m_hOwnerEntity")] = InvalidHandle; + desired[new RuleKey(recipientSlot, weaponEntityIndex, EntityClass, "m_CBodyComponent.m_pSceneNode.m_hParent.m_hOwner")] = InvalidHandle; + desired[new RuleKey(recipientSlot, weaponEntityIndex, EntityClass, "m_CBodyComponent.m_pSceneNode.m_hParent.m_name")] = EmptyToken; + desired[new RuleKey(recipientSlot, weaponEntityIndex, EntityClass, "m_CBodyComponent.m_pSceneNode.m_nParentAttachmentOrBone")] = NoAttachment; + desired[new RuleKey(recipientSlot, weaponEntityIndex, EntityClass, "m_CBodyComponent.m_pSceneNode.m_hierarchyAttachName")] = EmptyToken; + desired[new RuleKey(recipientSlot, weaponEntityIndex, EntityClass, "m_CBodyComponent.m_pSceneNode.m_bForceParentToBeNetworked")] = FalseByte; + } + private static int ToEngineSlot(CCSPlayerController player) { return Math.Max(0, player.Slot - 1); diff --git a/src/detour.cpp b/src/detour.cpp index 7e4f2d0..1988ac1 100644 --- a/src/detour.cpp +++ b/src/detour.cpp @@ -26,8 +26,6 @@ static uint64_t g_packCalls = 0; static uint64_t g_packEntityCalls = 0; static uint64_t g_packEntityGenericSpoofs = 0; static uint64_t g_fullUpdateWrites = 0; -static uint64_t g_packEntitiesDebugLogs = 0; -static uint64_t g_packEntityRuleDebugLogs = 0; static int g_fullUpdateBudget = 0; static thread_local CPlayerSlot g_currentRecipient(-1); static thread_local CPlayerSlot g_lastSnapshotRecipient(-1); @@ -79,20 +77,6 @@ static void Detour_PackEntities(void* self, void* arg1, int arg2, void* arg3, vo { ++g_packCalls; CPlayerSlot recipient((arg2 >= 0 && arg2 < 64) ? arg2 : -1); - if (g_packEntitiesDebugLogs < 16) - { - SPMessage("pack_entities call %llu self=%p arg1=%p arg2=%d recipient=%d args=[%p %p %p %p]\n", - static_cast(g_packCalls), - self, - arg1, - arg2, - recipient.Get(), - arg3, - arg4, - arg5, - arg6); - ++g_packEntitiesDebugLogs; - } ScopedRecipient scopedRecipient(recipient); g_packEntities(self, arg1, arg2, arg3, arg4, arg5, arg6); } @@ -110,24 +94,6 @@ static void Detour_PackEntity(void* self, void* arg1, int entityIndex, void* ent CPlayerSlot recipient = g_currentRecipient; if (recipient.Get() < 0 && g_lastSnapshotRecipient.Get() >= 0) recipient = g_lastSnapshotRecipient; - if (g_packEntityRuleDebugLogs < 64 && g_overrides.HasRulesForEntity(entityIndex)) - { - SPMessage("pack_entity ruled call %llu entity=%d current=%d lastSnapshot=%d args self=%p arg1=%p data=%p arg4=%p arg5=%p arg6=%p arg7=%p arg8=%p arg9=%p\n", - static_cast(g_packEntityCalls), - entityIndex, - g_currentRecipient.Get(), - g_lastSnapshotRecipient.Get(), - self, - arg1, - entityData, - arg4, - arg5, - arg6, - arg7, - arg8, - arg9); - ++g_packEntityRuleDebugLogs; - } auto applied = g_overrides.ApplyForPackedEntity(recipient, entityIndex, entityData); g_packEntityGenericSpoofs += applied.size(); g_packEntity(self, arg1, entityIndex, entityData, arg4, arg5, arg6, arg7, arg8, arg9); diff --git a/src/overrides.cpp b/src/overrides.cpp index 747d283..8cf8a6a 100644 --- a/src/overrides.cpp +++ b/src/overrides.cpp @@ -214,29 +214,6 @@ static void ApplyVectorFirstFromField(const CompiledOverrideRule& rule, void* en constexpr uint32_t invalidHandle = 0xffffffff; const int32_t count = *reinterpret_cast(vectorAddress); auto* elements = *reinterpret_cast(vectorAddress + 8); - if (!rule.debugLogged) - { - uint32_t h0 = elements && count > 0 ? *reinterpret_cast(elements) : invalidHandle; - uint32_t h1 = elements && count > 1 ? *reinterpret_cast(elements + 4) : invalidHandle; - uint32_t h2 = elements && count > 2 ? *reinterpret_cast(elements + 8) : invalidHandle; - const auto* raw = reinterpret_cast(vectorAddress); - SPMessage("vector apply rule %d recipient=%d entity=%d vec=%p src=%p count=%d elems=%p active=%08x first=[%08x %08x %08x] raw=%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - rule.id, - rule.recipientSlot, - rule.entityIndex, - vectorAddress, - sourceAddress, - count, - elements, - sourceHandle, - h0, - h1, - h2, - raw[0], raw[1], raw[2], raw[3], raw[4], raw[5], raw[6], raw[7], - raw[8], raw[9], raw[10], raw[11], raw[12], raw[13], raw[14], raw[15], - raw[16], raw[17], raw[18], raw[19], raw[20], raw[21], raw[22], raw[23]); - rule.debugLogged = true; - } if (count < 0 || count > 128) return; @@ -323,19 +300,6 @@ int OverrideManager::AddRuleBytes(int recipientSlot, int entityIndex, const char auto* bytes = static_cast(value); rule.value.assign(bytes, bytes + valueSize); m_rules.push_back(rule); - if (rule.fieldPath.find("m_hMyWeapons") != std::string::npos) - { - SPMessage("rule %d recipient=%d entity=%d %s::%s size=%d valueSize=%d topOffset=%d steps=%zu\n", - rule.id, - rule.recipientSlot, - rule.entityIndex, - rule.className.c_str(), - rule.fieldPath.c_str(), - rule.size, - valueSize, - rule.offset, - rule.addressSteps.size()); - } RebuildIndex(); MarkEntityFullDirty(entityIndex); return rule.id; @@ -375,18 +339,6 @@ int OverrideManager::AddRuleVectorFirstFromField(int recipientSlot, int entityIn } m_rules.push_back(rule); - SPMessage("vector-first rule %d recipient=%d entity=%d %s::%s <- %s vectorSize=%d sourceSize=%d topOffset=%d steps=%zu sourceSteps=%zu\n", - rule.id, - rule.recipientSlot, - rule.entityIndex, - rule.className.c_str(), - rule.fieldPath.c_str(), - rule.sourceFieldPath.c_str(), - rule.size, - rule.sourceSize, - rule.offset, - rule.addressSteps.size(), - rule.sourceAddressSteps.size()); RebuildIndex(); MarkEntityFullDirty(entityIndex); return rule.id; @@ -443,18 +395,7 @@ std::vector OverrideManager::ApplyForPackedEntity(CPlayerSlot r } if ((effectiveRecipient < 0 || effectiveRecipient == 0 || effectiveRecipient == 1) && uniqueRuleRecipient >= 0) - { - static int fallbackLogs = 0; - if (fallbackLogs < 64) - { - SPMessage("entity=%d unresolved recipient current=%d using unique rule recipient=%d\n", - entityIndex, - effectiveRecipient, - uniqueRuleRecipient); - ++fallbackLogs; - } effectiveRecipient = uniqueRuleRecipient; - } for (size_t ruleIndex : found->second) { @@ -463,20 +404,7 @@ std::vector OverrideManager::ApplyForPackedEntity(CPlayerSlot r continue; if (rule.recipientSlot != -1 && rule.recipientSlot != effectiveRecipient) - { - if (!rule.recipientMismatchLogged) - { - SPMessage("rule %d entity=%d matched packed entity but skipped recipient rule=%d current=%d field=%s::%s\n", - rule.id, - entityIndex, - rule.recipientSlot, - effectiveRecipient, - rule.className.c_str(), - rule.fieldPath.c_str()); - rule.recipientMismatchLogged = true; - } continue; - } if (rule.kind == OverrideRuleKind::VectorFirstFromField) { diff --git a/src/overrides.h b/src/overrides.h index 665be16..da48739 100644 --- a/src/overrides.h +++ b/src/overrides.h @@ -41,8 +41,6 @@ struct CompiledOverrideRule std::vector value; OverrideRuleKind kind {OverrideRuleKind::Bytes}; bool enabled {true}; - mutable bool debugLogged {false}; - mutable bool recipientMismatchLogged {false}; }; class OverrideManager