From 14a38d4c5f19cf5f31e4b7c6477a5f7ed8595c28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordan=20Bri=C3=A8re?= Date: Fri, 14 Aug 2020 19:14:47 -0400 Subject: [PATCH 1/5] First pass on entity transmission filtering system. --- .../source-python/entities/transmit.py | 176 +++++++++++ src/CMakeLists.txt | 3 + .../modules/entities/entities_transmit.cpp | 283 ++++++++++++++++++ src/core/modules/entities/entities_transmit.h | 135 +++++++++ .../entities/entities_transmit_wrap.cpp | 168 +++++++++++ src/core/sp_main.cpp | 2 + 6 files changed, 767 insertions(+) create mode 100644 addons/source-python/packages/source-python/entities/transmit.py create mode 100644 src/core/modules/entities/entities_transmit.cpp create mode 100644 src/core/modules/entities/entities_transmit.h create mode 100644 src/core/modules/entities/entities_transmit_wrap.cpp diff --git a/addons/source-python/packages/source-python/entities/transmit.py b/addons/source-python/packages/source-python/entities/transmit.py new file mode 100644 index 000000000..1be7af53c --- /dev/null +++ b/addons/source-python/packages/source-python/entities/transmit.py @@ -0,0 +1,176 @@ +# ../entities/transmit.py + +"""Provides entity transmission filtering.""" + +# ============================================================================ +# >> IMPORTS +# ============================================================================ +# Source.Python +# Core +from core import AutoUnload +# Entities +from entities.entity import Entity +from entities.hooks import EntityCondition +# Filters +from filters.entities import EntityIter +# Listeners +from listeners import on_entity_created_listener_manager +from listeners import on_entity_deleted_listener_manager + + +# ============================================================================ +# >> FORWARD IMPORTS +# ============================================================================ +# Source.Python +# Entities +from _entities._transmit import BaseTransmitCriteria +from _entities._transmit import BaseTransmitFilter +from _entities._transmit import TransmitManager +from _entities._transmit import TransmitStates +from _entities._transmit import TransmitTarget +from _entities._transmit import TransmitType +from _entities._transmit import transmit_manager + + +# ============================================================================ +# >> ALL DECLARATION +# ============================================================================ +__all__ = [ + 'BaseTransmitCriteria', + 'BaseTransmitFilter', + 'TransmitCriteria', + 'TransmitFilter', + 'TransmitManager', + 'TransmitStates', + 'TransmitTarget', + 'TransmitType', + 'transmit_manager', +] + + +# ============================================================================ +# >> CLASSES +# ============================================================================ +class TransmitFilter(AutoUnload, BaseTransmitFilter): + """Decorator class used to register entity transmission filter.""" + + def __call__(self, callback): + """Register the given callback and initialize the filter. + + :param function callback: + The callback to register. + """ + self.callback = callback + self.initialize() + return self + + def initialize(self): + """Initializes the filter.""" + transmit_manager.register_filter(self) + + def _unload_instance(self): + """Unregister ourself as filter.""" + transmit_manager.unregister_filter(self) + + +class TransmitCriteria(AutoUnload, BaseTransmitCriteria): + """Class used to narrow down entity transmission filtering.""" + + def __init__(self, conditions, target=TransmitTarget.ENTITY): + """Initialize the criteria. + + :param function/iterable conditions: + Conditions that an entity have to meet in order to match this + criteria. + :param TransmitTarget target: + Whether the criteria is to be checked against the entity being + transmitted or the receiving player. + """ + super().__init__(target) + + # Validate and store the given conditions + if callable(conditions): + self.conditions = (conditions,) + else: + for condition in conditions: + if not callable(condition): + raise ValueError(f'"{condition}" is not callable.') + self.conditions = conditions + + # Let's test existing entities + for entity in EntityIter(): + self[entity.index] = self.test_entity(entity) + + # Register our internal listeners + on_entity_created_listener_manager.register_listener( + self._on_entity_created) + on_entity_deleted_listener_manager.register_listener( + self._on_entity_deleted) + + def test_entity(self, entity): + """Test whether the entity matches all the conditions. + + :param Entity entity:: + The entity to test against all conditions. + + :rtype: + bool + """ + for condition in self.conditions: + if not condition(entity): + return False + + return True + + def _on_entity_created(self, base_entity): + """Called when an entity is created. + + :param BaseEntity base_entity: + The entity that was created. + """ + # Try to grab an index or exit if the entity isn't networked + try: + entity = Entity(base_entity.index) + except ValueError: + return + + # Test the entity and set the result + self[entity.index] = self.test_entity(entity) + + def _on_entity_deleted(self, base_entity): + """Called when an entity is being deleted. + + :param BaseEntity base_entity: + The entity that is being deleted. + """ + # Try to grab an index or exit if the entity isn't networked + try: + entity_index = base_entity.index + except ValueError: + return + + # Mark the entity as no longer matching + del self[entity_index] + + def _unload_instance(self): + """Unregister our internal listeners.""" + self.listener.unregister_listener(self._on_entity_created) + on_entity_deleted_listener_manager.unregister_listener( + self._on_entity_deleted) + + +# For convenience, register some commonly used criterias +TransmitCriteria.is_player = TransmitCriteria( + EntityCondition.is_player) +TransmitCriteria.is_not_player = TransmitCriteria( + EntityCondition.is_not_player) +TransmitCriteria.is_human_player = TransmitCriteria( + EntityCondition.is_human_player) +TransmitCriteria.is_bot_player = TransmitCriteria( + EntityCondition.is_bot_player) +TransmitCriteria.equals_entity_classname = ( + lambda *classnames: TransmitCriteria( + EntityCondition.equals_entity_classname(*classnames))) +TransmitCriteria.equals_entity_classname = ( + lambda *classnames: TransmitCriteria( + EntityCondition.equals_entity_classname(*classnames))) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6df2fd77..19a9d12f7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -222,6 +222,7 @@ Set(SOURCEPYTHON_ENTITIES_MODULE_HEADERS core/modules/entities/${SOURCE_ENGINE}/entities_props_wrap.h core/modules/entities/${SOURCE_ENGINE}/entities_constants_wrap.h core/modules/entities/entities_entity.h + core/modules/entities/entities_transmit.h ) Set(SOURCEPYTHON_ENTITIES_MODULE_SOURCES @@ -238,6 +239,8 @@ Set(SOURCEPYTHON_ENTITIES_MODULE_SOURCES core/modules/entities/entities_props_wrap.cpp core/modules/entities/entities_entity.cpp core/modules/entities/entities_entity_wrap.cpp + core/modules/entities/entities_transmit.cpp + core/modules/entities/entities_transmit_wrap.cpp ) # ------------------------------------------------------------------ diff --git a/src/core/modules/entities/entities_transmit.cpp b/src/core/modules/entities/entities_transmit.cpp new file mode 100644 index 000000000..35897c012 --- /dev/null +++ b/src/core/modules/entities/entities_transmit.cpp @@ -0,0 +1,283 @@ +/** +* ============================================================================= +* Source Python +* Copyright (C) 2012-2020 Source Python Development Team. All rights reserved. +* ============================================================================= +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU General Public License, version 3.0, as published by the +* Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +* details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see . +* +* As a special exception, the Source Python Team gives you permission +* to link the code of this program (as well as its derivative works) to +* "Half-Life 2," the "Source Engine," and any Game MODs that run on software +* by the Valve Corporation. You must obey the GNU General Public License in +* all respects for all other code used. Additionally, the Source.Python +* Development Team grants this exception to all derivative works. +*/ + +//----------------------------------------------------------------------------- +// Includes. +//----------------------------------------------------------------------------- +#include "eiface.h" + +#include "utilities/conversions.h" +#include "modules/entities/entities_transmit.h" +#include "modules/memory/memory_pointer.h" +#include "modules/memory/memory_function_info.h" + + +//----------------------------------------------------------------------------- +// Eternal variables. +//----------------------------------------------------------------------------- +extern IServerGameEnts *gameents; + + +//----------------------------------------------------------------------------- +// CBaseTransmitCriteria class. +//----------------------------------------------------------------------------- +CBaseTransmitCriteria::CBaseTransmitCriteria(ETransmitTarget eTarget) +{ + m_eTarget = eTarget; +} + + +//----------------------------------------------------------------------------- +// CBaseTransmitFilter class. +//----------------------------------------------------------------------------- +CBaseTransmitFilter::CBaseTransmitFilter(ETransmitType eType, CBaseTransmitCriteria *pCriteria, object oOverride): + m_oCallback(object()), + m_bHasOverride(false) +{ + m_eType = eType; + m_pCriteria = pCriteria; + + set_override(oOverride); +} + + +object CBaseTransmitFilter::get_callback() +{ + return m_oCallback; +} + +void CBaseTransmitFilter::set_callback(object oCallback) +{ + if (!oCallback.is_none() && !PyCallable_Check(oCallback.ptr())) + BOOST_RAISE_EXCEPTION( + PyExc_TypeError, + "The given function is not callable." + ); + + m_oCallback = oCallback; +} + + +bool CBaseTransmitFilter::get_override() +{ + return m_bOverride; +} + +void CBaseTransmitFilter::set_override(object oOverride) +{ + if (oOverride.is_none()) + { + m_bOverride = oOverride; + m_bHasOverride = false; + } + else + { + extract extract_override(oOverride); + if (!extract_override.check()) + BOOST_RAISE_EXCEPTION( + PyExc_TypeError, + "The given override couldn't be evaluated as a boolean." + ); + + m_bOverride = extract_override(); + m_bHasOverride = true; + } +} + +bool CBaseTransmitFilter::has_override() +{ + return m_bHasOverride; +} + + +//----------------------------------------------------------------------------- +// CTransmitManager class. +//----------------------------------------------------------------------------- +CTransmitManager::CTransmitManager(): + m_bInitialized(false) +{ +} + +CTransmitManager *CTransmitManager::GetSingleton() +{ + static CTransmitManager *s_pManager = new CTransmitManager; + return s_pManager; +} + + +void CTransmitManager::initialize() +{ + if (m_bInitialized) + return; + + CFunctionInfo *pInfo = GetFunctionInfo(&IServerGameEnts::CheckTransmit); + if (!pInfo) + BOOST_RAISE_EXCEPTION( + PyExc_ValueError, + "Failed to retrieve CheckTransmit's info." + ) + + CFunction *pFunc = CPointer((unsigned long)((void *)gameents)).MakeVirtualFunction(*pInfo); + delete pInfo; + + if (!pFunc || !pFunc->IsHookable()) + BOOST_RAISE_EXCEPTION( + PyExc_ValueError, + "CheckTransmit is invalid or not hookable." + ) + + void *pAddr = (void *)pFunc->m_ulAddr; + CHook *pHook = GetHookManager()->FindHook(pAddr); + if (!pHook) + { + pHook = GetHookManager()->HookFunction(pAddr, pFunc->m_pCallingConvention); + if (!pHook) + BOOST_RAISE_EXCEPTION( + PyExc_ValueError, + "Failed to hook CheckTransmit." + ) + } + + delete pFunc; + pHook->AddCallback( + HOOKTYPE_POST, + (HookHandlerFn *)&CTransmitManager::_post_check_transmit + ); + + m_bInitialized = true; +} + + +void CTransmitManager::register_filter(CBaseTransmitFilter *pFilter) +{ + if (m_vecFilters.HasElement(pFilter)) + BOOST_RAISE_EXCEPTION( + PyExc_ValueError, + "The given filter is already registered." + ); + + initialize(); + m_vecFilters.AddToTail(pFilter); +} + +void CTransmitManager::unregister_filter(CBaseTransmitFilter *pFilter) +{ + m_vecFilters.FindAndRemove(pFilter); +} + + +bool CTransmitManager::handle_filters(ETransmitType eType, int iIndex, unsigned int uiPlayer) +{ + static object Entity = import("entities.entity").attr("Entity"); + object entity = Entity(iIndex); + + static object Player = import("players.entity").attr("Player"); + object player = Player(uiPlayer); + + for (int i=0;i < m_vecFilters.Count();i++) + { + CBaseTransmitFilter *pFilter = m_vecFilters[i]; + + if (pFilter->m_eType != eType) + continue; + + if (pFilter->m_pCriteria) + { + switch (pFilter->m_pCriteria->m_eTarget) + { + case TRANSMIT_TARGET_ENTITY: + { + if (!pFilter->m_pCriteria->IsBitSet(iIndex)) + continue; + break; + } + case TRANSMIT_TARGET_PLAYER: + { + if (!pFilter->m_pCriteria->IsBitSet((int)uiPlayer)) + continue; + break; + } + default: + continue; + } + } + + if (pFilter->has_override()) + return pFilter->get_override(); + + object callback = pFilter->get_callback(); + if (!callback.is_none() && callback(entity, player)) + return true; + } + + return false; +} + + +bool CTransmitManager::_post_check_transmit(HookType_t eHookType, CHook *pHook) +{ + static CTransmitManager *pManager = GetTransmitManager(); + if (!pManager->m_vecFilters.Count()) + return false; + + int nEdicts = pHook->GetArgument(3); + if (!nEdicts) + return false; + + CCheckTransmitInfo *pInfo = pHook->GetArgument(1); + + unsigned int uiIndex; + if (!IndexFromEdict(pInfo->m_pClientEnt, uiIndex)) + return false; + + static object Player = import("players.entity").attr("Player"); + object player = Player(uiIndex); + + unsigned short *pIndexes = pHook->GetArgument(2); + + for (int i=0; i < nEdicts; i++) + { + BEGIN_BOOST_PY() + int iIndex = pIndexes[i]; + if (iIndex == WORLD_ENTITY_INDEX) + continue; + + unsigned int uiPlayer; + IndexFromEdict(pInfo->m_pClientEnt, uiPlayer); + + if (uiPlayer == iIndex) + continue; + + ETransmitType eType = pInfo->m_pTransmitEdict->IsBitSet(iIndex) ? TRANSMIT_OUT : TRANSMIT_IN; + if (!pManager->handle_filters(eType, iIndex, uiPlayer)) + continue; + + pInfo->m_pTransmitEdict->Set(iIndex, !pInfo->m_pTransmitEdict->Get(iIndex)); + END_BOOST_PY_NORET() + } + + return false; +} diff --git a/src/core/modules/entities/entities_transmit.h b/src/core/modules/entities/entities_transmit.h new file mode 100644 index 000000000..9b62216c8 --- /dev/null +++ b/src/core/modules/entities/entities_transmit.h @@ -0,0 +1,135 @@ +/** +* ============================================================================= +* Source Python +* Copyright (C) 2012-2020 Source Python Development Team. All rights reserved. +* ============================================================================= +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU General Public License, version 3.0, as published by the +* Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +* details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see . +* +* As a special exception, the Source Python Team gives you permission +* to link the code of this program (as well as its derivative works) to +* "Half-Life 2," the "Source Engine," and any Game MODs that run on software +* by the Valve Corporation. You must obey the GNU General Public License in +* all respects for all other code used. Additionally, the Source.Python +* Development Team grants this exception to all derivative works. +*/ + +#ifndef _ENTITIES_TRANSMIT_H +#define _ENTITIES_TRANSMIT_H + +//----------------------------------------------------------------------------- +// Includes. +//----------------------------------------------------------------------------- +#include "public/const.h" +#include "public/bitvec.h" +#include "public/tier1/utlvector.h" + +#include "modules/listeners/listeners_manager.h" +#include "modules/memory/memory_function.h" + + +//----------------------------------------------------------------------------- +// TransmitStates_t definition. +//----------------------------------------------------------------------------- +typedef CBitVec TransmitStates_t; + + +//----------------------------------------------------------------------------- +// ETransmitTarget enumeration. +//----------------------------------------------------------------------------- +enum ETransmitTarget +{ + TRANSMIT_TARGET_ENTITY, + TRANSMIT_TARGET_PLAYER +}; + + +//----------------------------------------------------------------------------- +// CBaseTransmitCriteria class. +//----------------------------------------------------------------------------- +class CBaseTransmitCriteria: public TransmitStates_t +{ +public: + CBaseTransmitCriteria(ETransmitTarget eTarget = TRANSMIT_TARGET_ENTITY); + +public: + ETransmitTarget m_eTarget; +}; + + +//----------------------------------------------------------------------------- +// ETransmitType enumeration. +//----------------------------------------------------------------------------- +enum ETransmitType +{ + TRANSMIT_IN, + TRANSMIT_OUT +}; + + +//----------------------------------------------------------------------------- +// CBaseTransmitFilter class. +//----------------------------------------------------------------------------- +class CBaseTransmitFilter +{ +public: + CBaseTransmitFilter(ETransmitType eType = TRANSMIT_OUT, CBaseTransmitCriteria *pCriteria = NULL, object oOverride = object()); + +public: + bool get_override(); + void set_override(object oOverride); + bool has_override(); + + object get_callback(); + void set_callback(object oCallback); + +private: + bool m_bOverride; + bool m_bHasOverride; + + object m_oCallback; + +public: + ETransmitType m_eType; + CBaseTransmitCriteria *m_pCriteria; +}; + + +//----------------------------------------------------------------------------- +// CTransmitManager class. +//----------------------------------------------------------------------------- +class CTransmitManager +{ +private: + CTransmitManager(); + +private: + void initialize(); + static bool _post_check_transmit(HookType_t eHookType, CHook *pHook); + bool handle_filters(ETransmitType eType, int iIndex, unsigned int uiPlayer); + +public: + static CTransmitManager *GetSingleton(); + + void register_filter(CBaseTransmitFilter *pFilter); + void unregister_filter(CBaseTransmitFilter *pFilter); + +private: + bool m_bInitialized; + CUtlVector m_vecFilters; +}; + +inline CTransmitManager *GetTransmitManager() { return CTransmitManager::GetSingleton(); } + + +#endif // _ENTITIES_TRANSMIT_H diff --git a/src/core/modules/entities/entities_transmit_wrap.cpp b/src/core/modules/entities/entities_transmit_wrap.cpp new file mode 100644 index 000000000..d50ff0f38 --- /dev/null +++ b/src/core/modules/entities/entities_transmit_wrap.cpp @@ -0,0 +1,168 @@ +/** +* ============================================================================= +* Source Python +* Copyright (C) 2012-2020 Source Python Development Team. All rights reserved. +* ============================================================================= +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU General Public License, version 3.0, as published by the +* Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +* details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see . +* +* As a special exception, the Source Python Team gives you permission +* to link the code of this program (as well as its derivative works) to +* "Half-Life 2," the "Source Engine," and any Game MODs that run on software +* by the Valve Corporation. You must obey the GNU General Public License in +* all respects for all other code used. Additionally, the Source.Python +* Development Team grants this exception to all derivative works. +*/ + +//----------------------------------------------------------------------------- +// Includes. +//----------------------------------------------------------------------------- +#include "export_main.h" +#include "utilities/wrap_macros.h" +#include "modules/entities/entities_transmit.h" +#include "modules/memory/memory_tools.h" + + +//----------------------------------------------------------------------------- +// Forward declarations. +//----------------------------------------------------------------------------- +static void export_transmit_states(scope); +static void export_transmit_target(scope); +static void export_transmit_type(scope); +static void export_base_transmit_criteria(scope); +static void export_base_transmit_filter(scope); +static void export_transmit_manager(scope); + + +//----------------------------------------------------------------------------- +// Declare the _entities._transmit module. +//----------------------------------------------------------------------------- +DECLARE_SP_SUBMODULE(_entities, _transmit) +{ + export_transmit_states(_transmit); + export_transmit_target(_transmit); + export_transmit_type(_transmit); + export_base_transmit_criteria(_transmit); + export_base_transmit_filter(_transmit); + export_transmit_manager(_transmit); +} + + +//----------------------------------------------------------------------------- +// Exports TransmitStates_t. +//----------------------------------------------------------------------------- +void export_transmit_states(scope _transmit) +{ + class_ TransmitStates("TransmitStates"); + + // Special methods... + TransmitStates.def("__delitem__", GET_METHOD(void, TransmitStates_t, Clear, int)); + TransmitStates.def("__getitem__", &TransmitStates_t::IsBitSet); + TransmitStates.def("__setitem__", GET_METHOD(void, TransmitStates_t, Set, int, bool)); + + // Add memory tools... + TransmitStates ADD_MEM_TOOLS(TransmitStates_t); +} + + +//----------------------------------------------------------------------------- +// Exports ETransmitTarget. +//----------------------------------------------------------------------------- +void export_transmit_target(scope _transmit) +{ + enum_ TransmitTarget("TransmitTarget"); + + // Values... + TransmitTarget.value("ENTITY", TRANSMIT_TARGET_ENTITY); + TransmitTarget.value("PLAYER", TRANSMIT_TARGET_PLAYER); +} + + +//----------------------------------------------------------------------------- +// Exports ETransmitType. +//----------------------------------------------------------------------------- +void export_transmit_type(scope _transmit) +{ + enum_ TransmitType("TransmitType"); + + // Values... + TransmitType.value("IN", TRANSMIT_IN); + TransmitType.value("OUT", TRANSMIT_OUT); +} + + +//----------------------------------------------------------------------------- +// Exports CBaseTransmitCriteria. +//----------------------------------------------------------------------------- +void export_base_transmit_criteria(scope _transmit) +{ + class_ > BaseTransmitCriteria( + "BaseTransmitCriteria", + init( + ( + arg("self"), arg("target")=TRANSMIT_TARGET_ENTITY + ) + ) + ); + + // Properties... + BaseTransmitCriteria.def_readwrite("target", &CBaseTransmitCriteria::m_eTarget); + + // Add memory tools... + BaseTransmitCriteria ADD_MEM_TOOLS(CBaseTransmitCriteria); +} + + +//----------------------------------------------------------------------------- +// Exports CBaseTransmitFilter. +//----------------------------------------------------------------------------- +void export_base_transmit_filter(scope _transmit) +{ + class_ BaseTransmitFilter( + "BaseTransmitFilter", + init( + ( + arg("self"), arg("type")=TRANSMIT_OUT, arg("criteria")=object(), arg("override")=object() + ) + ) + ); + + // Properties... + BaseTransmitFilter.def_readwrite("type", &CBaseTransmitFilter::m_eType); + BaseTransmitFilter.def_readwrite("criteria", &CBaseTransmitFilter::m_pCriteria); + BaseTransmitFilter.add_property("override", &CBaseTransmitFilter::get_override, &CBaseTransmitFilter::set_override); + BaseTransmitFilter.add_property("callback", &CBaseTransmitFilter::get_callback, &CBaseTransmitFilter::set_callback); + + // Add memory tools... + BaseTransmitFilter ADD_MEM_TOOLS(CBaseTransmitFilter); +} + + +//----------------------------------------------------------------------------- +// Exports CTransmitManager. +//----------------------------------------------------------------------------- +void export_transmit_manager(scope _transmit) +{ + class_ TransmitManager("TransmitManager", no_init); + + // Methods... + TransmitManager.def("register_filter", &CTransmitManager::register_filter); + TransmitManager.def("unregister_filter", &CTransmitManager::unregister_filter); + + // Add memory tools... + TransmitManager ADD_MEM_TOOLS(CTransmitManager); + + // Singleton... + _transmit.attr("transmit_manager") = object(ptr(GetTransmitManager())); +} + diff --git a/src/core/sp_main.cpp b/src/core/sp_main.cpp index 2e582c3fa..d1f237c66 100644 --- a/src/core/sp_main.cpp +++ b/src/core/sp_main.cpp @@ -91,6 +91,7 @@ IEngineSound* enginesound = NULL; CGlobalVars* gpGlobals = NULL; IFileSystem* filesystem = NULL; IServerGameDLL* servergamedll = NULL; +IServerGameEnts* gameents = NULL; // Interface to get at server entities IServerTools* servertools = NULL; IPhysics* physics = NULL; IPhysicsCollision* physcollision = NULL; @@ -151,6 +152,7 @@ InterfaceHelper_t gGameInterfaces[] = { {INTERFACEVERSION_PLAYERINFOMANAGER, (void **)&playerinfomanager}, {INTERFACEVERSION_PLAYERBOTMANAGER, (void **)&botmanager}, {INTERFACEVERSION_SERVERGAMEDLL, (void **)&servergamedll}, + {INTERFACEVERSION_SERVERGAMEENTS, (void **)&gameents}, {VSERVERTOOLS_INTERFACE_VERSION, (void **)&servertools}, {NULL, NULL} }; From d739f6e1b906c078a78b1b106df9224f9baefb96 Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Tue, 25 Aug 2020 05:23:04 +0900 Subject: [PATCH 2/5] Entity transmission alternative. --- .../source-python/entities/transmit.py | 140 +- .../modules/entities/entities_transmit.cpp | 299 ++-- src/core/modules/entities/entities_transmit.h | 103 +- .../entities/entities_transmit_wrap.cpp | 147 +- src/patches/csgo/public/bitvec.h | 1417 +++++++++++++++++ 5 files changed, 1662 insertions(+), 444 deletions(-) mode change 100644 => 100755 addons/source-python/packages/source-python/entities/transmit.py mode change 100644 => 100755 src/core/modules/entities/entities_transmit.cpp mode change 100644 => 100755 src/core/modules/entities/entities_transmit.h mode change 100644 => 100755 src/core/modules/entities/entities_transmit_wrap.cpp create mode 100755 src/patches/csgo/public/bitvec.h diff --git a/addons/source-python/packages/source-python/entities/transmit.py b/addons/source-python/packages/source-python/entities/transmit.py old mode 100644 new mode 100755 index 1be7af53c..e79237a22 --- a/addons/source-python/packages/source-python/entities/transmit.py +++ b/addons/source-python/packages/source-python/entities/transmit.py @@ -23,154 +23,18 @@ # ============================================================================ # Source.Python # Entities -from _entities._transmit import BaseTransmitCriteria -from _entities._transmit import BaseTransmitFilter -from _entities._transmit import TransmitManager -from _entities._transmit import TransmitStates -from _entities._transmit import TransmitTarget -from _entities._transmit import TransmitType from _entities._transmit import transmit_manager # ============================================================================ # >> ALL DECLARATION # ============================================================================ -__all__ = [ - 'BaseTransmitCriteria', - 'BaseTransmitFilter', - 'TransmitCriteria', - 'TransmitFilter', - 'TransmitManager', - 'TransmitStates', - 'TransmitTarget', - 'TransmitType', +__all__ = ( 'transmit_manager', -] +) # ============================================================================ # >> CLASSES # ============================================================================ -class TransmitFilter(AutoUnload, BaseTransmitFilter): - """Decorator class used to register entity transmission filter.""" - def __call__(self, callback): - """Register the given callback and initialize the filter. - - :param function callback: - The callback to register. - """ - self.callback = callback - self.initialize() - return self - - def initialize(self): - """Initializes the filter.""" - transmit_manager.register_filter(self) - - def _unload_instance(self): - """Unregister ourself as filter.""" - transmit_manager.unregister_filter(self) - - -class TransmitCriteria(AutoUnload, BaseTransmitCriteria): - """Class used to narrow down entity transmission filtering.""" - - def __init__(self, conditions, target=TransmitTarget.ENTITY): - """Initialize the criteria. - - :param function/iterable conditions: - Conditions that an entity have to meet in order to match this - criteria. - :param TransmitTarget target: - Whether the criteria is to be checked against the entity being - transmitted or the receiving player. - """ - super().__init__(target) - - # Validate and store the given conditions - if callable(conditions): - self.conditions = (conditions,) - else: - for condition in conditions: - if not callable(condition): - raise ValueError(f'"{condition}" is not callable.') - self.conditions = conditions - - # Let's test existing entities - for entity in EntityIter(): - self[entity.index] = self.test_entity(entity) - - # Register our internal listeners - on_entity_created_listener_manager.register_listener( - self._on_entity_created) - on_entity_deleted_listener_manager.register_listener( - self._on_entity_deleted) - - def test_entity(self, entity): - """Test whether the entity matches all the conditions. - - :param Entity entity:: - The entity to test against all conditions. - - :rtype: - bool - """ - for condition in self.conditions: - if not condition(entity): - return False - - return True - - def _on_entity_created(self, base_entity): - """Called when an entity is created. - - :param BaseEntity base_entity: - The entity that was created. - """ - # Try to grab an index or exit if the entity isn't networked - try: - entity = Entity(base_entity.index) - except ValueError: - return - - # Test the entity and set the result - self[entity.index] = self.test_entity(entity) - - def _on_entity_deleted(self, base_entity): - """Called when an entity is being deleted. - - :param BaseEntity base_entity: - The entity that is being deleted. - """ - # Try to grab an index or exit if the entity isn't networked - try: - entity_index = base_entity.index - except ValueError: - return - - # Mark the entity as no longer matching - del self[entity_index] - - def _unload_instance(self): - """Unregister our internal listeners.""" - self.listener.unregister_listener(self._on_entity_created) - on_entity_deleted_listener_manager.unregister_listener( - self._on_entity_deleted) - - -# For convenience, register some commonly used criterias -TransmitCriteria.is_player = TransmitCriteria( - EntityCondition.is_player) -TransmitCriteria.is_not_player = TransmitCriteria( - EntityCondition.is_not_player) -TransmitCriteria.is_human_player = TransmitCriteria( - EntityCondition.is_human_player) -TransmitCriteria.is_bot_player = TransmitCriteria( - EntityCondition.is_bot_player) -TransmitCriteria.equals_entity_classname = ( - lambda *classnames: TransmitCriteria( - EntityCondition.equals_entity_classname(*classnames))) -TransmitCriteria.equals_entity_classname = ( - lambda *classnames: TransmitCriteria( - EntityCondition.equals_entity_classname(*classnames))) diff --git a/src/core/modules/entities/entities_transmit.cpp b/src/core/modules/entities/entities_transmit.cpp old mode 100644 new mode 100755 index 35897c012..ff7d1fedd --- a/src/core/modules/entities/entities_transmit.cpp +++ b/src/core/modules/entities/entities_transmit.cpp @@ -42,97 +42,51 @@ extern IServerGameEnts *gameents; //----------------------------------------------------------------------------- -// CBaseTransmitCriteria class. +// Static variables. //----------------------------------------------------------------------------- -CBaseTransmitCriteria::CBaseTransmitCriteria(ETransmitTarget eTarget) -{ - m_eTarget = eTarget; -} +std::once_flag CTransmitManager::init_flag; +CTransmitManager* CTransmitManager::instance = nullptr; //----------------------------------------------------------------------------- -// CBaseTransmitFilter class. +// CTransmitManager class. //----------------------------------------------------------------------------- -CBaseTransmitFilter::CBaseTransmitFilter(ETransmitType eType, CBaseTransmitCriteria *pCriteria, object oOverride): - m_oCallback(object()), - m_bHasOverride(false) +CTransmitManager::CTransmitManager() { - m_eType = eType; - m_pCriteria = pCriteria; + initialize(); - set_override(oOverride); + for( auto& filters: m_vecFilters) + { + filters.first.SetAll(); + } } -object CBaseTransmitFilter::get_callback() +CTransmitManager* CTransmitManager::get_instance() { - return m_oCallback; -} - -void CBaseTransmitFilter::set_callback(object oCallback) -{ - if (!oCallback.is_none() && !PyCallable_Check(oCallback.ptr())) - BOOST_RAISE_EXCEPTION( - PyExc_TypeError, - "The given function is not callable." - ); - - m_oCallback = oCallback; + std::call_once(init_flag, create); + return instance; } -bool CBaseTransmitFilter::get_override() +void CTransmitManager::create() { - return m_bOverride; + instance = new CTransmitManager; } -void CBaseTransmitFilter::set_override(object oOverride) -{ - if (oOverride.is_none()) - { - m_bOverride = oOverride; - m_bHasOverride = false; - } - else - { - extract extract_override(oOverride); - if (!extract_override.check()) - BOOST_RAISE_EXCEPTION( - PyExc_TypeError, - "The given override couldn't be evaluated as a boolean." - ); - - m_bOverride = extract_override(); - m_bHasOverride = true; - } -} -bool CBaseTransmitFilter::has_override() +void CTransmitManager::destroy() { - return m_bHasOverride; -} - + if(instance) + instance->finalize(); -//----------------------------------------------------------------------------- -// CTransmitManager class. -//----------------------------------------------------------------------------- -CTransmitManager::CTransmitManager(): - m_bInitialized(false) -{ -} - -CTransmitManager *CTransmitManager::GetSingleton() -{ - static CTransmitManager *s_pManager = new CTransmitManager; - return s_pManager; + delete instance; + instance = nullptr; } void CTransmitManager::initialize() { - if (m_bInitialized) - return; - CFunctionInfo *pInfo = GetFunctionInfo(&IServerGameEnts::CheckTransmit); if (!pInfo) BOOST_RAISE_EXCEPTION( @@ -149,11 +103,11 @@ void CTransmitManager::initialize() "CheckTransmit is invalid or not hookable." ) - void *pAddr = (void *)pFunc->m_ulAddr; - CHook *pHook = GetHookManager()->FindHook(pAddr); + m_pCheckTransmit = (void *)pFunc->m_ulAddr; + CHook *pHook = GetHookManager()->FindHook(m_pCheckTransmit); if (!pHook) { - pHook = GetHookManager()->HookFunction(pAddr, pFunc->m_pCallingConvention); + pHook = GetHookManager()->HookFunction(m_pCheckTransmit, pFunc->m_pCallingConvention); if (!pHook) BOOST_RAISE_EXCEPTION( PyExc_ValueError, @@ -161,123 +115,174 @@ void CTransmitManager::initialize() ) } + pFunc->m_bAllocatedCallingConvention = false; delete pFunc; + pHook->AddCallback( HOOKTYPE_POST, (HookHandlerFn *)&CTransmitManager::_post_check_transmit ); - - m_bInitialized = true; } -void CTransmitManager::register_filter(CBaseTransmitFilter *pFilter) +void CTransmitManager::finalize() { - if (m_vecFilters.HasElement(pFilter)) - BOOST_RAISE_EXCEPTION( - PyExc_ValueError, - "The given filter is already registered." + CHook *pHook = GetHookManager()->FindHook(m_pCheckTransmit); + if (pHook) + { + pHook->RemoveCallback( + HOOKTYPE_POST, + (HookHandlerFn *)&CTransmitManager::_post_check_transmit ); + } +} - initialize(); - m_vecFilters.AddToTail(pFilter); + +void CTransmitManager::hide(int entity_index) +{ + if (entity_index == 0) + return; + + for(int i = 0; i < m_vecFilters.size(); ++i) + { + if ((i+1) == entity_index) + continue; + + filter_pair& filters = m_vecFilters[i]; + + filters.first.Set(entity_index, false); + filters.second.Set(entity_index, false); + } +} + + +void CTransmitManager::hide_from(int entity_index, int player_index) +{ + if (entity_index == 0) + return; + + player_index -= 1; + + if (entity_index == player_index) + return; + + filter_pair& filters = m_vecFilters[player_index]; + + filters.first.Set(entity_index, false); + filters.second.Set(entity_index, false); } -void CTransmitManager::unregister_filter(CBaseTransmitFilter *pFilter) + +void CTransmitManager::unhide(int entity_index) { - m_vecFilters.FindAndRemove(pFilter); + for( auto& filters: m_vecFilters) + { + filters.first.Set(entity_index, true); + filters.second.Set(entity_index, true); + } } -bool CTransmitManager::handle_filters(ETransmitType eType, int iIndex, unsigned int uiPlayer) +void CTransmitManager::unhide_from(int entity_index, int player_index) { - static object Entity = import("entities.entity").attr("Entity"); - object entity = Entity(iIndex); + player_index -= 1; + + filter_pair& filters = m_vecFilters[player_index]; + + filters.first.Set(entity_index, true); + filters.second.Set(entity_index, true); +} - static object Player = import("players.entity").attr("Player"); - object player = Player(uiPlayer); - for (int i=0;i < m_vecFilters.Count();i++) +void CTransmitManager::reset(int entity_index) +{ + for( auto& filters: m_vecFilters) { - CBaseTransmitFilter *pFilter = m_vecFilters[i]; + filters.first.Set(entity_index, true); + filters.second.Set(entity_index, false); + } +} - if (pFilter->m_eType != eType) - continue; - if (pFilter->m_pCriteria) - { - switch (pFilter->m_pCriteria->m_eTarget) - { - case TRANSMIT_TARGET_ENTITY: - { - if (!pFilter->m_pCriteria->IsBitSet(iIndex)) - continue; - break; - } - case TRANSMIT_TARGET_PLAYER: - { - if (!pFilter->m_pCriteria->IsBitSet((int)uiPlayer)) - continue; - break; - } - default: - continue; - } - } - - if (pFilter->has_override()) - return pFilter->get_override(); - - object callback = pFilter->get_callback(); - if (!callback.is_none() && callback(entity, player)) - return true; +void CTransmitManager::reset_from(int entity_index, int player_index) +{ + player_index -= 1; + m_vecFilters[player_index].first.Set(entity_index, true); + m_vecFilters[player_index].second.Set(entity_index, false); +} + + +void CTransmitManager::reset_all() +{ + for( auto& filters: m_vecFilters) + { + filters.first.SetAll(); + filters.second.ClearAll(); } +} - return false; + +bool CTransmitManager::is_hidden(int entity_index) +{ + bool hidden_state = false; + + for( auto& filters: m_vecFilters) + { + hidden_state |= (!filters.first.IsBitSet(entity_index)); + } + + return hidden_state; } -bool CTransmitManager::_post_check_transmit(HookType_t eHookType, CHook *pHook) +bool CTransmitManager::is_hidden_from(int entity_index, int player_index) { - static CTransmitManager *pManager = GetTransmitManager(); - if (!pManager->m_vecFilters.Count()) - return false; + player_index -= 1; - int nEdicts = pHook->GetArgument(3); - if (!nEdicts) - return false; + return (!m_vecFilters[player_index].first.IsBitSet(entity_index)); +} - CCheckTransmitInfo *pInfo = pHook->GetArgument(1); - unsigned int uiIndex; - if (!IndexFromEdict(pInfo->m_pClientEnt, uiIndex)) - return false; +tuple CTransmitManager::get_hidden_states(int entity_index) +{ + list player_list; - static object Player = import("players.entity").attr("Player"); - object player = Player(uiIndex); + for(int i = 0; i < m_vecFilters.size(); ++i) + { + if (!m_vecFilters[i].first.IsBitSet(entity_index)) + player_list.append(i+1); + } - unsigned short *pIndexes = pHook->GetArgument(2); + return tuple(player_list); +} - for (int i=0; i < nEdicts; i++) - { - BEGIN_BOOST_PY() - int iIndex = pIndexes[i]; - if (iIndex == WORLD_ENTITY_INDEX) - continue; - unsigned int uiPlayer; - IndexFromEdict(pInfo->m_pClientEnt, uiPlayer); +void CTransmitManager::handle_filters(CCheckTransmitInfo* pInfo, unsigned int player_index) +{ + player_index -= 1; - if (uiPlayer == iIndex) - continue; + TransmitStates_t* transmit_edict = pInfo->m_pTransmitEdict; + filter_pair& filters = m_vecFilters[player_index]; - ETransmitType eType = pInfo->m_pTransmitEdict->IsBitSet(iIndex) ? TRANSMIT_OUT : TRANSMIT_IN; - if (!pManager->handle_filters(eType, iIndex, uiPlayer)) - continue; + transmit_edict->And(filters.first, transmit_edict); + transmit_edict->Or(filters.second, transmit_edict); +} - pInfo->m_pTransmitEdict->Set(iIndex, !pInfo->m_pTransmitEdict->Get(iIndex)); - END_BOOST_PY_NORET() - } + +bool CTransmitManager::_post_check_transmit(HookType_t eHookType, CHook* pHook) +{ + int nEdicts = pHook->GetArgument(3); + if (!nEdicts) + return false; + + CCheckTransmitInfo* pInfo = pHook->GetArgument(1); + + unsigned int player_index; + if (!IndexFromEdict(pInfo->m_pClientEnt, player_index)) + return false; + + instance->handle_filters(pInfo, player_index); return false; } + diff --git a/src/core/modules/entities/entities_transmit.h b/src/core/modules/entities/entities_transmit.h old mode 100644 new mode 100755 index 9b62216c8..626d04457 --- a/src/core/modules/entities/entities_transmit.h +++ b/src/core/modules/entities/entities_transmit.h @@ -30,13 +30,23 @@ //----------------------------------------------------------------------------- // Includes. //----------------------------------------------------------------------------- +#include +#include +#include + #include "public/const.h" #include "public/bitvec.h" #include "public/tier1/utlvector.h" +#include "utilities/baseentity.h" + #include "modules/listeners/listeners_manager.h" #include "modules/memory/memory_function.h" +// Boost.Python +#include "boost/python.hpp" +using namespace boost::python; + //----------------------------------------------------------------------------- // TransmitStates_t definition. @@ -45,91 +55,52 @@ typedef CBitVec TransmitStates_t; //----------------------------------------------------------------------------- -// ETransmitTarget enumeration. -//----------------------------------------------------------------------------- -enum ETransmitTarget -{ - TRANSMIT_TARGET_ENTITY, - TRANSMIT_TARGET_PLAYER -}; - - -//----------------------------------------------------------------------------- -// CBaseTransmitCriteria class. +// CTransmitManager class. //----------------------------------------------------------------------------- -class CBaseTransmitCriteria: public TransmitStates_t +class CTransmitManager { -public: - CBaseTransmitCriteria(ETransmitTarget eTarget = TRANSMIT_TARGET_ENTITY); - -public: - ETransmitTarget m_eTarget; -}; - +private: + CTransmitManager(); -//----------------------------------------------------------------------------- -// ETransmitType enumeration. -//----------------------------------------------------------------------------- -enum ETransmitType -{ - TRANSMIT_IN, - TRANSMIT_OUT -}; + void initialize(); + void finalize(); + void handle_filters(CCheckTransmitInfo* pInfo, unsigned int player_index); + static bool _post_check_transmit(HookType_t eHookType, CHook *pHook); -//----------------------------------------------------------------------------- -// CBaseTransmitFilter class. -//----------------------------------------------------------------------------- -class CBaseTransmitFilter -{ public: - CBaseTransmitFilter(ETransmitType eType = TRANSMIT_OUT, CBaseTransmitCriteria *pCriteria = NULL, object oOverride = object()); + using filter_pair = std::pair; -public: - bool get_override(); - void set_override(object oOverride); - bool has_override(); + static CTransmitManager* get_instance(); - object get_callback(); - void set_callback(object oCallback); + static void create(); + static void destroy(); -private: - bool m_bOverride; - bool m_bHasOverride; + void hide(int entity_index); + void hide_from(int entity_index, int player_index); - object m_oCallback; + void unhide(int entity_index); + void unhide_from(int entity_index, int player_index); -public: - ETransmitType m_eType; - CBaseTransmitCriteria *m_pCriteria; -}; + void reset(int entity_index); + void reset_from(int entity_index, int player_index); + void reset_all(); + bool is_hidden(int entity_index); + bool is_hidden_from(int entity_index, int player_index); -//----------------------------------------------------------------------------- -// CTransmitManager class. -//----------------------------------------------------------------------------- -class CTransmitManager -{ -private: - CTransmitManager(); + tuple get_hidden_states(int entity_index); private: - void initialize(); - static bool _post_check_transmit(HookType_t eHookType, CHook *pHook); - bool handle_filters(ETransmitType eType, int iIndex, unsigned int uiPlayer); + static std::once_flag init_flag; + static CTransmitManager* instance; -public: - static CTransmitManager *GetSingleton(); + void* m_pCheckTransmit = nullptr; - void register_filter(CBaseTransmitFilter *pFilter); - void unregister_filter(CBaseTransmitFilter *pFilter); - -private: - bool m_bInitialized; - CUtlVector m_vecFilters; + std::vector> m_vecFilters = decltype(m_vecFilters)(ABSOLUTE_PLAYER_LIMIT); }; -inline CTransmitManager *GetTransmitManager() { return CTransmitManager::GetSingleton(); } +inline CTransmitManager *GetTransmitManager() { return CTransmitManager::get_instance(); } #endif // _ENTITIES_TRANSMIT_H diff --git a/src/core/modules/entities/entities_transmit_wrap.cpp b/src/core/modules/entities/entities_transmit_wrap.cpp old mode 100644 new mode 100755 index d50ff0f38..51ff87954 --- a/src/core/modules/entities/entities_transmit_wrap.cpp +++ b/src/core/modules/entities/entities_transmit_wrap.cpp @@ -36,11 +36,6 @@ //----------------------------------------------------------------------------- // Forward declarations. //----------------------------------------------------------------------------- -static void export_transmit_states(scope); -static void export_transmit_target(scope); -static void export_transmit_type(scope); -static void export_base_transmit_criteria(scope); -static void export_base_transmit_filter(scope); static void export_transmit_manager(scope); @@ -49,118 +44,84 @@ static void export_transmit_manager(scope); //----------------------------------------------------------------------------- DECLARE_SP_SUBMODULE(_entities, _transmit) { - export_transmit_states(_transmit); - export_transmit_target(_transmit); - export_transmit_type(_transmit); - export_base_transmit_criteria(_transmit); - export_base_transmit_filter(_transmit); export_transmit_manager(_transmit); } //----------------------------------------------------------------------------- -// Exports TransmitStates_t. -//----------------------------------------------------------------------------- -void export_transmit_states(scope _transmit) -{ - class_ TransmitStates("TransmitStates"); - - // Special methods... - TransmitStates.def("__delitem__", GET_METHOD(void, TransmitStates_t, Clear, int)); - TransmitStates.def("__getitem__", &TransmitStates_t::IsBitSet); - TransmitStates.def("__setitem__", GET_METHOD(void, TransmitStates_t, Set, int, bool)); - - // Add memory tools... - TransmitStates ADD_MEM_TOOLS(TransmitStates_t); -} - - -//----------------------------------------------------------------------------- -// Exports ETransmitTarget. +// Exports CTransmitManager. //----------------------------------------------------------------------------- -void export_transmit_target(scope _transmit) +void export_transmit_manager(scope _transmit) { - enum_ TransmitTarget("TransmitTarget"); - - // Values... - TransmitTarget.value("ENTITY", TRANSMIT_TARGET_ENTITY); - TransmitTarget.value("PLAYER", TRANSMIT_TARGET_PLAYER); -} + class_("TransmitManager", no_init) + // Class methods + .def("hide", + &CTransmitManager::hide, + "", + ("entity_index") + ) -//----------------------------------------------------------------------------- -// Exports ETransmitType. -//----------------------------------------------------------------------------- -void export_transmit_type(scope _transmit) -{ - enum_ TransmitType("TransmitType"); + .def("hide_from", + &CTransmitManager::hide_from, + "", + ("entity_index", "player_index") + ) - // Values... - TransmitType.value("IN", TRANSMIT_IN); - TransmitType.value("OUT", TRANSMIT_OUT); -} + .def("unhide", + &CTransmitManager::unhide, + "", + ("entity_index") + ) -//----------------------------------------------------------------------------- -// Exports CBaseTransmitCriteria. -//----------------------------------------------------------------------------- -void export_base_transmit_criteria(scope _transmit) -{ - class_ > BaseTransmitCriteria( - "BaseTransmitCriteria", - init( - ( - arg("self"), arg("target")=TRANSMIT_TARGET_ENTITY - ) + .def("unhide_from", + &CTransmitManager::unhide_from, + "", + ("entity_index", "player_index") ) - ); - // Properties... - BaseTransmitCriteria.def_readwrite("target", &CBaseTransmitCriteria::m_eTarget); - // Add memory tools... - BaseTransmitCriteria ADD_MEM_TOOLS(CBaseTransmitCriteria); -} + .def("reset", + &CTransmitManager::reset, + "", + ("entity_index") + ) + .def("reset_from", + &CTransmitManager::reset_from, + "", + ("entity_index", "player_index") + ) -//----------------------------------------------------------------------------- -// Exports CBaseTransmitFilter. -//----------------------------------------------------------------------------- -void export_base_transmit_filter(scope _transmit) -{ - class_ BaseTransmitFilter( - "BaseTransmitFilter", - init( - ( - arg("self"), arg("type")=TRANSMIT_OUT, arg("criteria")=object(), arg("override")=object() - ) + .def("reset_all", + &CTransmitManager::reset_all, + "" ) - ); - // Properties... - BaseTransmitFilter.def_readwrite("type", &CBaseTransmitFilter::m_eType); - BaseTransmitFilter.def_readwrite("criteria", &CBaseTransmitFilter::m_pCriteria); - BaseTransmitFilter.add_property("override", &CBaseTransmitFilter::get_override, &CBaseTransmitFilter::set_override); - BaseTransmitFilter.add_property("callback", &CBaseTransmitFilter::get_callback, &CBaseTransmitFilter::set_callback); - // Add memory tools... - BaseTransmitFilter ADD_MEM_TOOLS(CBaseTransmitFilter); -} + .def("is_hidden", + &CTransmitManager::is_hidden, + "", + ("entity_index") + ) + .def("is_hidden_from", + &CTransmitManager::is_hidden_from, + "", + ("entity_index", "player_index") + ) -//----------------------------------------------------------------------------- -// Exports CTransmitManager. -//----------------------------------------------------------------------------- -void export_transmit_manager(scope _transmit) -{ - class_ TransmitManager("TransmitManager", no_init); + .def("get_hidden_states", + &CTransmitManager::get_hidden_states, + "", + ("entity_index") + ) - // Methods... - TransmitManager.def("register_filter", &CTransmitManager::register_filter); - TransmitManager.def("unregister_filter", &CTransmitManager::unregister_filter); - // Add memory tools... - TransmitManager ADD_MEM_TOOLS(CTransmitManager); + // Add memory tools... + ADD_MEM_TOOLS(CTransmitManager) + ; // Singleton... _transmit.attr("transmit_manager") = object(ptr(GetTransmitManager())); diff --git a/src/patches/csgo/public/bitvec.h b/src/patches/csgo/public/bitvec.h new file mode 100755 index 000000000..bb5c49948 --- /dev/null +++ b/src/patches/csgo/public/bitvec.h @@ -0,0 +1,1417 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// + +#ifndef BITVEC_H +#define BITVEC_H +#ifdef _WIN32 +#pragma once +#endif + +#include +#include "tier0/dbg.h" +#include "tier0/basetypes.h" + + +class CBitVecAccessor +{ +public: + CBitVecAccessor(uint32 *pDWords, int iBit); + + void operator=(int val); + operator uint32(); + +private: + uint32 *m_pDWords; + int m_iBit; +}; + + +//----------------------------------------------------------------------------- +// Support functions +//----------------------------------------------------------------------------- + +#define LOG2_BITS_PER_INT 5 +#define BITS_PER_INT 32 + +#if _WIN32 && !defined(_X360) +#include +#pragma intrinsic(_BitScanForward) +#endif + +inline int FirstBitInWord( unsigned int elem, int offset ) +{ +#if _WIN32 + if ( !elem ) + return -1; +#if _X360 + // this implements CountTrailingZeros() / BitScanForward() + unsigned int mask = elem-1; + unsigned int comp = ~elem; + elem = mask & comp; + return (32 - _CountLeadingZeros(elem)) + offset; +#else + unsigned long out; + _BitScanForward(&out, elem); + return out + offset; +#endif + +#else + static unsigned firstBitLUT[256] = + { + 0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0, + 3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0, + 3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0, + 3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 + }; + unsigned elemByte; + + elemByte = (elem & 0xFF); + if ( elemByte ) + return offset + firstBitLUT[elemByte]; + + elem >>= 8; + offset += 8; + elemByte = (elem & 0xFF); + if ( elemByte ) + return offset + firstBitLUT[elemByte]; + + elem >>= 8; + offset += 8; + elemByte = (elem & 0xFF); + if ( elemByte ) + return offset + firstBitLUT[elemByte]; + + elem >>= 8; + offset += 8; + elemByte = (elem & 0xFF); + if ( elemByte ) + return offset + firstBitLUT[elemByte]; + + return -1; +#endif +} + +//------------------------------------- + +inline unsigned GetEndMask( int numBits ) +{ + static unsigned bitStringEndMasks[] = + { + 0xffffffff, + 0x00000001, + 0x00000003, + 0x00000007, + 0x0000000f, + 0x0000001f, + 0x0000003f, + 0x0000007f, + 0x000000ff, + 0x000001ff, + 0x000003ff, + 0x000007ff, + 0x00000fff, + 0x00001fff, + 0x00003fff, + 0x00007fff, + 0x0000ffff, + 0x0001ffff, + 0x0003ffff, + 0x0007ffff, + 0x000fffff, + 0x001fffff, + 0x003fffff, + 0x007fffff, + 0x00ffffff, + 0x01ffffff, + 0x03ffffff, + 0x07ffffff, + 0x0fffffff, + 0x1fffffff, + 0x3fffffff, + 0x7fffffff, + }; + + return bitStringEndMasks[numBits % BITS_PER_INT]; +} + + +inline int GetBitForBitnum( int bitNum ) +{ + static int bitsForBitnum[] = + { + ( 1 << 0 ), + ( 1 << 1 ), + ( 1 << 2 ), + ( 1 << 3 ), + ( 1 << 4 ), + ( 1 << 5 ), + ( 1 << 6 ), + ( 1 << 7 ), + ( 1 << 8 ), + ( 1 << 9 ), + ( 1 << 10 ), + ( 1 << 11 ), + ( 1 << 12 ), + ( 1 << 13 ), + ( 1 << 14 ), + ( 1 << 15 ), + ( 1 << 16 ), + ( 1 << 17 ), + ( 1 << 18 ), + ( 1 << 19 ), + ( 1 << 20 ), + ( 1 << 21 ), + ( 1 << 22 ), + ( 1 << 23 ), + ( 1 << 24 ), + ( 1 << 25 ), + ( 1 << 26 ), + ( 1 << 27 ), + ( 1 << 28 ), + ( 1 << 29 ), + ( 1 << 30 ), + ( 1 << 31 ), + }; + + return bitsForBitnum[ (bitNum) & (BITS_PER_INT-1) ]; +} + +inline int GetBitForBitnumByte( int bitNum ) +{ + static int bitsForBitnum[] = + { + ( 1 << 0 ), + ( 1 << 1 ), + ( 1 << 2 ), + ( 1 << 3 ), + ( 1 << 4 ), + ( 1 << 5 ), + ( 1 << 6 ), + ( 1 << 7 ), + }; + + return bitsForBitnum[ bitNum & 7 ]; +} + +inline int CalcNumIntsForBits( int numBits ) { return (numBits + (BITS_PER_INT-1)) / BITS_PER_INT; } + +#ifdef _X360 +#define BitVec_Bit( bitNum ) GetBitForBitnum( bitNum ) +#define BitVec_BitInByte( bitNum ) GetBitForBitnumByte( bitNum ) +#else +#define BitVec_Bit( bitNum ) ( 1 << ( (bitNum) & (BITS_PER_INT-1) ) ) +#define BitVec_BitInByte( bitNum ) ( 1 << ( (bitNum) & 7 ) ) +#endif +#define BitVec_Int( bitNum ) ( (bitNum) >> LOG2_BITS_PER_INT ) + + +//----------------------------------------------------------------------------- +// template CBitVecT +// +// Defines the operations relevant to any bit array. Simply requires a base +// class that implements GetNumBits(), Base(), GetNumDWords() & ValidateOperand() +// +// CVarBitVec and CBitVec are the actual classes generally used +// by clients +// + +template +class CBitVecT : public BASE_OPS +{ +public: + CBitVecT(); + CBitVecT(int numBits); // Must be initialized with the number of bits + + void Init(int val = 0); + + // Access the bits like an array. + CBitVecAccessor operator[](int i); + + // Do NOT override bitwise operators (see note in header) + void And(const CBitVecT &andStr, CBitVecT *out) const; + void Or(const CBitVecT &orStr, CBitVecT *out) const; + void Xor(const CBitVecT &orStr, CBitVecT *out) const; + + void Not(CBitVecT *out) const; + + void CopyTo(CBitVecT *out) const; + void Copy( const CBitVecT &other, int nBits=-1 ); + bool Compare( const CBitVecT &other, int nBits=-1 ) const; + + bool IsAllClear(void) const; // Are all bits zero? + bool IsAllSet(void) const; // Are all bits one? + + uint32 Get( uint32 bitNum ) const; + bool IsBitSet( int bitNum ) const; + void Set( int bitNum ); + void Set( int bitNum, bool bNewVal ); + void Clear(int bitNum); + + bool TestAndSet(int bitNum); + + void Set( uint32 offset, uint32 mask ); + void Clear( uint32 offset, uint32 mask ); + uint32 Get( uint32 offset, uint32 mask ); + + void SetAll(void); // Sets all bits + void ClearAll(void); // Clears all bits + + uint32 GetDWord(int i) const; + void SetDWord(int i, uint32 val); + + CBitVecT& operator=(const CBitVecT &other) { other.CopyTo( this ); return *this; } + bool operator==(const CBitVecT &other) { return Compare( other ); } + bool operator!=(const CBitVecT &other) { return !operator==( other ); } + + static void GetOffsetMaskForBit( uint32 bitNum, uint32 *pOffset, uint32 *pMask ) { *pOffset = BitVec_Int( bitNum ); *pMask = BitVec_Bit( bitNum ); } +}; + +//----------------------------------------------------------------------------- +// class CVarBitVecBase +// +// Defines the operations necessary for a variable sized bit array + +class CVarBitVecBase +{ +public: + bool IsFixedSize() const { return false; } + int GetNumBits(void) const { return m_numBits; } + void Resize( int numBits, bool bClearAll = false ); // resizes bit array + + int GetNumDWords() const { return m_numInts; } + uint32 *Base() { return m_pInt; } + const uint32 *Base() const { return m_pInt; } + + void Attach( uint32 *pBits, int numBits ); + bool Detach( uint32 **ppBits, int *pNumBits ); + + int FindNextSetBit(int iStartBit) const; // returns -1 if no set bit was found + +protected: + CVarBitVecBase(); + CVarBitVecBase(int numBits); + CVarBitVecBase( const CVarBitVecBase &from ); + CVarBitVecBase &operator=( const CVarBitVecBase &from ); + ~CVarBitVecBase(void); + + void ValidateOperand( const CVarBitVecBase &operand ) const { Assert(GetNumBits() == operand.GetNumBits()); } + + unsigned GetEndMask() const { return ::GetEndMask( GetNumBits() ); } + +private: + + unsigned short m_numBits; // Number of bits in the bitstring + unsigned short m_numInts; // Number of ints to needed to store bitstring + uint32 m_iBitStringStorage; // If the bit string fits in one int, it goes here + uint32 * m_pInt; // Array of ints containing the bitstring + + void AllocInts( int numInts ); // Free the allocated bits + void ReallocInts( int numInts ); + void FreeInts( void ); // Free the allocated bits +}; + +//----------------------------------------------------------------------------- +// class CFixedBitVecBase +// +// Defines the operations necessary for a fixed sized bit array. +// + +template struct BitCountToEndMask_t { }; +template <> struct BitCountToEndMask_t< 0> { enum { MASK = 0xffffffff }; }; +template <> struct BitCountToEndMask_t< 1> { enum { MASK = 0x00000001 }; }; +template <> struct BitCountToEndMask_t< 2> { enum { MASK = 0x00000003 }; }; +template <> struct BitCountToEndMask_t< 3> { enum { MASK = 0x00000007 }; }; +template <> struct BitCountToEndMask_t< 4> { enum { MASK = 0x0000000f }; }; +template <> struct BitCountToEndMask_t< 5> { enum { MASK = 0x0000001f }; }; +template <> struct BitCountToEndMask_t< 6> { enum { MASK = 0x0000003f }; }; +template <> struct BitCountToEndMask_t< 7> { enum { MASK = 0x0000007f }; }; +template <> struct BitCountToEndMask_t< 8> { enum { MASK = 0x000000ff }; }; +template <> struct BitCountToEndMask_t< 9> { enum { MASK = 0x000001ff }; }; +template <> struct BitCountToEndMask_t<10> { enum { MASK = 0x000003ff }; }; +template <> struct BitCountToEndMask_t<11> { enum { MASK = 0x000007ff }; }; +template <> struct BitCountToEndMask_t<12> { enum { MASK = 0x00000fff }; }; +template <> struct BitCountToEndMask_t<13> { enum { MASK = 0x00001fff }; }; +template <> struct BitCountToEndMask_t<14> { enum { MASK = 0x00003fff }; }; +template <> struct BitCountToEndMask_t<15> { enum { MASK = 0x00007fff }; }; +template <> struct BitCountToEndMask_t<16> { enum { MASK = 0x0000ffff }; }; +template <> struct BitCountToEndMask_t<17> { enum { MASK = 0x0001ffff }; }; +template <> struct BitCountToEndMask_t<18> { enum { MASK = 0x0003ffff }; }; +template <> struct BitCountToEndMask_t<19> { enum { MASK = 0x0007ffff }; }; +template <> struct BitCountToEndMask_t<20> { enum { MASK = 0x000fffff }; }; +template <> struct BitCountToEndMask_t<21> { enum { MASK = 0x001fffff }; }; +template <> struct BitCountToEndMask_t<22> { enum { MASK = 0x003fffff }; }; +template <> struct BitCountToEndMask_t<23> { enum { MASK = 0x007fffff }; }; +template <> struct BitCountToEndMask_t<24> { enum { MASK = 0x00ffffff }; }; +template <> struct BitCountToEndMask_t<25> { enum { MASK = 0x01ffffff }; }; +template <> struct BitCountToEndMask_t<26> { enum { MASK = 0x03ffffff }; }; +template <> struct BitCountToEndMask_t<27> { enum { MASK = 0x07ffffff }; }; +template <> struct BitCountToEndMask_t<28> { enum { MASK = 0x0fffffff }; }; +template <> struct BitCountToEndMask_t<29> { enum { MASK = 0x1fffffff }; }; +template <> struct BitCountToEndMask_t<30> { enum { MASK = 0x3fffffff }; }; +template <> struct BitCountToEndMask_t<31> { enum { MASK = 0x7fffffff }; }; + +//------------------------------------- + +template +class CFixedBitVecBase +{ +public: + bool IsFixedSize() const { return true; } + int GetNumBits(void) const { return NUM_BITS; } + void Resize( int numBits, bool bClearAll = false ) { Assert(numBits == NUM_BITS); if ( bClearAll ) Plat_FastMemset( m_Ints, 0, NUM_INTS * sizeof(uint32) ); }// for syntatic consistency (for when using templates) + + int GetNumDWords() const { return NUM_INTS; } + uint32 * Base() { return m_Ints; } + const uint32 * Base() const { return m_Ints; } + + int FindNextSetBit(int iStartBit) const; // returns -1 if no set bit was found + +protected: + CFixedBitVecBase() {} + CFixedBitVecBase(int numBits) { Assert( numBits == NUM_BITS ); } // doesn't make sense, really. Supported to simplify templates & allow easy replacement of variable + + void ValidateOperand( const CFixedBitVecBase &operand ) const { } // no need, compiler does so statically + +public: // for test code + unsigned GetEndMask() const { return static_cast( BitCountToEndMask_t::MASK ); } + +private: + enum + { + NUM_INTS = (NUM_BITS + (BITS_PER_INT-1)) / BITS_PER_INT + }; + + uint32 m_Ints[(NUM_BITS + (BITS_PER_INT-1)) / BITS_PER_INT]; +}; + +//----------------------------------------------------------------------------- +// +// The actual classes used +// + +// inheritance instead of typedef to allow forward declarations +class CVarBitVec : public CBitVecT +{ +public: + CVarBitVec() + { + } + + CVarBitVec(int numBits) + : CBitVecT(numBits) + { + } +}; + +//----------------------------------------------------------------------------- + +template < int NUM_BITS > +class CBitVec : public CBitVecT< CFixedBitVecBase > +{ +public: + CBitVec() + { + } + + CBitVec(int numBits) + : CBitVecT< CFixedBitVecBase >(numBits) + { + } +}; + + +//----------------------------------------------------------------------------- + +typedef CBitVec<32> CDWordBitVec; + +//----------------------------------------------------------------------------- + +inline CVarBitVecBase::CVarBitVecBase() +{ + Plat_FastMemset( this, 0, sizeof( *this ) ); +} + +//----------------------------------------------------------------------------- + +inline CVarBitVecBase::CVarBitVecBase(int numBits) +{ + Assert( numBits ); + m_numBits = numBits; + + // Figure out how many ints are needed + m_numInts = CalcNumIntsForBits( numBits ); + m_pInt = NULL; + AllocInts( m_numInts ); +} + +//----------------------------------------------------------------------------- + +inline CVarBitVecBase::CVarBitVecBase( const CVarBitVecBase &from ) +{ + if ( from.m_numInts ) + { + m_numBits = from.m_numBits; + m_numInts = from.m_numInts; + m_pInt = NULL; + AllocInts( m_numInts ); + memcpy( m_pInt, from.m_pInt, m_numInts * sizeof(int) ); + } + else + memset( this, 0, sizeof( *this ) ); +} + +//----------------------------------------------------------------------------- + +inline CVarBitVecBase &CVarBitVecBase::operator=( const CVarBitVecBase &from ) +{ + Resize( from.GetNumBits() ); + if ( m_pInt ) + memcpy( m_pInt, from.m_pInt, m_numInts * sizeof(int) ); + return (*this); +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +// Input : +// Output : +//----------------------------------------------------------------------------- + +inline CVarBitVecBase::~CVarBitVecBase(void) +{ + FreeInts(); +} + +//----------------------------------------------------------------------------- + +inline void CVarBitVecBase::Attach( uint32 *pBits, int numBits ) +{ + FreeInts(); + m_numBits = numBits; + m_numInts = CalcNumIntsForBits( numBits ); + if ( m_numInts > 1 ) + { + m_pInt = pBits; + } + else + { + m_iBitStringStorage = *pBits; + m_pInt = &m_iBitStringStorage; + free( pBits ); + } +} + +//----------------------------------------------------------------------------- + +inline bool CVarBitVecBase::Detach( uint32 **ppBits, int *pNumBits ) +{ + if ( !m_numBits ) + { + return false; + } + + *pNumBits = m_numBits; + if ( m_numInts > 1 ) + { + *ppBits = m_pInt; + } + else + { + *ppBits = (uint32 *)malloc( sizeof(uint32) ); + **ppBits = m_iBitStringStorage; + free( m_pInt ); + } + + memset( this, 0, sizeof( *this ) ); + return true; +} + +//----------------------------------------------------------------------------- + +template +inline CBitVecT::CBitVecT() +{ + // undef this is ints are not 4 bytes + // generate a compile error if sizeof(int) is not 4 (HACK: can't use the preprocessor so use the compiler) + + COMPILE_TIME_ASSERT( sizeof(int)==4 ); + + // Initialize bitstring by clearing all bits + ClearAll(); +} + +//----------------------------------------------------------------------------- +template +inline CBitVecT::CBitVecT(int numBits) + : BASE_OPS( numBits ) +{ + // undef this is ints are not 4 bytes + // generate a compile error if sizeof(int) is not 4 (HACK: can't use the preprocessor so use the compiler) + + COMPILE_TIME_ASSERT( sizeof(int)==4 ); + + // Initialize bitstring by clearing all bits + ClearAll(); +} + +//----------------------------------------------------------------------------- + +template +inline CBitVecAccessor CBitVecT::operator[](int i) +{ + Assert(i >= 0 && i < this->GetNumBits()); + return CBitVecAccessor(this->Base(), i); +} + + +//----------------------------------------------------------------------------- + +template +inline void CBitVecT::Init( int val ) +{ + if ( this->Base() ) + Plat_FastMemset( this->Base(), ( val ) ? 0xff : 0, this->GetNumDWords() * sizeof(int) ); +} + +//----------------------------------------------------------------------------- + +template +inline uint32 CBitVecT::Get( uint32 bitNum ) const +{ + Assert( bitNum < (uint32)this->GetNumBits() ); + const uint32 *pInt = this->Base() + BitVec_Int( bitNum ); + return ( *pInt & BitVec_Bit( bitNum ) ); +} + +//----------------------------------------------------------------------------- + +template +inline bool CBitVecT::IsBitSet( int bitNum ) const +{ + Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); + const uint32 *pInt = this->Base() + BitVec_Int( bitNum ); + return ( ( *pInt & BitVec_Bit( bitNum ) ) != 0 ); +} + +//----------------------------------------------------------------------------- + +template +inline void CBitVecT::Set( int bitNum ) +{ + Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); + uint32 *pInt = this->Base() + BitVec_Int( bitNum ); + *pInt |= BitVec_Bit( bitNum ); +} + +//----------------------------------------------------------------------------- + +template +inline bool CBitVecT::TestAndSet(int bitNum) +{ + Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); + uint32 bitVecBit = BitVec_Bit( bitNum ); + uint32 *pInt = this->Base() + BitVec_Int( bitNum ); + bool bResult = ( ( *pInt & bitVecBit) != 0 ); + *pInt |= bitVecBit; + return bResult; +} + +//----------------------------------------------------------------------------- + +template +inline void CBitVecT::Clear(int bitNum) +{ + Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); + uint32 *pInt = this->Base() + BitVec_Int( bitNum ); + *pInt &= ~BitVec_Bit( bitNum ); +} + +//----------------------------------------------------------------------------- + +template +inline void CBitVecT::Set( int bitNum, bool bNewVal ) +{ + uint32 *pInt = this->Base() + BitVec_Int( bitNum ); + uint32 bitMask = BitVec_Bit( bitNum ); + if ( bNewVal ) + { + *pInt |= bitMask; + } + else + { + *pInt &= ~bitMask; + } +} + +//----------------------------------------------------------------------------- + +template +inline void CBitVecT::Set( uint32 offset, uint32 mask ) +{ + uint32 *pInt = this->Base() + offset; + *pInt |= mask; +} + +//----------------------------------------------------------------------------- + +template +inline void CBitVecT::Clear( uint32 offset, uint32 mask ) +{ + uint32 *pInt = this->Base() + offset; + *pInt &= ~mask; +} + +//----------------------------------------------------------------------------- + +template +inline uint32 CBitVecT::Get( uint32 offset, uint32 mask ) +{ + uint32 *pInt = this->Base() + offset; + return ( *pInt & mask ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : +//----------------------------------------------------------------------------- +template +inline void CBitVecT::And(const CBitVecT &addStr, CBitVecT *out) const +{ + this->ValidateOperand( addStr ); + this->ValidateOperand( *out ); + + uint32 * pDest = out->Base(); + const uint32 *pOperand1 = this->Base(); + const uint32 *pOperand2 = addStr.Base(); + + for (int i = this->GetNumDWords() - 1; i >= 0 ; --i) + { + pDest[i] = pOperand1[i] & pOperand2[i]; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : +//----------------------------------------------------------------------------- +template +inline void CBitVecT::Or(const CBitVecT &orStr, CBitVecT *out) const +{ + this->ValidateOperand( orStr ); + this->ValidateOperand( *out ); + + uint32 * pDest = out->Base(); + const uint32 *pOperand1 = this->Base(); + const uint32 *pOperand2 = orStr.Base(); + + for (int i = this->GetNumDWords() - 1; i >= 0; --i) + { + pDest[i] = pOperand1[i] | pOperand2[i]; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : +//----------------------------------------------------------------------------- +template +inline void CBitVecT::Xor(const CBitVecT &xorStr, CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pOperand1 = this->Base(); + const uint32 *pOperand2 = xorStr.Base(); + + for (int i = this->GetNumDWords() - 1; i >= 0; --i) + { + pDest[i] = pOperand1[i] ^ pOperand2[i]; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : +//----------------------------------------------------------------------------- +template +inline void CBitVecT::Not(CBitVecT *out) const +{ + ValidateOperand( *out ); + + uint32 * pDest = out->Base(); + const uint32 *pOperand = this->Base(); + + for (int i = this->GetNumDWords() - 1; i >= 0; --i) + { + pDest[i] = ~(pOperand[i]); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Copy a bit string +// Input : +// Output : +//----------------------------------------------------------------------------- +template +inline void CBitVecT::CopyTo(CBitVecT *out) const +{ + out->Resize( this->GetNumBits() ); + + this->ValidateOperand( *out ); + Assert( out != this ); + + memcpy( out->Base(), this->Base(), this->GetNumDWords() * sizeof( int ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: Are all bits zero? +// Input : +// Output : +//----------------------------------------------------------------------------- +template +inline bool CBitVecT::IsAllClear(void) const +{ + // Number of available bits may be more than the number + // actually used, so make sure to mask out unused bits + // before testing for zero + (const_cast(this))->Base()[this->GetNumDWords()-1] &= CBitVecT::GetEndMask(); // external semantics of const retained + + for (int i = this->GetNumDWords() - 1; i >= 0; --i) + { + if ( this->Base()[i] !=0 ) + { + return false; + } + } + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Are all bits set? +// Input : +// Output : +//----------------------------------------------------------------------------- +template +inline bool CBitVecT::IsAllSet(void) const +{ + // Number of available bits may be more than the number + // actually used, so make sure to mask out unused bits + // before testing for set bits + (const_cast(this))->Base()[this->GetNumDWords()-1] |= ~CBitVecT::GetEndMask(); // external semantics of const retained + + for (int i = this->GetNumDWords() - 1; i >= 0; --i) + { + if ( this->Base()[i] != ~0 ) + { + return false; + } + } + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Sets all bits +// Input : +// Output : +//----------------------------------------------------------------------------- +template +inline void CBitVecT::SetAll(void) +{ + if ( this->Base() ) + Plat_FastMemset( this->Base(), 0xff, this->GetNumDWords() * sizeof(int) ); +} + +//----------------------------------------------------------------------------- +// Purpose: Clears all bits +// Input : +// Output : +//----------------------------------------------------------------------------- +template +inline void CBitVecT::ClearAll(void) +{ + if ( this->Base() ) + Plat_FastMemset( this->Base(), 0, this->GetNumDWords() * sizeof(int) ); +} + +//----------------------------------------------------------------------------- +template +inline void CBitVecT::Copy( const CBitVecT &other, int nBits ) +{ + if ( nBits == - 1 ) + { + nBits = other.GetNumBits(); + } + + this->Resize( nBits ); + + ValidateOperand( other ); + Assert( &other != this ); + + memcpy( this->Base(), other.Base(), this->GetNumDWords() * sizeof( uint32 ) ); +} + +//----------------------------------------------------------------------------- +template +inline bool CBitVecT::Compare( const CBitVecT &other, int nBits ) const +{ + if ( nBits == - 1 ) + { + if ( other.GetNumBits() != this->GetNumBits() ) + { + return false; + } + + nBits = other.GetNumBits(); + } + + if ( nBits > other.GetNumBits() || nBits > this->GetNumBits() ) + { + return false; + } + + (const_cast(this))->Base()[this->GetNumDWords()-1] &= CBitVecT::GetEndMask(); // external semantics of const retained + (const_cast(&other))->Base()[this->GetNumDWords()-1] &= other.CBitVecT::GetEndMask(); // external semantics of const retained + + int nBytes = PAD_NUMBER( nBits, 8 ) >> 3; + + return ( memcmp( this->Base(), other.Base(), nBytes ) == 0 ); +} + +//----------------------------------------------------------------------------- +template +inline uint32 CBitVecT::GetDWord(int i) const +{ + Assert(i >= 0 && i < this->GetNumDWords()); + return this->Base()[i]; +} + +//----------------------------------------------------------------------------- +template +inline void CBitVecT::SetDWord(int i, uint32 val) +{ + Assert(i >= 0 && i < this->GetNumDWords()); + this->Base()[i] = val; +} + +//----------------------------------------------------------------------------- + +inline unsigned GetStartBitMask( int startBit ) +{ + static unsigned int g_StartMask[32] = + { + 0xffffffff, + 0xfffffffe, + 0xfffffffc, + 0xfffffff8, + 0xfffffff0, + 0xffffffe0, + 0xffffffc0, + 0xffffff80, + 0xffffff00, + 0xfffffe00, + 0xfffffc00, + 0xfffff800, + 0xfffff000, + 0xffffe000, + 0xffffc000, + 0xffff8000, + 0xffff0000, + 0xfffe0000, + 0xfffc0000, + 0xfff80000, + 0xfff00000, + 0xffe00000, + 0xffc00000, + 0xff800000, + 0xff000000, + 0xfe000000, + 0xfc000000, + 0xf8000000, + 0xf0000000, + 0xe0000000, + 0xc0000000, + 0x80000000, + }; + + return g_StartMask[ startBit & 31 ]; +} + +inline int CVarBitVecBase::FindNextSetBit( int startBit ) const +{ + if ( startBit < GetNumBits() ) + { + int wordIndex = BitVec_Int(startBit); + unsigned int startMask = GetStartBitMask( startBit ); + int lastWord = GetNumDWords()-1; + + // handle non dword lengths + if ( (GetNumBits() % BITS_PER_INT) != 0 ) + { + unsigned int elem = Base()[wordIndex]; + elem &= startMask; + if ( wordIndex == lastWord) + { + elem &= (GetEndMask()); + // there's a bit remaining in this word + if ( elem ) + return FirstBitInWord(elem, wordIndex << 5); + } + else + { + // there's a bit remaining in this word + if ( elem ) + return FirstBitInWord(elem, wordIndex << 5); + + // iterate the words + for ( int i = wordIndex+1; i < lastWord; i++ ) + { + elem = Base()[i]; + if ( elem ) + return FirstBitInWord(elem, i << 5); + } + elem = Base()[lastWord] & GetEndMask(); + if ( elem ) + return FirstBitInWord(elem, lastWord << 5); + } + } + else + { + const uint32 * RESTRICT pCurElem = Base() + wordIndex; + unsigned int elem = *pCurElem; + elem &= startMask; + do + { + if ( elem ) + return FirstBitInWord(elem, wordIndex << 5); + ++pCurElem; + elem = *pCurElem; + ++wordIndex; + } while( wordIndex <= lastWord ); + } + + } + + return -1; +} + +template +inline int CFixedBitVecBase::FindNextSetBit( int startBit ) const +{ + if ( startBit < NUM_BITS ) + { + int wordIndex = BitVec_Int(startBit); + unsigned int startMask = GetStartBitMask( startBit ); + + // handle non dword lengths + if ( (NUM_BITS % BITS_PER_INT) != 0 ) + { + unsigned int elem = Base()[wordIndex]; + elem &= startMask; + if ( wordIndex == NUM_INTS-1) + { + elem &= (GetEndMask()); + // there's a bit remaining in this word + if ( elem ) + return FirstBitInWord(elem, wordIndex << 5); + } + else + { + // there's a bit remaining in this word + if ( elem ) + return FirstBitInWord(elem, wordIndex << 5); + + // iterate the words + for ( int i = wordIndex+1; i < NUM_INTS-1; i++ ) + { + elem = Base()[i]; + if ( elem ) + return FirstBitInWord(elem, i << 5); + } + elem = Base()[NUM_INTS-1] & GetEndMask(); + if ( elem ) + return FirstBitInWord(elem, (NUM_INTS-1) << 5); + } + } + else + { + const uint32 * RESTRICT pCurElem = Base() + wordIndex; + unsigned int elem = *pCurElem; + elem &= startMask; + do + { + if ( elem ) + return FirstBitInWord(elem, wordIndex << 5); + ++pCurElem; + elem = *pCurElem; + ++wordIndex; + } while( wordIndex <= NUM_INTS-1); + } + + } + + return -1; +} + +//----------------------------------------------------------------------------- +// Unrolled loops for some common sizes + +template<> +FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<256> >::And(const CBitVecT &addStr, CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pOperand1 = Base(); + const uint32 *pOperand2 = addStr.Base(); + + pDest[0] = pOperand1[0] & pOperand2[0]; + pDest[1] = pOperand1[1] & pOperand2[1]; + pDest[2] = pOperand1[2] & pOperand2[2]; + pDest[3] = pOperand1[3] & pOperand2[3]; + pDest[4] = pOperand1[4] & pOperand2[4]; + pDest[5] = pOperand1[5] & pOperand2[5]; + pDest[6] = pOperand1[6] & pOperand2[6]; + pDest[7] = pOperand1[7] & pOperand2[7]; +} + +template<> +FORCEINLINE_TEMPLATE bool CBitVecT< CFixedBitVecBase<256> >::IsAllClear(void) const +{ + const uint32 *pInts = Base(); + return ( pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 && pInts[3] == 0 && pInts[4] == 0 && pInts[5] == 0 && pInts[6] == 0 && pInts[7] == 0 ); +} + +template<> +FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<256> >::CopyTo(CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pInts = Base(); + + pDest[0] = pInts[0]; + pDest[1] = pInts[1]; + pDest[2] = pInts[2]; + pDest[3] = pInts[3]; + pDest[4] = pInts[4]; + pDest[5] = pInts[5]; + pDest[6] = pInts[6]; + pDest[7] = pInts[7]; +} + +template<> +FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<128> >::And(const CBitVecT &addStr, CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pOperand1 = Base(); + const uint32 *pOperand2 = addStr.Base(); + + pDest[0] = pOperand1[0] & pOperand2[0]; + pDest[1] = pOperand1[1] & pOperand2[1]; + pDest[2] = pOperand1[2] & pOperand2[2]; + pDest[3] = pOperand1[3] & pOperand2[3]; +} + +template<> +FORCEINLINE_TEMPLATE bool CBitVecT< CFixedBitVecBase<128> >::IsAllClear(void) const +{ + const uint32 *pInts = Base(); + return ( pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 && pInts[3] == 0 ); +} + +template<> +FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<128> >::CopyTo(CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pInts = Base(); + + pDest[0] = pInts[0]; + pDest[1] = pInts[1]; + pDest[2] = pInts[2]; + pDest[3] = pInts[3]; +} + +template<> +inline void CBitVecT< CFixedBitVecBase<96> >::And(const CBitVecT &addStr, CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pOperand1 = Base(); + const uint32 *pOperand2 = addStr.Base(); + + pDest[0] = pOperand1[0] & pOperand2[0]; + pDest[1] = pOperand1[1] & pOperand2[1]; + pDest[2] = pOperand1[2] & pOperand2[2]; +} + +template<> +inline bool CBitVecT< CFixedBitVecBase<96> >::IsAllClear(void) const +{ + const uint32 *pInts = Base(); + return ( pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 ); +} + +template<> +inline void CBitVecT< CFixedBitVecBase<96> >::CopyTo(CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pInts = Base(); + + pDest[0] = pInts[0]; + pDest[1] = pInts[1]; + pDest[2] = pInts[2]; +} + +template<> +inline void CBitVecT< CFixedBitVecBase<64> >::And(const CBitVecT &addStr, CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pOperand1 = Base(); + const uint32 *pOperand2 = addStr.Base(); + + pDest[0] = pOperand1[0] & pOperand2[0]; + pDest[1] = pOperand1[1] & pOperand2[1]; +} + +template<> +inline bool CBitVecT< CFixedBitVecBase<64> >::IsAllClear(void) const +{ + const uint32 *pInts = Base(); + return ( pInts[0] == 0 && pInts[1] == 0 ); +} + +template<> +inline void CBitVecT< CFixedBitVecBase<64> >::CopyTo(CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pInts = Base(); + + pDest[0] = pInts[0]; + pDest[1] = pInts[1]; +} + +template<> +inline void CBitVecT< CFixedBitVecBase<32> >::And(const CBitVecT &addStr, CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pOperand1 = Base(); + const uint32 *pOperand2 = addStr.Base(); + + pDest[0] = pOperand1[0] & pOperand2[0]; +} + +template<> +inline bool CBitVecT< CFixedBitVecBase<32> >::IsAllClear(void) const +{ + const uint32 *pInts = Base(); + + return ( pInts[0] == 0 ); +} + +template<> +inline void CBitVecT< CFixedBitVecBase<32> >::CopyTo(CBitVecT *out) const +{ + uint32 * pDest = out->Base(); + const uint32 *pInts = Base(); + + pDest[0] = pInts[0]; +} + +//----------------------------------------------------------------------------- + +template <> +inline uint32 CBitVecT< CFixedBitVecBase<32> >::Get( uint32 bitNum ) const +{ + return ( *Base() & BitVec_Bit( bitNum ) ); +} + +//----------------------------------------------------------------------------- + +template <> +inline bool CBitVecT< CFixedBitVecBase<32> >::IsBitSet( int bitNum ) const +{ + return ( ( *Base() & BitVec_Bit( bitNum ) ) != 0 ); +} + +//----------------------------------------------------------------------------- + +template <> +inline void CBitVecT< CFixedBitVecBase<32> >::Set( int bitNum ) +{ + *Base() |= BitVec_Bit( bitNum ); +} + +//----------------------------------------------------------------------------- + +template <> +inline void CBitVecT< CFixedBitVecBase<32> >::Clear(int bitNum) +{ + *Base() &= ~BitVec_Bit( bitNum ); +} + +//----------------------------------------------------------------------------- + +template <> +inline void CBitVecT< CFixedBitVecBase<32> >::Set( int bitNum, bool bNewVal ) +{ + uint32 bitMask = BitVec_Bit( bitNum ); + if ( bNewVal ) + { + *Base() |= bitMask; + } + else + { + *Base() &= ~bitMask; + } +} + + +//----------------------------------------------------------------------------- + +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// Purpose: Resizes the bit string to a new number of bits +// Input : resizeNumBits - +//----------------------------------------------------------------------------- +inline void CVarBitVecBase::Resize( int resizeNumBits, bool bClearAll ) +{ + Assert( resizeNumBits >= 0 && resizeNumBits <= USHRT_MAX ); + + int newIntCount = CalcNumIntsForBits( resizeNumBits ); + if ( newIntCount != GetNumDWords() ) + { + if ( Base() ) + { + ReallocInts( newIntCount ); + if ( !bClearAll && resizeNumBits >= GetNumBits() ) + { + Base()[GetNumDWords() - 1] &= GetEndMask(); + Plat_FastMemset( Base() + GetNumDWords(), 0, (newIntCount - GetNumDWords()) * sizeof(int) ); + } + } + else + { + // Figure out how many ints are needed + AllocInts( newIntCount ); + // Initialize bitstring by clearing all bits + bClearAll = true; + } + + m_numInts = newIntCount; + } + else if ( !bClearAll && resizeNumBits >= GetNumBits() && Base() ) + { + Base()[GetNumDWords() - 1] &= GetEndMask(); + } + + if ( bClearAll && Base() ) + { + Plat_FastMemset( Base(), 0, newIntCount * sizeof(int) ); + } + + // store the new size and end mask + m_numBits = resizeNumBits; +} + +//----------------------------------------------------------------------------- +// Purpose: Allocate the storage for the ints +// Input : numInts - +//----------------------------------------------------------------------------- +inline void CVarBitVecBase::AllocInts( int numInts ) +{ + Assert( !m_pInt ); + + if ( numInts == 0 ) + return; + + if ( numInts == 1 ) + { + m_pInt = &m_iBitStringStorage; + return; + } + + m_pInt = (uint32 *)malloc( numInts * sizeof(int) ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Reallocate the storage for the ints +// Input : numInts - +//----------------------------------------------------------------------------- +inline void CVarBitVecBase::ReallocInts( int numInts ) +{ + Assert( Base() ); + if ( numInts == 0) + { + FreeInts(); + return; + } + + if ( m_pInt == &m_iBitStringStorage ) + { + if ( numInts != 1 ) + { + m_pInt = ((uint32 *)malloc( numInts * sizeof(int) )); + *m_pInt = m_iBitStringStorage; + } + + return; + } + + if ( numInts == 1 ) + { + m_iBitStringStorage = *m_pInt; + free( m_pInt ); + m_pInt = &m_iBitStringStorage; + return; + } + + m_pInt = (uint32 *)realloc( m_pInt, numInts * sizeof(int) ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Free storage allocated with AllocInts +//----------------------------------------------------------------------------- +inline void CVarBitVecBase::FreeInts( void ) +{ + if ( m_numInts > 1 ) + { + free( m_pInt ); + } + m_pInt = NULL; +} + +#include "tier0/memdbgoff.h" + +// ------------------------------------------------------------------------ // +// CBitVecAccessor inlines. +// ------------------------------------------------------------------------ // + +inline CBitVecAccessor::CBitVecAccessor(uint32 *pDWords, int iBit) +{ + m_pDWords = pDWords; + m_iBit = iBit; +} + + +inline void CBitVecAccessor::operator=(int val) +{ + if(val) + m_pDWords[m_iBit >> 5] |= (1 << (m_iBit & 31)); + else + m_pDWords[m_iBit >> 5] &= ~(unsigned long)(1 << (m_iBit & 31)); +} + +inline CBitVecAccessor::operator uint32() +{ + return m_pDWords[m_iBit >> 5] & (1 << (m_iBit & 31)); +} + + +//============================================================================= + +#endif // BITVEC_H From 27a70423d971649081de4a186851ebf584d5a940 Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Fri, 11 Sep 2020 07:50:05 +0900 Subject: [PATCH 3/5] Overhaul of Entity Transmit. --- .../packages/source-python/entities/_base.py | 69 + .../source-python/entities/transmit.py | 14 +- .../packages/source-python/players/_base.py | 58 + .../modules/entities/entities_transmit.cpp | 358 +++-- src/core/modules/entities/entities_transmit.h | 107 +- .../entities/entities_transmit_wrap.cpp | 47 +- src/core/sp_main.cpp | 7 + src/patches/csgo/public/bitvec.h | 1417 ----------------- 8 files changed, 505 insertions(+), 1572 deletions(-) mode change 100644 => 100755 addons/source-python/packages/source-python/entities/_base.py mode change 100644 => 100755 src/core/sp_main.cpp delete mode 100755 src/patches/csgo/public/bitvec.h diff --git a/addons/source-python/packages/source-python/entities/_base.py b/addons/source-python/packages/source-python/entities/_base.py old mode 100644 new mode 100755 index eec4b211a..a679e4195 --- a/addons/source-python/packages/source-python/entities/_base.py +++ b/addons/source-python/packages/source-python/entities/_base.py @@ -67,6 +67,7 @@ # Source.Python Imports # Entities from _entities._entity import BaseEntity +from _entities._transmit import TransmitManager # ============================================================================= @@ -779,6 +780,71 @@ def set_parent(self, parent, attachment=INVALID_ATTACHMENT_INDEX): return [parent, attachment] + # ========================================================================= + # >> ENTITY TRANSMIT FUNCTIONALITY + # ========================================================================= + def hide(self): + """Hide the entity from all players.""" + TransmitManager.hide(self.index) + + def hide_from(self, player_index): + """Hide the entity from player. + + :param int player_index: + The target player index to hide this entity. + """ + TransmitManager.hide_from(self.index, player_index) + + def show(self): + """Show the entity to all players.""" + TransmitManager.show(self.index) + + def show_from(self, player_index): + """Show the entity to player. + + :param int player_index: + The target player index to show this entity. + """ + TransmitManager.show_from(self.index, player_index) + + def reset(self): + """Reset the entity's hidden/shown state.""" + TransmitManager.reset(self.index) + + def reset_from(self, player_index): + """Reset the player's entity hidden/shown state. + + :param int player_index: + The target player index to reset the player's hidden/shown state. + """ + TransmitManager.reset_from(self.index, player_index) + + def is_hidden(self): + """Return True if the entity is hidden from any player. + + :rtype: bool + """ + return TransmitManager.is_hidden(self.index) + + def is_hidden_from(self, player_index): + """Return True if the entity is hidden from the player. + + :param int player_index: + The target player index to check if the entity is hidden. + :rtype: bool + """ + return TransmitManager.is_hidden_from(self.index, player_index) + + def get_hidden_player(self): + """Get the players where the entity is hidden. + + :return: + A tuple containing :class:`players.entity.Player` instances + in which the entity is hidden. + :rtype: tuple + """ + return TransmitManager.get_hidden_player(self.index) + # ============================================================================= # >> LISTENERS @@ -814,3 +880,6 @@ def _on_entity_deleted(base_entity): # Invalidate the internal entity caches for this entity for cls in _entity_classes: cls.cache.pop(index, None) + + # Reset the entity's hidden state. + TransmitManager.reset(index) diff --git a/addons/source-python/packages/source-python/entities/transmit.py b/addons/source-python/packages/source-python/entities/transmit.py index e79237a22..16bb788a2 100755 --- a/addons/source-python/packages/source-python/entities/transmit.py +++ b/addons/source-python/packages/source-python/entities/transmit.py @@ -15,7 +15,6 @@ from filters.entities import EntityIter # Listeners from listeners import on_entity_created_listener_manager -from listeners import on_entity_deleted_listener_manager # ============================================================================ @@ -23,14 +22,15 @@ # ============================================================================ # Source.Python # Entities -from _entities._transmit import transmit_manager +from _entities._transmit import TransmitManager # ============================================================================ # >> ALL DECLARATION # ============================================================================ __all__ = ( - 'transmit_manager', + 'TransmitManager', + 'reset_hidden_state', ) @@ -38,3 +38,11 @@ # >> CLASSES # ============================================================================ + +# ============================================================================= +# >> FUNCTIONS +# ============================================================================= +def reset_hidden_state(): + """Reset all entities' hidden/shown state.""" + TransmitManager.reset_all() + diff --git a/addons/source-python/packages/source-python/players/_base.py b/addons/source-python/packages/source-python/players/_base.py index 3cfcda061..2a067491e 100755 --- a/addons/source-python/packages/source-python/players/_base.py +++ b/addons/source-python/packages/source-python/players/_base.py @@ -73,6 +73,14 @@ from auth.manager import auth_manager +# ============================================================================= +# >> FORWARD IMPORTS +# ============================================================================= +# Source.Python Imports +# Entities +from _entities._transmit import TransmitManager + + # ============================================================================= # >> CLASSES # ============================================================================= @@ -994,6 +1002,56 @@ def drop_weapon(self, weapon, target=None, velocity=None): """ return [weapon, target, velocity] + # ========================================================================= + # >> PLAYER TRANSMIT FUNCTIONALITY + # ========================================================================= + def hide_entity(self, entity_index): + """Hide the entity from player. + + :param int entity_index: + The target entity index to hide from the player. + """ + TransmitManager.hide_from(entity_index, self.index) + + def show_entity(self, entity_index): + """Show the entity to player. + + :param int entity_index: + The target entity index to show the entity to player. + """ + TransmitManager.show_from(entity_index, self.index) + + def reset_entity(self, entity_index): + """Reset the player's entity hidden/shown state. + + :param int entity_index: + The target entity_index to reset the player's hidden/shown state. + """ + TransmitManager.reset_from(entity_index, self.index) + + def reset_player(self): + """Reset the player's hidden/shown state on all entities.""" + TransmitManager.reset_player(self.index) + + def is_entity_hidden(self, entity_index): + """Return True if the entity is hidden from the player. + + :param int entity_index: + The target entity index to check if the entity is hidden. + :rtype: bool + """ + return TransmitManager.is_hidden_from(entity_index, self.index) + + def get_hidden_entity(self): + """Get the entities that are hidden from the player. + + :return: + A tuple containing :class:`entities.entity.Entity` instances + that are hidden from the player. + :rtype: tuple + """ + return TransmitManager.get_hidden_entity(self.index) + # ============================================================================= # >> HELPER FUNCTIONS diff --git a/src/core/modules/entities/entities_transmit.cpp b/src/core/modules/entities/entities_transmit.cpp index ff7d1fedd..a6e7b53ed 100755 --- a/src/core/modules/entities/entities_transmit.cpp +++ b/src/core/modules/entities/entities_transmit.cpp @@ -28,6 +28,7 @@ // Includes. //----------------------------------------------------------------------------- #include "eiface.h" +#include "strtools.h" #include "utilities/conversions.h" #include "modules/entities/entities_transmit.h" @@ -39,12 +40,13 @@ // Eternal variables. //----------------------------------------------------------------------------- extern IServerGameEnts *gameents; +extern CGlobalVars *gpGlobals; +extern IPlayerInfoManager *playerinfomanager; //----------------------------------------------------------------------------- // Static variables. //----------------------------------------------------------------------------- -std::once_flag CTransmitManager::init_flag; CTransmitManager* CTransmitManager::instance = nullptr; @@ -52,19 +54,88 @@ CTransmitManager* CTransmitManager::instance = nullptr; // CTransmitManager class. //----------------------------------------------------------------------------- CTransmitManager::CTransmitManager() + :m_arrayFilterIndexes() { - initialize(); + CFunctionInfo *pFunctionInfo = GetFunctionInfo(&IServerGameEnts::CheckTransmit); + if (!pFunctionInfo) + BOOST_RAISE_EXCEPTION( + PyExc_ValueError, + "Failed to retrieve CheckTransmit's info." + ) + + CFunction *pFunction = CPointer((unsigned long)((void *)gameents)).MakeVirtualFunction(*pFunctionInfo); + delete pFunctionInfo; + + if (!pFunction || !pFunction->IsHookable()) + BOOST_RAISE_EXCEPTION( + PyExc_ValueError, + "CheckTransmit is invalid or not hookable." + ) + + void *pAddr = (void *)pFunction->m_ulAddr; + CHook *pHook = GetHookManager()->FindHook(pAddr); + if (!pHook) + { + pHook = GetHookManager()->HookFunction(pAddr, pFunction->m_pCallingConvention); + if (!pHook) + BOOST_RAISE_EXCEPTION( + PyExc_ValueError, + "Failed to hook CheckTransmit." + ) + } + + //m_pCheckTransmit = (void *)pFunction->m_ulAddr; + delete pFunction; + + pHook->AddCallback( + HOOKTYPE_POST, + (HookHandlerFn *)&CTransmitManager::_post_check_transmit + ); + + current_clients = 0; + + IPlayerInfo* pPlayerInfo = nullptr; + + for (unsigned int i=1; i <= (unsigned int) gpGlobals->maxClients; ++i) + { + if (!PlayerInfoFromIndex(i, pPlayerInfo)) + continue; + + if (pPlayerInfo->IsFakeClient() || V_strstr(pPlayerInfo->GetNetworkIDString(), "BOT")) + continue; - for( auto& filters: m_vecFilters) + ++current_clients; + m_arrayFilterIndexes[i-1] = current_clients; + } + + unsigned int filter_size = bit_ceil(current_clients); + if (filter_size < 4) + filter_size = 4; + + m_vecFilters.resize(filter_size); + + for(auto it = m_vecFilters.begin(); it != m_vecFilters.begin()+current_clients; ++it) { - filters.first.SetAll(); + it->hide.SetAll(); } } +CTransmitManager::~CTransmitManager() +{ +/* + CHook *pHook = GetHookManager()->FindHook(m_pCheckTransmit); + if (pHook) + pHook->RemoveCallback(HOOKTYPE_POST, (HookHandlerFn *)&CTransmitManager::_post_check_transmit); +*/ +} + + CTransmitManager* CTransmitManager::get_instance() { - std::call_once(init_flag, create); + if (!instance) + create(); + return instance; } @@ -75,197 +146,272 @@ void CTransmitManager::create() } +/* void CTransmitManager::destroy() { - if(instance) - instance->finalize(); - delete instance; instance = nullptr; } +*/ -void CTransmitManager::initialize() +void CTransmitManager::add_player(edict_t* pEdict, unsigned int player_index) { - CFunctionInfo *pInfo = GetFunctionInfo(&IServerGameEnts::CheckTransmit); - if (!pInfo) - BOOST_RAISE_EXCEPTION( - PyExc_ValueError, - "Failed to retrieve CheckTransmit's info." - ) - - CFunction *pFunc = CPointer((unsigned long)((void *)gameents)).MakeVirtualFunction(*pInfo); - delete pInfo; + static ConVar* sv_replaybots = cvar->FindVar("sv_replaybots"); + static ConVar* sv_stressbots = cvar->FindVar("sv_stressbots"); + IPlayerInfo* pPlayerInfo = playerinfomanager->GetPlayerInfo(pEdict); + + if ((pPlayerInfo && + (pPlayerInfo->IsFakeClient() || V_strstr(pPlayerInfo->GetNetworkIDString(), "BOT"))) && ( + (!sv_replaybots || !sv_replaybots->GetBool()) || + (!sv_stressbots || !sv_stressbots->GetBool()))) + return; - if (!pFunc || !pFunc->IsHookable()) - BOOST_RAISE_EXCEPTION( - PyExc_ValueError, - "CheckTransmit is invalid or not hookable." - ) + unsigned int filter_size = m_vecFilters.size(); + if (current_clients >= filter_size) + m_vecFilters.resize(filter_size*2); - m_pCheckTransmit = (void *)pFunc->m_ulAddr; - CHook *pHook = GetHookManager()->FindHook(m_pCheckTransmit); - if (!pHook) + unsigned char filter_index; + if (find_filter_index(player_index, filter_index)) { - pHook = GetHookManager()->HookFunction(m_pCheckTransmit, pFunc->m_pCallingConvention); - if (!pHook) - BOOST_RAISE_EXCEPTION( - PyExc_ValueError, - "Failed to hook CheckTransmit." - ) - } + ++current_clients; + m_arrayFilterIndexes[player_index-1] = filter_index; - pFunc->m_bAllocatedCallingConvention = false; - delete pFunc; + Filter& filter = m_vecFilters[filter_index-1]; - pHook->AddCallback( - HOOKTYPE_POST, - (HookHandlerFn *)&CTransmitManager::_post_check_transmit - ); + filter.hide.SetAll(); + filter.show.ClearAll(); + } } -void CTransmitManager::finalize() +void CTransmitManager::remove_player(edict_t* pEdict, unsigned int player_index) { - CHook *pHook = GetHookManager()->FindHook(m_pCheckTransmit); - if (pHook) + unsigned char filter_index; + if (get_filter_index(player_index, filter_index)) { - pHook->RemoveCallback( - HOOKTYPE_POST, - (HookHandlerFn *)&CTransmitManager::_post_check_transmit - ); + --current_clients; + m_arrayFilterIndexes[player_index-1] = 0; } } -void CTransmitManager::hide(int entity_index) +void CTransmitManager::hide(unsigned int entity_index) { - if (entity_index == 0) + if (entity_index < 1 || entity_index >= MAX_EDICTS) return; - for(int i = 0; i < m_vecFilters.size(); ++i) - { - if ((i+1) == entity_index) - continue; - - filter_pair& filters = m_vecFilters[i]; + for(auto it = m_vecFilters.begin(); it != m_vecFilters.begin()+current_clients; ++it) + { + it->hide.Set((int) entity_index, false); + it->show.Set((int) entity_index, false); + } - filters.first.Set(entity_index, false); - filters.second.Set(entity_index, false); - } + reset_from(entity_index, entity_index); } -void CTransmitManager::hide_from(int entity_index, int player_index) +void CTransmitManager::hide_from(unsigned int entity_index, unsigned int player_index) { - if (entity_index == 0) + if (entity_index < 1 || entity_index >= MAX_EDICTS) return; - player_index -= 1; + if (player_index < 1 || player_index > (unsigned int) gpGlobals->maxClients) + return; if (entity_index == player_index) return; - filter_pair& filters = m_vecFilters[player_index]; + unsigned char filter_index; + if (get_filter_index(player_index, filter_index)) + { + Filter& filter = m_vecFilters[filter_index-1]; - filters.first.Set(entity_index, false); - filters.second.Set(entity_index, false); + filter.hide.Set((int) entity_index, false); + filter.show.Set((int) entity_index, false); + } } -void CTransmitManager::unhide(int entity_index) +void CTransmitManager::show(unsigned int entity_index) { - for( auto& filters: m_vecFilters) + if (entity_index < 1 || entity_index >= MAX_EDICTS) + return; + + for( auto it = m_vecFilters.begin(); it != m_vecFilters.begin()+current_clients; ++it) { - filters.first.Set(entity_index, true); - filters.second.Set(entity_index, true); + it->hide.Set((int) entity_index, true); + it->show.Set((int) entity_index, true); } } -void CTransmitManager::unhide_from(int entity_index, int player_index) +void CTransmitManager::show_from(unsigned int entity_index, unsigned int player_index) { - player_index -= 1; + if (entity_index < 1 || entity_index >= MAX_EDICTS) + return; + + if (player_index < 1 || player_index > (unsigned int) gpGlobals->maxClients) + return; - filter_pair& filters = m_vecFilters[player_index]; + unsigned char filter_index; + if (get_filter_index(player_index, filter_index)) + { + Filter& filter = m_vecFilters[filter_index-1]; - filters.first.Set(entity_index, true); - filters.second.Set(entity_index, true); + filter.hide.Set((int) entity_index, true); + filter.show.Set((int) entity_index, true); + } } -void CTransmitManager::reset(int entity_index) +void CTransmitManager::reset(unsigned int entity_index) { - for( auto& filters: m_vecFilters) + if (entity_index < 1 || entity_index >= MAX_EDICTS) + return; + + for( auto it = m_vecFilters.begin(); it != m_vecFilters.begin()+current_clients; ++it) { - filters.first.Set(entity_index, true); - filters.second.Set(entity_index, false); + it->hide.Set((int) entity_index, true); + it->show.Set((int) entity_index, false); } } -void CTransmitManager::reset_from(int entity_index, int player_index) +void CTransmitManager::reset_from(unsigned int entity_index, unsigned int player_index) { - player_index -= 1; - m_vecFilters[player_index].first.Set(entity_index, true); - m_vecFilters[player_index].second.Set(entity_index, false); + if (entity_index < 1 || entity_index >= MAX_EDICTS) + return; + + if (player_index < 1 || player_index > (unsigned int) gpGlobals->maxClients) + return; + + unsigned char filter_index; + if (get_filter_index(player_index, filter_index)) + { + Filter& filter = m_vecFilters[filter_index-1]; + + filter.hide.Set((int) entity_index, true); + filter.show.Set((int) entity_index, false); + } +} + + +void CTransmitManager::reset_player(unsigned int player_index) +{ + if (player_index < 1 || player_index > (unsigned int) gpGlobals->maxClients) + return; + + unsigned char filter_index; + if (get_filter_index(player_index, filter_index)) + { + Filter& filter = m_vecFilters[filter_index-1]; + + filter.hide.SetAll(); + filter.show.ClearAll(); + } } void CTransmitManager::reset_all() { - for( auto& filters: m_vecFilters) + for( auto it = m_vecFilters.begin(); it != m_vecFilters.begin()+current_clients; ++it) { - filters.first.SetAll(); - filters.second.ClearAll(); + it->hide.SetAll(); + it->show.ClearAll(); } } -bool CTransmitManager::is_hidden(int entity_index) +bool CTransmitManager::is_hidden(unsigned int entity_index) { + if (entity_index < 1 || entity_index >= MAX_EDICTS) + return false; + bool hidden_state = false; - for( auto& filters: m_vecFilters) + for( auto it = m_vecFilters.begin(); it != m_vecFilters.begin()+current_clients; ++it) { - hidden_state |= (!filters.first.IsBitSet(entity_index)); + hidden_state |= (!it->hide.IsBitSet((int) entity_index)); } return hidden_state; } -bool CTransmitManager::is_hidden_from(int entity_index, int player_index) +bool CTransmitManager::is_hidden_from(unsigned int entity_index, unsigned int player_index) { - player_index -= 1; + if (entity_index < 1 || entity_index >= MAX_EDICTS) + return false; + + if (player_index < 1 || player_index > (unsigned int) gpGlobals->maxClients) + return false; + + unsigned char filter_index; + if (get_filter_index(player_index, filter_index)) + { + Filter& filter = m_vecFilters[filter_index-1]; + + return (!filter.hide.IsBitSet((int) entity_index)); + } - return (!m_vecFilters[player_index].first.IsBitSet(entity_index)); + return false; } -tuple CTransmitManager::get_hidden_states(int entity_index) +boost::python::tuple CTransmitManager::get_hidden_player(unsigned int entity_index) { - list player_list; + if (entity_index < 1 || entity_index >= MAX_EDICTS) + return boost::python::tuple(); + + static boost::python::object Player = boost::python::import("players.entity").attr("Player"); - for(int i = 0; i < m_vecFilters.size(); ++i) - { - if (!m_vecFilters[i].first.IsBitSet(entity_index)) - player_list.append(i+1); - } + boost::python::list player_list; + + for (unsigned int i=1; i <= (unsigned int) gpGlobals->maxClients; ++i) + { + if (is_hidden_from(entity_index, i)) + player_list.append(Player(i)); + } - return tuple(player_list); + return boost::python::tuple(player_list); } -void CTransmitManager::handle_filters(CCheckTransmitInfo* pInfo, unsigned int player_index) +boost::python::tuple CTransmitManager::get_hidden_entity(unsigned int player_index) { - player_index -= 1; + if (player_index < 1 || player_index > (unsigned int) gpGlobals->maxClients) + return boost::python::tuple(); + + static boost::python::object Entity = boost::python::import("entities.entity").attr("Entity"); - TransmitStates_t* transmit_edict = pInfo->m_pTransmitEdict; - filter_pair& filters = m_vecFilters[player_index]; + boost::python::list entity_list; - transmit_edict->And(filters.first, transmit_edict); - transmit_edict->Or(filters.second, transmit_edict); + for (unsigned int i=1; i < MAX_EDICTS; ++i) + { + if (is_hidden_from(i, player_index)) + entity_list.append(Entity(i)); + } + + return boost::python::tuple(entity_list); +} + + +void CTransmitManager::handle_filters(TransmitStates_t* pTransmitEdict, unsigned int player_index) +{ + unsigned char filter_index; + if (get_filter_index(player_index, filter_index)) + { + Filter& filter = m_vecFilters[filter_index-1]; + + uint32* base = pTransmitEdict->Base(); + const uint32* hide = filter.hide.Base(); + const uint32* show = filter.show.Base(); + for (int i = 0; i < CalcNumIntsForBits(MAX_EDICTS); ++i) + { + base[i] = (base[i] & hide[i]) | show[i]; + } + } } @@ -275,13 +421,13 @@ bool CTransmitManager::_post_check_transmit(HookType_t eHookType, CHook* pHook) if (!nEdicts) return false; - CCheckTransmitInfo* pInfo = pHook->GetArgument(1); + CCheckTransmitInfo* pTransmitInfo = pHook->GetArgument(1); unsigned int player_index; - if (!IndexFromEdict(pInfo->m_pClientEnt, player_index)) + if (!IndexFromEdict(pTransmitInfo->m_pClientEnt, player_index)) return false; - instance->handle_filters(pInfo, player_index); + instance->handle_filters(pTransmitInfo->m_pTransmitEdict, player_index); return false; } diff --git a/src/core/modules/entities/entities_transmit.h b/src/core/modules/entities/entities_transmit.h index 626d04457..db6e74a89 100755 --- a/src/core/modules/entities/entities_transmit.h +++ b/src/core/modules/entities/entities_transmit.h @@ -30,22 +30,24 @@ //----------------------------------------------------------------------------- // Includes. //----------------------------------------------------------------------------- -#include -#include +#include +#include #include +#include + +#ifdef _WIN32 + #include +#endif -#include "public/const.h" +// Source SDK #include "public/bitvec.h" -#include "public/tier1/utlvector.h" +// Source.Python #include "utilities/baseentity.h" - -#include "modules/listeners/listeners_manager.h" #include "modules/memory/memory_function.h" // Boost.Python #include "boost/python.hpp" -using namespace boost::python; //----------------------------------------------------------------------------- @@ -54,6 +56,15 @@ using namespace boost::python; typedef CBitVec TransmitStates_t; +//----------------------------------------------------------------------------- +// Filter struct. +//----------------------------------------------------------------------------- +struct Filter{ + TransmitStates_t hide; + TransmitStates_t show; +}; + + //----------------------------------------------------------------------------- // CTransmitManager class. //----------------------------------------------------------------------------- @@ -61,46 +72,84 @@ class CTransmitManager { private: CTransmitManager(); + ~CTransmitManager(); - void initialize(); - void finalize(); - - void handle_filters(CCheckTransmitInfo* pInfo, unsigned int player_index); + void handle_filters(TransmitStates_t* pTransmitEdict, unsigned int player_index); static bool _post_check_transmit(HookType_t eHookType, CHook *pHook); public: - using filter_pair = std::pair; - static CTransmitManager* get_instance(); static void create(); - static void destroy(); + //static void destroy(); - void hide(int entity_index); - void hide_from(int entity_index, int player_index); + void add_player(edict_t* pEdict, unsigned int player_index); + void remove_player(edict_t* pEdict, unsigned int player_index); - void unhide(int entity_index); - void unhide_from(int entity_index, int player_index); + void hide(unsigned int entity_index); + void hide_from(unsigned int entity_index, unsigned int player_index); - void reset(int entity_index); - void reset_from(int entity_index, int player_index); - void reset_all(); + void show(unsigned int entity_index); + void show_from(unsigned int entity_index, unsigned int player_index); - bool is_hidden(int entity_index); - bool is_hidden_from(int entity_index, int player_index); + void reset(unsigned int entity_index); + void reset_from(unsigned int entity_index, unsigned int player_index); + void reset_player(unsigned int player_index); + void reset_all(); - tuple get_hidden_states(int entity_index); + bool is_hidden(unsigned int entity_index); + bool is_hidden_from(unsigned int entity_index, unsigned int player_index); + + boost::python::tuple get_hidden_player(unsigned int entity_index); + boost::python::tuple get_hidden_entity(unsigned int player_index); + + inline bool find_filter_index(unsigned int player_index, unsigned char& filter_index) + { + for (unsigned int i = 1; i <= m_arrayFilterIndexes.size(); ++i) + { + auto it = std::find(m_arrayFilterIndexes.begin(), m_arrayFilterIndexes.end(), i); + if (it == m_arrayFilterIndexes.end()) + { + filter_index = i; + return true; + } + } + return false; + } + + inline bool get_filter_index(unsigned int player_index, unsigned char& filter_index) + { + filter_index = m_arrayFilterIndexes[player_index-1]; + if (filter_index) + return true; + else + return false; + } private: - static std::once_flag init_flag; - static CTransmitManager* instance; + static CTransmitManager* instance; - void* m_pCheckTransmit = nullptr; + //void* m_pCheckTransmit; - std::vector> m_vecFilters = decltype(m_vecFilters)(ABSOLUTE_PLAYER_LIMIT); + unsigned int current_clients; + std::vector m_vecFilters; + std::array m_arrayFilterIndexes; }; -inline CTransmitManager *GetTransmitManager() { return CTransmitManager::get_instance(); } + +//----------------------------------------------------------------------------- +// Functions. +//----------------------------------------------------------------------------- +inline unsigned int bit_ceil(unsigned int x) +{ +#ifdef _WIN32 + unsigned long ret; + _BitScanReverse(&ret, (x-1)); + return 1 << (32 - (31 ^ ret));//(1 << (32 - __lzcnt(x)))) +#else + return 1 << (32 - __builtin_clz(x-1)); +#endif +} #endif // _ENTITIES_TRANSMIT_H diff --git a/src/core/modules/entities/entities_transmit_wrap.cpp b/src/core/modules/entities/entities_transmit_wrap.cpp index 51ff87954..f387cb770 100755 --- a/src/core/modules/entities/entities_transmit_wrap.cpp +++ b/src/core/modules/entities/entities_transmit_wrap.cpp @@ -58,72 +58,85 @@ void export_transmit_manager(scope _transmit) // Class methods .def("hide", &CTransmitManager::hide, - "", + "Hide the entity from all players.", ("entity_index") ) .def("hide_from", &CTransmitManager::hide_from, - "", + "Hide the entity from player.", ("entity_index", "player_index") ) - .def("unhide", - &CTransmitManager::unhide, - "", + .def("show", + &CTransmitManager::show, + "Show the entity to all players.", ("entity_index") ) - .def("unhide_from", - &CTransmitManager::unhide_from, - "", + .def("show_from", + &CTransmitManager::show_from, + "Show the entity to player.", ("entity_index", "player_index") ) .def("reset", &CTransmitManager::reset, - "", + "Reset the entity's hidden/shown state.", ("entity_index") ) .def("reset_from", &CTransmitManager::reset_from, - "", + "Reset the player's entity hidden/shown state.", ("entity_index", "player_index") ) + .def("reset_player", + &CTransmitManager::reset_player, + "Reset the player's hidden/shown state on all entities.", + ("player_index") + ) + .def("reset_all", &CTransmitManager::reset_all, - "" + "Reset all entities' hidden/shown state." ) .def("is_hidden", &CTransmitManager::is_hidden, - "", + "Return True if the entity is hidden from any player.", ("entity_index") ) .def("is_hidden_from", &CTransmitManager::is_hidden_from, - "", + "Return True if the entity is hidden from the player.", ("entity_index", "player_index") ) - .def("get_hidden_states", - &CTransmitManager::get_hidden_states, - "", + + .def("get_hidden_player", + &CTransmitManager::get_hidden_player, + "Get the players where the entity is hidden.", ("entity_index") ) + .def("get_hidden_entity", + &CTransmitManager::get_hidden_entity, + "Get the entities that are hidden from the player.", + ("player_index") + ) + // Add memory tools... ADD_MEM_TOOLS(CTransmitManager) ; // Singleton... - _transmit.attr("transmit_manager") = object(ptr(GetTransmitManager())); + _transmit.attr("TransmitManager") = object(ptr(CTransmitManager::get_instance())); } diff --git a/src/core/sp_main.cpp b/src/core/sp_main.cpp old mode 100644 new mode 100755 index d1f237c66..795363ec0 --- a/src/core/sp_main.cpp +++ b/src/core/sp_main.cpp @@ -60,6 +60,7 @@ #include "utilities/conversions.h" #include "modules/entities/entities_entity.h" #include "modules/core/core.h" +#include "modules/entities/entities_transmit.h" #ifdef _WIN32 #include "Windows.h" @@ -487,6 +488,9 @@ void CSourcePython::ClientActive( edict_t *pEntity ) if (!IndexFromEdict(pEntity, iEntityIndex)) return; + static CTransmitManager* transmit_manager = CTransmitManager::get_instance(); + transmit_manager->add_player(pEntity, iEntityIndex); + CALL_LISTENERS(OnClientActive, iEntityIndex); } @@ -500,6 +504,9 @@ void CSourcePython::ClientDisconnect( edict_t *pEntity ) return; CALL_LISTENERS(OnClientDisconnect, iEntityIndex); + + static CTransmitManager* transmit_manager = CTransmitManager::get_instance(); + transmit_manager->remove_player(pEntity, iEntityIndex); } //----------------------------------------------------------------------------- diff --git a/src/patches/csgo/public/bitvec.h b/src/patches/csgo/public/bitvec.h deleted file mode 100755 index bb5c49948..000000000 --- a/src/patches/csgo/public/bitvec.h +++ /dev/null @@ -1,1417 +0,0 @@ -//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef BITVEC_H -#define BITVEC_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tier0/dbg.h" -#include "tier0/basetypes.h" - - -class CBitVecAccessor -{ -public: - CBitVecAccessor(uint32 *pDWords, int iBit); - - void operator=(int val); - operator uint32(); - -private: - uint32 *m_pDWords; - int m_iBit; -}; - - -//----------------------------------------------------------------------------- -// Support functions -//----------------------------------------------------------------------------- - -#define LOG2_BITS_PER_INT 5 -#define BITS_PER_INT 32 - -#if _WIN32 && !defined(_X360) -#include -#pragma intrinsic(_BitScanForward) -#endif - -inline int FirstBitInWord( unsigned int elem, int offset ) -{ -#if _WIN32 - if ( !elem ) - return -1; -#if _X360 - // this implements CountTrailingZeros() / BitScanForward() - unsigned int mask = elem-1; - unsigned int comp = ~elem; - elem = mask & comp; - return (32 - _CountLeadingZeros(elem)) + offset; -#else - unsigned long out; - _BitScanForward(&out, elem); - return out + offset; -#endif - -#else - static unsigned firstBitLUT[256] = - { - 0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0, - 3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, - 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0, - 3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, - 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0, - 3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, - 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - }; - unsigned elemByte; - - elemByte = (elem & 0xFF); - if ( elemByte ) - return offset + firstBitLUT[elemByte]; - - elem >>= 8; - offset += 8; - elemByte = (elem & 0xFF); - if ( elemByte ) - return offset + firstBitLUT[elemByte]; - - elem >>= 8; - offset += 8; - elemByte = (elem & 0xFF); - if ( elemByte ) - return offset + firstBitLUT[elemByte]; - - elem >>= 8; - offset += 8; - elemByte = (elem & 0xFF); - if ( elemByte ) - return offset + firstBitLUT[elemByte]; - - return -1; -#endif -} - -//------------------------------------- - -inline unsigned GetEndMask( int numBits ) -{ - static unsigned bitStringEndMasks[] = - { - 0xffffffff, - 0x00000001, - 0x00000003, - 0x00000007, - 0x0000000f, - 0x0000001f, - 0x0000003f, - 0x0000007f, - 0x000000ff, - 0x000001ff, - 0x000003ff, - 0x000007ff, - 0x00000fff, - 0x00001fff, - 0x00003fff, - 0x00007fff, - 0x0000ffff, - 0x0001ffff, - 0x0003ffff, - 0x0007ffff, - 0x000fffff, - 0x001fffff, - 0x003fffff, - 0x007fffff, - 0x00ffffff, - 0x01ffffff, - 0x03ffffff, - 0x07ffffff, - 0x0fffffff, - 0x1fffffff, - 0x3fffffff, - 0x7fffffff, - }; - - return bitStringEndMasks[numBits % BITS_PER_INT]; -} - - -inline int GetBitForBitnum( int bitNum ) -{ - static int bitsForBitnum[] = - { - ( 1 << 0 ), - ( 1 << 1 ), - ( 1 << 2 ), - ( 1 << 3 ), - ( 1 << 4 ), - ( 1 << 5 ), - ( 1 << 6 ), - ( 1 << 7 ), - ( 1 << 8 ), - ( 1 << 9 ), - ( 1 << 10 ), - ( 1 << 11 ), - ( 1 << 12 ), - ( 1 << 13 ), - ( 1 << 14 ), - ( 1 << 15 ), - ( 1 << 16 ), - ( 1 << 17 ), - ( 1 << 18 ), - ( 1 << 19 ), - ( 1 << 20 ), - ( 1 << 21 ), - ( 1 << 22 ), - ( 1 << 23 ), - ( 1 << 24 ), - ( 1 << 25 ), - ( 1 << 26 ), - ( 1 << 27 ), - ( 1 << 28 ), - ( 1 << 29 ), - ( 1 << 30 ), - ( 1 << 31 ), - }; - - return bitsForBitnum[ (bitNum) & (BITS_PER_INT-1) ]; -} - -inline int GetBitForBitnumByte( int bitNum ) -{ - static int bitsForBitnum[] = - { - ( 1 << 0 ), - ( 1 << 1 ), - ( 1 << 2 ), - ( 1 << 3 ), - ( 1 << 4 ), - ( 1 << 5 ), - ( 1 << 6 ), - ( 1 << 7 ), - }; - - return bitsForBitnum[ bitNum & 7 ]; -} - -inline int CalcNumIntsForBits( int numBits ) { return (numBits + (BITS_PER_INT-1)) / BITS_PER_INT; } - -#ifdef _X360 -#define BitVec_Bit( bitNum ) GetBitForBitnum( bitNum ) -#define BitVec_BitInByte( bitNum ) GetBitForBitnumByte( bitNum ) -#else -#define BitVec_Bit( bitNum ) ( 1 << ( (bitNum) & (BITS_PER_INT-1) ) ) -#define BitVec_BitInByte( bitNum ) ( 1 << ( (bitNum) & 7 ) ) -#endif -#define BitVec_Int( bitNum ) ( (bitNum) >> LOG2_BITS_PER_INT ) - - -//----------------------------------------------------------------------------- -// template CBitVecT -// -// Defines the operations relevant to any bit array. Simply requires a base -// class that implements GetNumBits(), Base(), GetNumDWords() & ValidateOperand() -// -// CVarBitVec and CBitVec are the actual classes generally used -// by clients -// - -template -class CBitVecT : public BASE_OPS -{ -public: - CBitVecT(); - CBitVecT(int numBits); // Must be initialized with the number of bits - - void Init(int val = 0); - - // Access the bits like an array. - CBitVecAccessor operator[](int i); - - // Do NOT override bitwise operators (see note in header) - void And(const CBitVecT &andStr, CBitVecT *out) const; - void Or(const CBitVecT &orStr, CBitVecT *out) const; - void Xor(const CBitVecT &orStr, CBitVecT *out) const; - - void Not(CBitVecT *out) const; - - void CopyTo(CBitVecT *out) const; - void Copy( const CBitVecT &other, int nBits=-1 ); - bool Compare( const CBitVecT &other, int nBits=-1 ) const; - - bool IsAllClear(void) const; // Are all bits zero? - bool IsAllSet(void) const; // Are all bits one? - - uint32 Get( uint32 bitNum ) const; - bool IsBitSet( int bitNum ) const; - void Set( int bitNum ); - void Set( int bitNum, bool bNewVal ); - void Clear(int bitNum); - - bool TestAndSet(int bitNum); - - void Set( uint32 offset, uint32 mask ); - void Clear( uint32 offset, uint32 mask ); - uint32 Get( uint32 offset, uint32 mask ); - - void SetAll(void); // Sets all bits - void ClearAll(void); // Clears all bits - - uint32 GetDWord(int i) const; - void SetDWord(int i, uint32 val); - - CBitVecT& operator=(const CBitVecT &other) { other.CopyTo( this ); return *this; } - bool operator==(const CBitVecT &other) { return Compare( other ); } - bool operator!=(const CBitVecT &other) { return !operator==( other ); } - - static void GetOffsetMaskForBit( uint32 bitNum, uint32 *pOffset, uint32 *pMask ) { *pOffset = BitVec_Int( bitNum ); *pMask = BitVec_Bit( bitNum ); } -}; - -//----------------------------------------------------------------------------- -// class CVarBitVecBase -// -// Defines the operations necessary for a variable sized bit array - -class CVarBitVecBase -{ -public: - bool IsFixedSize() const { return false; } - int GetNumBits(void) const { return m_numBits; } - void Resize( int numBits, bool bClearAll = false ); // resizes bit array - - int GetNumDWords() const { return m_numInts; } - uint32 *Base() { return m_pInt; } - const uint32 *Base() const { return m_pInt; } - - void Attach( uint32 *pBits, int numBits ); - bool Detach( uint32 **ppBits, int *pNumBits ); - - int FindNextSetBit(int iStartBit) const; // returns -1 if no set bit was found - -protected: - CVarBitVecBase(); - CVarBitVecBase(int numBits); - CVarBitVecBase( const CVarBitVecBase &from ); - CVarBitVecBase &operator=( const CVarBitVecBase &from ); - ~CVarBitVecBase(void); - - void ValidateOperand( const CVarBitVecBase &operand ) const { Assert(GetNumBits() == operand.GetNumBits()); } - - unsigned GetEndMask() const { return ::GetEndMask( GetNumBits() ); } - -private: - - unsigned short m_numBits; // Number of bits in the bitstring - unsigned short m_numInts; // Number of ints to needed to store bitstring - uint32 m_iBitStringStorage; // If the bit string fits in one int, it goes here - uint32 * m_pInt; // Array of ints containing the bitstring - - void AllocInts( int numInts ); // Free the allocated bits - void ReallocInts( int numInts ); - void FreeInts( void ); // Free the allocated bits -}; - -//----------------------------------------------------------------------------- -// class CFixedBitVecBase -// -// Defines the operations necessary for a fixed sized bit array. -// - -template struct BitCountToEndMask_t { }; -template <> struct BitCountToEndMask_t< 0> { enum { MASK = 0xffffffff }; }; -template <> struct BitCountToEndMask_t< 1> { enum { MASK = 0x00000001 }; }; -template <> struct BitCountToEndMask_t< 2> { enum { MASK = 0x00000003 }; }; -template <> struct BitCountToEndMask_t< 3> { enum { MASK = 0x00000007 }; }; -template <> struct BitCountToEndMask_t< 4> { enum { MASK = 0x0000000f }; }; -template <> struct BitCountToEndMask_t< 5> { enum { MASK = 0x0000001f }; }; -template <> struct BitCountToEndMask_t< 6> { enum { MASK = 0x0000003f }; }; -template <> struct BitCountToEndMask_t< 7> { enum { MASK = 0x0000007f }; }; -template <> struct BitCountToEndMask_t< 8> { enum { MASK = 0x000000ff }; }; -template <> struct BitCountToEndMask_t< 9> { enum { MASK = 0x000001ff }; }; -template <> struct BitCountToEndMask_t<10> { enum { MASK = 0x000003ff }; }; -template <> struct BitCountToEndMask_t<11> { enum { MASK = 0x000007ff }; }; -template <> struct BitCountToEndMask_t<12> { enum { MASK = 0x00000fff }; }; -template <> struct BitCountToEndMask_t<13> { enum { MASK = 0x00001fff }; }; -template <> struct BitCountToEndMask_t<14> { enum { MASK = 0x00003fff }; }; -template <> struct BitCountToEndMask_t<15> { enum { MASK = 0x00007fff }; }; -template <> struct BitCountToEndMask_t<16> { enum { MASK = 0x0000ffff }; }; -template <> struct BitCountToEndMask_t<17> { enum { MASK = 0x0001ffff }; }; -template <> struct BitCountToEndMask_t<18> { enum { MASK = 0x0003ffff }; }; -template <> struct BitCountToEndMask_t<19> { enum { MASK = 0x0007ffff }; }; -template <> struct BitCountToEndMask_t<20> { enum { MASK = 0x000fffff }; }; -template <> struct BitCountToEndMask_t<21> { enum { MASK = 0x001fffff }; }; -template <> struct BitCountToEndMask_t<22> { enum { MASK = 0x003fffff }; }; -template <> struct BitCountToEndMask_t<23> { enum { MASK = 0x007fffff }; }; -template <> struct BitCountToEndMask_t<24> { enum { MASK = 0x00ffffff }; }; -template <> struct BitCountToEndMask_t<25> { enum { MASK = 0x01ffffff }; }; -template <> struct BitCountToEndMask_t<26> { enum { MASK = 0x03ffffff }; }; -template <> struct BitCountToEndMask_t<27> { enum { MASK = 0x07ffffff }; }; -template <> struct BitCountToEndMask_t<28> { enum { MASK = 0x0fffffff }; }; -template <> struct BitCountToEndMask_t<29> { enum { MASK = 0x1fffffff }; }; -template <> struct BitCountToEndMask_t<30> { enum { MASK = 0x3fffffff }; }; -template <> struct BitCountToEndMask_t<31> { enum { MASK = 0x7fffffff }; }; - -//------------------------------------- - -template -class CFixedBitVecBase -{ -public: - bool IsFixedSize() const { return true; } - int GetNumBits(void) const { return NUM_BITS; } - void Resize( int numBits, bool bClearAll = false ) { Assert(numBits == NUM_BITS); if ( bClearAll ) Plat_FastMemset( m_Ints, 0, NUM_INTS * sizeof(uint32) ); }// for syntatic consistency (for when using templates) - - int GetNumDWords() const { return NUM_INTS; } - uint32 * Base() { return m_Ints; } - const uint32 * Base() const { return m_Ints; } - - int FindNextSetBit(int iStartBit) const; // returns -1 if no set bit was found - -protected: - CFixedBitVecBase() {} - CFixedBitVecBase(int numBits) { Assert( numBits == NUM_BITS ); } // doesn't make sense, really. Supported to simplify templates & allow easy replacement of variable - - void ValidateOperand( const CFixedBitVecBase &operand ) const { } // no need, compiler does so statically - -public: // for test code - unsigned GetEndMask() const { return static_cast( BitCountToEndMask_t::MASK ); } - -private: - enum - { - NUM_INTS = (NUM_BITS + (BITS_PER_INT-1)) / BITS_PER_INT - }; - - uint32 m_Ints[(NUM_BITS + (BITS_PER_INT-1)) / BITS_PER_INT]; -}; - -//----------------------------------------------------------------------------- -// -// The actual classes used -// - -// inheritance instead of typedef to allow forward declarations -class CVarBitVec : public CBitVecT -{ -public: - CVarBitVec() - { - } - - CVarBitVec(int numBits) - : CBitVecT(numBits) - { - } -}; - -//----------------------------------------------------------------------------- - -template < int NUM_BITS > -class CBitVec : public CBitVecT< CFixedBitVecBase > -{ -public: - CBitVec() - { - } - - CBitVec(int numBits) - : CBitVecT< CFixedBitVecBase >(numBits) - { - } -}; - - -//----------------------------------------------------------------------------- - -typedef CBitVec<32> CDWordBitVec; - -//----------------------------------------------------------------------------- - -inline CVarBitVecBase::CVarBitVecBase() -{ - Plat_FastMemset( this, 0, sizeof( *this ) ); -} - -//----------------------------------------------------------------------------- - -inline CVarBitVecBase::CVarBitVecBase(int numBits) -{ - Assert( numBits ); - m_numBits = numBits; - - // Figure out how many ints are needed - m_numInts = CalcNumIntsForBits( numBits ); - m_pInt = NULL; - AllocInts( m_numInts ); -} - -//----------------------------------------------------------------------------- - -inline CVarBitVecBase::CVarBitVecBase( const CVarBitVecBase &from ) -{ - if ( from.m_numInts ) - { - m_numBits = from.m_numBits; - m_numInts = from.m_numInts; - m_pInt = NULL; - AllocInts( m_numInts ); - memcpy( m_pInt, from.m_pInt, m_numInts * sizeof(int) ); - } - else - memset( this, 0, sizeof( *this ) ); -} - -//----------------------------------------------------------------------------- - -inline CVarBitVecBase &CVarBitVecBase::operator=( const CVarBitVecBase &from ) -{ - Resize( from.GetNumBits() ); - if ( m_pInt ) - memcpy( m_pInt, from.m_pInt, m_numInts * sizeof(int) ); - return (*this); -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -// Input : -// Output : -//----------------------------------------------------------------------------- - -inline CVarBitVecBase::~CVarBitVecBase(void) -{ - FreeInts(); -} - -//----------------------------------------------------------------------------- - -inline void CVarBitVecBase::Attach( uint32 *pBits, int numBits ) -{ - FreeInts(); - m_numBits = numBits; - m_numInts = CalcNumIntsForBits( numBits ); - if ( m_numInts > 1 ) - { - m_pInt = pBits; - } - else - { - m_iBitStringStorage = *pBits; - m_pInt = &m_iBitStringStorage; - free( pBits ); - } -} - -//----------------------------------------------------------------------------- - -inline bool CVarBitVecBase::Detach( uint32 **ppBits, int *pNumBits ) -{ - if ( !m_numBits ) - { - return false; - } - - *pNumBits = m_numBits; - if ( m_numInts > 1 ) - { - *ppBits = m_pInt; - } - else - { - *ppBits = (uint32 *)malloc( sizeof(uint32) ); - **ppBits = m_iBitStringStorage; - free( m_pInt ); - } - - memset( this, 0, sizeof( *this ) ); - return true; -} - -//----------------------------------------------------------------------------- - -template -inline CBitVecT::CBitVecT() -{ - // undef this is ints are not 4 bytes - // generate a compile error if sizeof(int) is not 4 (HACK: can't use the preprocessor so use the compiler) - - COMPILE_TIME_ASSERT( sizeof(int)==4 ); - - // Initialize bitstring by clearing all bits - ClearAll(); -} - -//----------------------------------------------------------------------------- -template -inline CBitVecT::CBitVecT(int numBits) - : BASE_OPS( numBits ) -{ - // undef this is ints are not 4 bytes - // generate a compile error if sizeof(int) is not 4 (HACK: can't use the preprocessor so use the compiler) - - COMPILE_TIME_ASSERT( sizeof(int)==4 ); - - // Initialize bitstring by clearing all bits - ClearAll(); -} - -//----------------------------------------------------------------------------- - -template -inline CBitVecAccessor CBitVecT::operator[](int i) -{ - Assert(i >= 0 && i < this->GetNumBits()); - return CBitVecAccessor(this->Base(), i); -} - - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Init( int val ) -{ - if ( this->Base() ) - Plat_FastMemset( this->Base(), ( val ) ? 0xff : 0, this->GetNumDWords() * sizeof(int) ); -} - -//----------------------------------------------------------------------------- - -template -inline uint32 CBitVecT::Get( uint32 bitNum ) const -{ - Assert( bitNum < (uint32)this->GetNumBits() ); - const uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - return ( *pInt & BitVec_Bit( bitNum ) ); -} - -//----------------------------------------------------------------------------- - -template -inline bool CBitVecT::IsBitSet( int bitNum ) const -{ - Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); - const uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - return ( ( *pInt & BitVec_Bit( bitNum ) ) != 0 ); -} - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Set( int bitNum ) -{ - Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); - uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - *pInt |= BitVec_Bit( bitNum ); -} - -//----------------------------------------------------------------------------- - -template -inline bool CBitVecT::TestAndSet(int bitNum) -{ - Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); - uint32 bitVecBit = BitVec_Bit( bitNum ); - uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - bool bResult = ( ( *pInt & bitVecBit) != 0 ); - *pInt |= bitVecBit; - return bResult; -} - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Clear(int bitNum) -{ - Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); - uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - *pInt &= ~BitVec_Bit( bitNum ); -} - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Set( int bitNum, bool bNewVal ) -{ - uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - uint32 bitMask = BitVec_Bit( bitNum ); - if ( bNewVal ) - { - *pInt |= bitMask; - } - else - { - *pInt &= ~bitMask; - } -} - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Set( uint32 offset, uint32 mask ) -{ - uint32 *pInt = this->Base() + offset; - *pInt |= mask; -} - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Clear( uint32 offset, uint32 mask ) -{ - uint32 *pInt = this->Base() + offset; - *pInt &= ~mask; -} - -//----------------------------------------------------------------------------- - -template -inline uint32 CBitVecT::Get( uint32 offset, uint32 mask ) -{ - uint32 *pInt = this->Base() + offset; - return ( *pInt & mask ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::And(const CBitVecT &addStr, CBitVecT *out) const -{ - this->ValidateOperand( addStr ); - this->ValidateOperand( *out ); - - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = this->Base(); - const uint32 *pOperand2 = addStr.Base(); - - for (int i = this->GetNumDWords() - 1; i >= 0 ; --i) - { - pDest[i] = pOperand1[i] & pOperand2[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::Or(const CBitVecT &orStr, CBitVecT *out) const -{ - this->ValidateOperand( orStr ); - this->ValidateOperand( *out ); - - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = this->Base(); - const uint32 *pOperand2 = orStr.Base(); - - for (int i = this->GetNumDWords() - 1; i >= 0; --i) - { - pDest[i] = pOperand1[i] | pOperand2[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::Xor(const CBitVecT &xorStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = this->Base(); - const uint32 *pOperand2 = xorStr.Base(); - - for (int i = this->GetNumDWords() - 1; i >= 0; --i) - { - pDest[i] = pOperand1[i] ^ pOperand2[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::Not(CBitVecT *out) const -{ - ValidateOperand( *out ); - - uint32 * pDest = out->Base(); - const uint32 *pOperand = this->Base(); - - for (int i = this->GetNumDWords() - 1; i >= 0; --i) - { - pDest[i] = ~(pOperand[i]); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Copy a bit string -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::CopyTo(CBitVecT *out) const -{ - out->Resize( this->GetNumBits() ); - - this->ValidateOperand( *out ); - Assert( out != this ); - - memcpy( out->Base(), this->Base(), this->GetNumDWords() * sizeof( int ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Are all bits zero? -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline bool CBitVecT::IsAllClear(void) const -{ - // Number of available bits may be more than the number - // actually used, so make sure to mask out unused bits - // before testing for zero - (const_cast(this))->Base()[this->GetNumDWords()-1] &= CBitVecT::GetEndMask(); // external semantics of const retained - - for (int i = this->GetNumDWords() - 1; i >= 0; --i) - { - if ( this->Base()[i] !=0 ) - { - return false; - } - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Are all bits set? -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline bool CBitVecT::IsAllSet(void) const -{ - // Number of available bits may be more than the number - // actually used, so make sure to mask out unused bits - // before testing for set bits - (const_cast(this))->Base()[this->GetNumDWords()-1] |= ~CBitVecT::GetEndMask(); // external semantics of const retained - - for (int i = this->GetNumDWords() - 1; i >= 0; --i) - { - if ( this->Base()[i] != ~0 ) - { - return false; - } - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets all bits -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::SetAll(void) -{ - if ( this->Base() ) - Plat_FastMemset( this->Base(), 0xff, this->GetNumDWords() * sizeof(int) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Clears all bits -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::ClearAll(void) -{ - if ( this->Base() ) - Plat_FastMemset( this->Base(), 0, this->GetNumDWords() * sizeof(int) ); -} - -//----------------------------------------------------------------------------- -template -inline void CBitVecT::Copy( const CBitVecT &other, int nBits ) -{ - if ( nBits == - 1 ) - { - nBits = other.GetNumBits(); - } - - this->Resize( nBits ); - - ValidateOperand( other ); - Assert( &other != this ); - - memcpy( this->Base(), other.Base(), this->GetNumDWords() * sizeof( uint32 ) ); -} - -//----------------------------------------------------------------------------- -template -inline bool CBitVecT::Compare( const CBitVecT &other, int nBits ) const -{ - if ( nBits == - 1 ) - { - if ( other.GetNumBits() != this->GetNumBits() ) - { - return false; - } - - nBits = other.GetNumBits(); - } - - if ( nBits > other.GetNumBits() || nBits > this->GetNumBits() ) - { - return false; - } - - (const_cast(this))->Base()[this->GetNumDWords()-1] &= CBitVecT::GetEndMask(); // external semantics of const retained - (const_cast(&other))->Base()[this->GetNumDWords()-1] &= other.CBitVecT::GetEndMask(); // external semantics of const retained - - int nBytes = PAD_NUMBER( nBits, 8 ) >> 3; - - return ( memcmp( this->Base(), other.Base(), nBytes ) == 0 ); -} - -//----------------------------------------------------------------------------- -template -inline uint32 CBitVecT::GetDWord(int i) const -{ - Assert(i >= 0 && i < this->GetNumDWords()); - return this->Base()[i]; -} - -//----------------------------------------------------------------------------- -template -inline void CBitVecT::SetDWord(int i, uint32 val) -{ - Assert(i >= 0 && i < this->GetNumDWords()); - this->Base()[i] = val; -} - -//----------------------------------------------------------------------------- - -inline unsigned GetStartBitMask( int startBit ) -{ - static unsigned int g_StartMask[32] = - { - 0xffffffff, - 0xfffffffe, - 0xfffffffc, - 0xfffffff8, - 0xfffffff0, - 0xffffffe0, - 0xffffffc0, - 0xffffff80, - 0xffffff00, - 0xfffffe00, - 0xfffffc00, - 0xfffff800, - 0xfffff000, - 0xffffe000, - 0xffffc000, - 0xffff8000, - 0xffff0000, - 0xfffe0000, - 0xfffc0000, - 0xfff80000, - 0xfff00000, - 0xffe00000, - 0xffc00000, - 0xff800000, - 0xff000000, - 0xfe000000, - 0xfc000000, - 0xf8000000, - 0xf0000000, - 0xe0000000, - 0xc0000000, - 0x80000000, - }; - - return g_StartMask[ startBit & 31 ]; -} - -inline int CVarBitVecBase::FindNextSetBit( int startBit ) const -{ - if ( startBit < GetNumBits() ) - { - int wordIndex = BitVec_Int(startBit); - unsigned int startMask = GetStartBitMask( startBit ); - int lastWord = GetNumDWords()-1; - - // handle non dword lengths - if ( (GetNumBits() % BITS_PER_INT) != 0 ) - { - unsigned int elem = Base()[wordIndex]; - elem &= startMask; - if ( wordIndex == lastWord) - { - elem &= (GetEndMask()); - // there's a bit remaining in this word - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - } - else - { - // there's a bit remaining in this word - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - - // iterate the words - for ( int i = wordIndex+1; i < lastWord; i++ ) - { - elem = Base()[i]; - if ( elem ) - return FirstBitInWord(elem, i << 5); - } - elem = Base()[lastWord] & GetEndMask(); - if ( elem ) - return FirstBitInWord(elem, lastWord << 5); - } - } - else - { - const uint32 * RESTRICT pCurElem = Base() + wordIndex; - unsigned int elem = *pCurElem; - elem &= startMask; - do - { - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - ++pCurElem; - elem = *pCurElem; - ++wordIndex; - } while( wordIndex <= lastWord ); - } - - } - - return -1; -} - -template -inline int CFixedBitVecBase::FindNextSetBit( int startBit ) const -{ - if ( startBit < NUM_BITS ) - { - int wordIndex = BitVec_Int(startBit); - unsigned int startMask = GetStartBitMask( startBit ); - - // handle non dword lengths - if ( (NUM_BITS % BITS_PER_INT) != 0 ) - { - unsigned int elem = Base()[wordIndex]; - elem &= startMask; - if ( wordIndex == NUM_INTS-1) - { - elem &= (GetEndMask()); - // there's a bit remaining in this word - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - } - else - { - // there's a bit remaining in this word - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - - // iterate the words - for ( int i = wordIndex+1; i < NUM_INTS-1; i++ ) - { - elem = Base()[i]; - if ( elem ) - return FirstBitInWord(elem, i << 5); - } - elem = Base()[NUM_INTS-1] & GetEndMask(); - if ( elem ) - return FirstBitInWord(elem, (NUM_INTS-1) << 5); - } - } - else - { - const uint32 * RESTRICT pCurElem = Base() + wordIndex; - unsigned int elem = *pCurElem; - elem &= startMask; - do - { - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - ++pCurElem; - elem = *pCurElem; - ++wordIndex; - } while( wordIndex <= NUM_INTS-1); - } - - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Unrolled loops for some common sizes - -template<> -FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<256> >::And(const CBitVecT &addStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = Base(); - const uint32 *pOperand2 = addStr.Base(); - - pDest[0] = pOperand1[0] & pOperand2[0]; - pDest[1] = pOperand1[1] & pOperand2[1]; - pDest[2] = pOperand1[2] & pOperand2[2]; - pDest[3] = pOperand1[3] & pOperand2[3]; - pDest[4] = pOperand1[4] & pOperand2[4]; - pDest[5] = pOperand1[5] & pOperand2[5]; - pDest[6] = pOperand1[6] & pOperand2[6]; - pDest[7] = pOperand1[7] & pOperand2[7]; -} - -template<> -FORCEINLINE_TEMPLATE bool CBitVecT< CFixedBitVecBase<256> >::IsAllClear(void) const -{ - const uint32 *pInts = Base(); - return ( pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 && pInts[3] == 0 && pInts[4] == 0 && pInts[5] == 0 && pInts[6] == 0 && pInts[7] == 0 ); -} - -template<> -FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<256> >::CopyTo(CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pInts = Base(); - - pDest[0] = pInts[0]; - pDest[1] = pInts[1]; - pDest[2] = pInts[2]; - pDest[3] = pInts[3]; - pDest[4] = pInts[4]; - pDest[5] = pInts[5]; - pDest[6] = pInts[6]; - pDest[7] = pInts[7]; -} - -template<> -FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<128> >::And(const CBitVecT &addStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = Base(); - const uint32 *pOperand2 = addStr.Base(); - - pDest[0] = pOperand1[0] & pOperand2[0]; - pDest[1] = pOperand1[1] & pOperand2[1]; - pDest[2] = pOperand1[2] & pOperand2[2]; - pDest[3] = pOperand1[3] & pOperand2[3]; -} - -template<> -FORCEINLINE_TEMPLATE bool CBitVecT< CFixedBitVecBase<128> >::IsAllClear(void) const -{ - const uint32 *pInts = Base(); - return ( pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 && pInts[3] == 0 ); -} - -template<> -FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<128> >::CopyTo(CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pInts = Base(); - - pDest[0] = pInts[0]; - pDest[1] = pInts[1]; - pDest[2] = pInts[2]; - pDest[3] = pInts[3]; -} - -template<> -inline void CBitVecT< CFixedBitVecBase<96> >::And(const CBitVecT &addStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = Base(); - const uint32 *pOperand2 = addStr.Base(); - - pDest[0] = pOperand1[0] & pOperand2[0]; - pDest[1] = pOperand1[1] & pOperand2[1]; - pDest[2] = pOperand1[2] & pOperand2[2]; -} - -template<> -inline bool CBitVecT< CFixedBitVecBase<96> >::IsAllClear(void) const -{ - const uint32 *pInts = Base(); - return ( pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 ); -} - -template<> -inline void CBitVecT< CFixedBitVecBase<96> >::CopyTo(CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pInts = Base(); - - pDest[0] = pInts[0]; - pDest[1] = pInts[1]; - pDest[2] = pInts[2]; -} - -template<> -inline void CBitVecT< CFixedBitVecBase<64> >::And(const CBitVecT &addStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = Base(); - const uint32 *pOperand2 = addStr.Base(); - - pDest[0] = pOperand1[0] & pOperand2[0]; - pDest[1] = pOperand1[1] & pOperand2[1]; -} - -template<> -inline bool CBitVecT< CFixedBitVecBase<64> >::IsAllClear(void) const -{ - const uint32 *pInts = Base(); - return ( pInts[0] == 0 && pInts[1] == 0 ); -} - -template<> -inline void CBitVecT< CFixedBitVecBase<64> >::CopyTo(CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pInts = Base(); - - pDest[0] = pInts[0]; - pDest[1] = pInts[1]; -} - -template<> -inline void CBitVecT< CFixedBitVecBase<32> >::And(const CBitVecT &addStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = Base(); - const uint32 *pOperand2 = addStr.Base(); - - pDest[0] = pOperand1[0] & pOperand2[0]; -} - -template<> -inline bool CBitVecT< CFixedBitVecBase<32> >::IsAllClear(void) const -{ - const uint32 *pInts = Base(); - - return ( pInts[0] == 0 ); -} - -template<> -inline void CBitVecT< CFixedBitVecBase<32> >::CopyTo(CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pInts = Base(); - - pDest[0] = pInts[0]; -} - -//----------------------------------------------------------------------------- - -template <> -inline uint32 CBitVecT< CFixedBitVecBase<32> >::Get( uint32 bitNum ) const -{ - return ( *Base() & BitVec_Bit( bitNum ) ); -} - -//----------------------------------------------------------------------------- - -template <> -inline bool CBitVecT< CFixedBitVecBase<32> >::IsBitSet( int bitNum ) const -{ - return ( ( *Base() & BitVec_Bit( bitNum ) ) != 0 ); -} - -//----------------------------------------------------------------------------- - -template <> -inline void CBitVecT< CFixedBitVecBase<32> >::Set( int bitNum ) -{ - *Base() |= BitVec_Bit( bitNum ); -} - -//----------------------------------------------------------------------------- - -template <> -inline void CBitVecT< CFixedBitVecBase<32> >::Clear(int bitNum) -{ - *Base() &= ~BitVec_Bit( bitNum ); -} - -//----------------------------------------------------------------------------- - -template <> -inline void CBitVecT< CFixedBitVecBase<32> >::Set( int bitNum, bool bNewVal ) -{ - uint32 bitMask = BitVec_Bit( bitNum ); - if ( bNewVal ) - { - *Base() |= bitMask; - } - else - { - *Base() &= ~bitMask; - } -} - - -//----------------------------------------------------------------------------- - -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Resizes the bit string to a new number of bits -// Input : resizeNumBits - -//----------------------------------------------------------------------------- -inline void CVarBitVecBase::Resize( int resizeNumBits, bool bClearAll ) -{ - Assert( resizeNumBits >= 0 && resizeNumBits <= USHRT_MAX ); - - int newIntCount = CalcNumIntsForBits( resizeNumBits ); - if ( newIntCount != GetNumDWords() ) - { - if ( Base() ) - { - ReallocInts( newIntCount ); - if ( !bClearAll && resizeNumBits >= GetNumBits() ) - { - Base()[GetNumDWords() - 1] &= GetEndMask(); - Plat_FastMemset( Base() + GetNumDWords(), 0, (newIntCount - GetNumDWords()) * sizeof(int) ); - } - } - else - { - // Figure out how many ints are needed - AllocInts( newIntCount ); - // Initialize bitstring by clearing all bits - bClearAll = true; - } - - m_numInts = newIntCount; - } - else if ( !bClearAll && resizeNumBits >= GetNumBits() && Base() ) - { - Base()[GetNumDWords() - 1] &= GetEndMask(); - } - - if ( bClearAll && Base() ) - { - Plat_FastMemset( Base(), 0, newIntCount * sizeof(int) ); - } - - // store the new size and end mask - m_numBits = resizeNumBits; -} - -//----------------------------------------------------------------------------- -// Purpose: Allocate the storage for the ints -// Input : numInts - -//----------------------------------------------------------------------------- -inline void CVarBitVecBase::AllocInts( int numInts ) -{ - Assert( !m_pInt ); - - if ( numInts == 0 ) - return; - - if ( numInts == 1 ) - { - m_pInt = &m_iBitStringStorage; - return; - } - - m_pInt = (uint32 *)malloc( numInts * sizeof(int) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Reallocate the storage for the ints -// Input : numInts - -//----------------------------------------------------------------------------- -inline void CVarBitVecBase::ReallocInts( int numInts ) -{ - Assert( Base() ); - if ( numInts == 0) - { - FreeInts(); - return; - } - - if ( m_pInt == &m_iBitStringStorage ) - { - if ( numInts != 1 ) - { - m_pInt = ((uint32 *)malloc( numInts * sizeof(int) )); - *m_pInt = m_iBitStringStorage; - } - - return; - } - - if ( numInts == 1 ) - { - m_iBitStringStorage = *m_pInt; - free( m_pInt ); - m_pInt = &m_iBitStringStorage; - return; - } - - m_pInt = (uint32 *)realloc( m_pInt, numInts * sizeof(int) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Free storage allocated with AllocInts -//----------------------------------------------------------------------------- -inline void CVarBitVecBase::FreeInts( void ) -{ - if ( m_numInts > 1 ) - { - free( m_pInt ); - } - m_pInt = NULL; -} - -#include "tier0/memdbgoff.h" - -// ------------------------------------------------------------------------ // -// CBitVecAccessor inlines. -// ------------------------------------------------------------------------ // - -inline CBitVecAccessor::CBitVecAccessor(uint32 *pDWords, int iBit) -{ - m_pDWords = pDWords; - m_iBit = iBit; -} - - -inline void CBitVecAccessor::operator=(int val) -{ - if(val) - m_pDWords[m_iBit >> 5] |= (1 << (m_iBit & 31)); - else - m_pDWords[m_iBit >> 5] &= ~(unsigned long)(1 << (m_iBit & 31)); -} - -inline CBitVecAccessor::operator uint32() -{ - return m_pDWords[m_iBit >> 5] & (1 << (m_iBit & 31)); -} - - -//============================================================================= - -#endif // BITVEC_H From 424e4bf41e8ab04dc90508f1662f741d3dd0df38 Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Fri, 11 Sep 2020 10:48:45 +0900 Subject: [PATCH 4/5] Fixed to check sv_replaybots&sv_stressbots in the CTransmitManager::CTransmitManager. --- src/core/modules/entities/entities_transmit.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/modules/entities/entities_transmit.cpp b/src/core/modules/entities/entities_transmit.cpp index a6e7b53ed..dceb6a8e8 100755 --- a/src/core/modules/entities/entities_transmit.cpp +++ b/src/core/modules/entities/entities_transmit.cpp @@ -95,13 +95,17 @@ CTransmitManager::CTransmitManager() current_clients = 0; IPlayerInfo* pPlayerInfo = nullptr; + ConVar* sv_replaybots = cvar->FindVar("sv_replaybots"); + ConVar* sv_stressbots = cvar->FindVar("sv_stressbots"); for (unsigned int i=1; i <= (unsigned int) gpGlobals->maxClients; ++i) { if (!PlayerInfoFromIndex(i, pPlayerInfo)) continue; - if (pPlayerInfo->IsFakeClient() || V_strstr(pPlayerInfo->GetNetworkIDString(), "BOT")) + if ((pPlayerInfo->IsFakeClient() || V_strstr(pPlayerInfo->GetNetworkIDString(), "BOT")) && ( + (!sv_replaybots || !sv_replaybots->GetBool()) || + (!sv_stressbots || !sv_stressbots->GetBool()))) continue; ++current_clients; From f66ba09697f9aeb25f0eee5dc5cb8599780690fc Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Wed, 23 Sep 2020 21:24:14 +0900 Subject: [PATCH 5/5] Changed player.reset_player to player.reset_all_entity. Minor fix. --- .../packages/source-python/entities/_base.py | 22 ++++++++-------- .../source-python/entities/transmit.py | 25 +++---------------- .../packages/source-python/players/_base.py | 16 ++++++------ .../entities/entities_transmit_wrap.cpp | 2 +- 4 files changed, 23 insertions(+), 42 deletions(-) diff --git a/addons/source-python/packages/source-python/entities/_base.py b/addons/source-python/packages/source-python/entities/_base.py index a679e4195..6a1892789 100755 --- a/addons/source-python/packages/source-python/entities/_base.py +++ b/addons/source-python/packages/source-python/entities/_base.py @@ -67,7 +67,7 @@ # Source.Python Imports # Entities from _entities._entity import BaseEntity -from _entities._transmit import TransmitManager +from _entities._transmit import transmit_manager # ============================================================================= @@ -785,7 +785,7 @@ def set_parent(self, parent, attachment=INVALID_ATTACHMENT_INDEX): # ========================================================================= def hide(self): """Hide the entity from all players.""" - TransmitManager.hide(self.index) + transmit_manager.hide(self.index) def hide_from(self, player_index): """Hide the entity from player. @@ -793,11 +793,11 @@ def hide_from(self, player_index): :param int player_index: The target player index to hide this entity. """ - TransmitManager.hide_from(self.index, player_index) + transmit_manager.hide_from(self.index, player_index) def show(self): """Show the entity to all players.""" - TransmitManager.show(self.index) + transmit_manager.show(self.index) def show_from(self, player_index): """Show the entity to player. @@ -805,11 +805,11 @@ def show_from(self, player_index): :param int player_index: The target player index to show this entity. """ - TransmitManager.show_from(self.index, player_index) + transmit_manager.show_from(self.index, player_index) def reset(self): """Reset the entity's hidden/shown state.""" - TransmitManager.reset(self.index) + transmit_manager.reset(self.index) def reset_from(self, player_index): """Reset the player's entity hidden/shown state. @@ -817,14 +817,14 @@ def reset_from(self, player_index): :param int player_index: The target player index to reset the player's hidden/shown state. """ - TransmitManager.reset_from(self.index, player_index) + transmit_manager.reset_from(self.index, player_index) def is_hidden(self): """Return True if the entity is hidden from any player. :rtype: bool """ - return TransmitManager.is_hidden(self.index) + return transmit_manager.is_hidden(self.index) def is_hidden_from(self, player_index): """Return True if the entity is hidden from the player. @@ -833,7 +833,7 @@ def is_hidden_from(self, player_index): The target player index to check if the entity is hidden. :rtype: bool """ - return TransmitManager.is_hidden_from(self.index, player_index) + return transmit_manager.is_hidden_from(self.index, player_index) def get_hidden_player(self): """Get the players where the entity is hidden. @@ -843,7 +843,7 @@ def get_hidden_player(self): in which the entity is hidden. :rtype: tuple """ - return TransmitManager.get_hidden_player(self.index) + return transmit_manager.get_hidden_player(self.index) # ============================================================================= @@ -882,4 +882,4 @@ def _on_entity_deleted(base_entity): cls.cache.pop(index, None) # Reset the entity's hidden state. - TransmitManager.reset(index) + transmit_manager.reset(index) diff --git a/addons/source-python/packages/source-python/entities/transmit.py b/addons/source-python/packages/source-python/entities/transmit.py index 16bb788a2..07e6e989f 100755 --- a/addons/source-python/packages/source-python/entities/transmit.py +++ b/addons/source-python/packages/source-python/entities/transmit.py @@ -2,47 +2,28 @@ """Provides entity transmission filtering.""" -# ============================================================================ -# >> IMPORTS -# ============================================================================ -# Source.Python -# Core -from core import AutoUnload -# Entities -from entities.entity import Entity -from entities.hooks import EntityCondition -# Filters -from filters.entities import EntityIter -# Listeners -from listeners import on_entity_created_listener_manager - # ============================================================================ # >> FORWARD IMPORTS # ============================================================================ # Source.Python # Entities -from _entities._transmit import TransmitManager +from _entities._transmit import transmit_manager # ============================================================================ # >> ALL DECLARATION # ============================================================================ __all__ = ( - 'TransmitManager', + 'transmit_manager', 'reset_hidden_state', ) -# ============================================================================ -# >> CLASSES -# ============================================================================ - - # ============================================================================= # >> FUNCTIONS # ============================================================================= def reset_hidden_state(): """Reset all entities' hidden/shown state.""" - TransmitManager.reset_all() + transmit_manager.reset_all() diff --git a/addons/source-python/packages/source-python/players/_base.py b/addons/source-python/packages/source-python/players/_base.py index 2a067491e..b9719b930 100755 --- a/addons/source-python/packages/source-python/players/_base.py +++ b/addons/source-python/packages/source-python/players/_base.py @@ -78,7 +78,7 @@ # ============================================================================= # Source.Python Imports # Entities -from _entities._transmit import TransmitManager +from _entities._transmit import transmit_manager # ============================================================================= @@ -1011,7 +1011,7 @@ def hide_entity(self, entity_index): :param int entity_index: The target entity index to hide from the player. """ - TransmitManager.hide_from(entity_index, self.index) + transmit_manager.hide_from(entity_index, self.index) def show_entity(self, entity_index): """Show the entity to player. @@ -1019,7 +1019,7 @@ def show_entity(self, entity_index): :param int entity_index: The target entity index to show the entity to player. """ - TransmitManager.show_from(entity_index, self.index) + transmit_manager.show_from(entity_index, self.index) def reset_entity(self, entity_index): """Reset the player's entity hidden/shown state. @@ -1027,11 +1027,11 @@ def reset_entity(self, entity_index): :param int entity_index: The target entity_index to reset the player's hidden/shown state. """ - TransmitManager.reset_from(entity_index, self.index) + transmit_manager.reset_from(entity_index, self.index) - def reset_player(self): + def reset_all_entity(self): """Reset the player's hidden/shown state on all entities.""" - TransmitManager.reset_player(self.index) + transmit_manager.reset_player(self.index) def is_entity_hidden(self, entity_index): """Return True if the entity is hidden from the player. @@ -1040,7 +1040,7 @@ def is_entity_hidden(self, entity_index): The target entity index to check if the entity is hidden. :rtype: bool """ - return TransmitManager.is_hidden_from(entity_index, self.index) + return transmit_manager.is_hidden_from(entity_index, self.index) def get_hidden_entity(self): """Get the entities that are hidden from the player. @@ -1050,7 +1050,7 @@ def get_hidden_entity(self): that are hidden from the player. :rtype: tuple """ - return TransmitManager.get_hidden_entity(self.index) + return transmit_manager.get_hidden_entity(self.index) # ============================================================================= diff --git a/src/core/modules/entities/entities_transmit_wrap.cpp b/src/core/modules/entities/entities_transmit_wrap.cpp index f387cb770..e1a405048 100755 --- a/src/core/modules/entities/entities_transmit_wrap.cpp +++ b/src/core/modules/entities/entities_transmit_wrap.cpp @@ -137,6 +137,6 @@ void export_transmit_manager(scope _transmit) ; // Singleton... - _transmit.attr("TransmitManager") = object(ptr(CTransmitManager::get_instance())); + _transmit.attr("transmit_manager") = object(ptr(CTransmitManager::get_instance())); }