From 0aea7acdf152d619d889f7e60a0728af6fd10ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordan=20Bri=C3=A8re?= Date: Thu, 21 Nov 2019 18:20:11 -0500 Subject: [PATCH 1/2] Potential fix for Player/Weapon MRO issues (#287). --- .../packages/source-python/players/_base.py | 5 +++-- .../packages/source-python/weapons/_base.py | 13 ++++++++++++- src/core/modules/players/players_entity.cpp | 10 ++++++++++ src/core/modules/players/players_entity.h | 3 ++- src/core/modules/players/players_wrap.cpp | 5 ++++- src/core/modules/weapons/weapons_entity.cpp | 10 ++++++++++ src/core/modules/weapons/weapons_entity.h | 1 + .../modules/weapons/weapons_entity_wrap.cpp | 5 ++++- src/core/utilities/wrap_macros.h | 18 ++++++++++++++++++ 9 files changed, 64 insertions(+), 6 deletions(-) diff --git a/addons/source-python/packages/source-python/players/_base.py b/addons/source-python/packages/source-python/players/_base.py index f1e901180..7a13dba46 100644 --- a/addons/source-python/packages/source-python/players/_base.py +++ b/addons/source-python/packages/source-python/players/_base.py @@ -74,7 +74,7 @@ # ============================================================================= # >> CLASSES # ============================================================================= -class Player(Entity, PlayerMixin): +class Player(PlayerMixin, Entity): """Class used to interact directly with players.""" def __init__(self, index): @@ -85,7 +85,8 @@ def __init__(self, index): :raise ValueError: Raised if the index is invalid. """ - super().__init__(index) + PlayerMixin.__init__(self, index) + Entity.__init__(self, index) object.__setattr__(self, '_playerinfo', None) @classmethod diff --git a/addons/source-python/packages/source-python/weapons/_base.py b/addons/source-python/packages/source-python/weapons/_base.py index 441a8924b..bced33209 100644 --- a/addons/source-python/packages/source-python/weapons/_base.py +++ b/addons/source-python/packages/source-python/weapons/_base.py @@ -24,9 +24,20 @@ # ============================================================================= # >> CLASSES # ============================================================================= -class Weapon(Entity, WeaponMixin): +class Weapon(WeaponMixin, Entity): """Allows easy usage of the weapon's attributes.""" + def __init__(self, index): + """Initialize the object. + + :param int index: + A valid weapon index. + :raise ValueError: + Raised if the index is invalid. + """ + WeaponMixin.__init__(self, index) + Entity.__init__(self, index) + def _validate_clip(self): """Test if the weapon has a clip.""" if ( diff --git a/src/core/modules/players/players_entity.cpp b/src/core/modules/players/players_entity.cpp index 631af131b..c4855f2fb 100644 --- a/src/core/modules/players/players_entity.cpp +++ b/src/core/modules/players/players_entity.cpp @@ -51,6 +51,16 @@ boost::shared_ptr PlayerMixin::wrap(CBaseEntity* pEntity) ); } +object PlayerMixin::_obj(object cls, CPointer *pPtr) +{ + static PyTypeObject *type = converter::registry::query(typeid(PlayerMixin))->m_class_object; + + if (type == downcast(cls.ptr())) + return object(__init__(ExcIndexFromPointer(pPtr))); + + return cls(object(ExcIndexFromPointer(pPtr))); +} + // CBasePlayer float PlayerMixin::GetSpeed() diff --git a/src/core/modules/players/players_entity.h b/src/core/modules/players/players_entity.h index 557a3ba3a..edb521e6f 100644 --- a/src/core/modules/players/players_entity.h +++ b/src/core/modules/players/players_entity.h @@ -66,7 +66,8 @@ class PlayerMixin: public CBaseEntityWrapper public: static boost::shared_ptr __init__(unsigned int uiEntityIndex); static boost::shared_ptr wrap(CBaseEntity* pEntity); - + static object _obj(object cls, CPointer *pPtr); + // CBasePlayer // TODO: Return for some of these the proper entity class instead of a handle/index // E. g. BaseEntity, Entity, Weapon, Player, etc. diff --git a/src/core/modules/players/players_wrap.cpp b/src/core/modules/players/players_wrap.cpp index d271173c1..866955d70 100644 --- a/src/core/modules/players/players_wrap.cpp +++ b/src/core/modules/players/players_wrap.cpp @@ -730,5 +730,8 @@ void export_player_wrapper(scope _players) ".. note:: Only available in TF2.\n\n" ":rtype: int"); - _PlayerMixin ADD_MEM_TOOLS(PlayerMixin); + CLASSMETHOD(_PlayerMixin, GET_OBJ_NAME, &PlayerMixin::_obj) + ADD_PTR(PlayerMixin) + ADD_SIZE(PlayerMixin) + STORE_CLASS("PlayerMixin", "PlayerMixin") } diff --git a/src/core/modules/weapons/weapons_entity.cpp b/src/core/modules/weapons/weapons_entity.cpp index c3b2f72ad..759411835 100644 --- a/src/core/modules/weapons/weapons_entity.cpp +++ b/src/core/modules/weapons/weapons_entity.cpp @@ -53,6 +53,16 @@ boost::shared_ptr WeaponMixin::wrap(CBaseEntity* pEntity) ); } +object WeaponMixin::_obj(object cls, CPointer *pPtr) +{ + static PyTypeObject *type = converter::registry::query(typeid(WeaponMixin))->m_class_object; + + if (type == downcast(cls.ptr())) + return object(__init__(ExcIndexFromPointer(pPtr))); + + return cls(object(ExcIndexFromPointer(pPtr))); +} + // CBaseCombatWeapon float WeaponMixin::GetNextAttack() diff --git a/src/core/modules/weapons/weapons_entity.h b/src/core/modules/weapons/weapons_entity.h index f5da8a7e2..e5534152a 100644 --- a/src/core/modules/weapons/weapons_entity.h +++ b/src/core/modules/weapons/weapons_entity.h @@ -44,6 +44,7 @@ class WeaponMixin: public CBaseEntityWrapper public: static boost::shared_ptr __init__(unsigned int uiEntityIndex); static boost::shared_ptr wrap(CBaseEntity* pEntity); + static object _obj(object cls, CPointer *pPtr); float GetNextAttack(); diff --git a/src/core/modules/weapons/weapons_entity_wrap.cpp b/src/core/modules/weapons/weapons_entity_wrap.cpp index 328c1b7fa..5a0613ad6 100644 --- a/src/core/modules/weapons/weapons_entity_wrap.cpp +++ b/src/core/modules/weapons/weapons_entity_wrap.cpp @@ -145,5 +145,8 @@ void export_weapon_entity(scope _entity) ":rtype: int"); - _WeaponMixin ADD_MEM_TOOLS(WeaponMixin); + CLASSMETHOD(_WeaponMixin, GET_OBJ_NAME, &WeaponMixin::_obj) + ADD_PTR(WeaponMixin) + ADD_SIZE(WeaponMixin) + STORE_CLASS("WeaponMixin", "WeaponMixin") } diff --git a/src/core/utilities/wrap_macros.h b/src/core/utilities/wrap_macros.h index bf82e3d8e..fbd551992 100644 --- a/src/core/utilities/wrap_macros.h +++ b/src/core/utilities/wrap_macros.h @@ -124,6 +124,24 @@ inline void* GetFuncPtr(Function func) static_cast< return_type(*)( __VA_ARGS__ ) >(&function) +//--------------------------------------------------------------------------------- +// Use these to declare classmethod wrappers. +//--------------------------------------------------------------------------------- +#define CLASSMETHOD(cls, name, ...) \ + classmethod(cls.def(name, __VA_ARGS__), name) + +template +T classmethod(T cls, const char *szName) +{ + PyTypeObject *self = downcast(cls.ptr()); + PyDict_SetItemString( + self->tp_dict, szName, + PyClassMethod_New(PyDict_GetItemString(self->tp_dict, szName)) + ); + return cls; +}; + + //--------------------------------------------------------------------------------- // Use this template to create variadic class methods //--------------------------------------------------------------------------------- From 5ca16aa430ff0f8a5c488ac19dd0276a3429602c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordan=20Bri=C3=A8re?= Date: Fri, 22 Nov 2019 11:17:53 -0500 Subject: [PATCH 2/2] Fixed a TypeError when calling Player/WeaponMixin._obj() directly rather than from a subclass. --- src/core/modules/players/players_entity.cpp | 5 ----- src/core/modules/weapons/weapons_entity.cpp | 5 ----- 2 files changed, 10 deletions(-) diff --git a/src/core/modules/players/players_entity.cpp b/src/core/modules/players/players_entity.cpp index c4855f2fb..2e34a9c40 100644 --- a/src/core/modules/players/players_entity.cpp +++ b/src/core/modules/players/players_entity.cpp @@ -53,11 +53,6 @@ boost::shared_ptr PlayerMixin::wrap(CBaseEntity* pEntity) object PlayerMixin::_obj(object cls, CPointer *pPtr) { - static PyTypeObject *type = converter::registry::query(typeid(PlayerMixin))->m_class_object; - - if (type == downcast(cls.ptr())) - return object(__init__(ExcIndexFromPointer(pPtr))); - return cls(object(ExcIndexFromPointer(pPtr))); } diff --git a/src/core/modules/weapons/weapons_entity.cpp b/src/core/modules/weapons/weapons_entity.cpp index 759411835..038404c39 100644 --- a/src/core/modules/weapons/weapons_entity.cpp +++ b/src/core/modules/weapons/weapons_entity.cpp @@ -55,11 +55,6 @@ boost::shared_ptr WeaponMixin::wrap(CBaseEntity* pEntity) object WeaponMixin::_obj(object cls, CPointer *pPtr) { - static PyTypeObject *type = converter::registry::query(typeid(WeaponMixin))->m_class_object; - - if (type == downcast(cls.ptr())) - return object(__init__(ExcIndexFromPointer(pPtr))); - return cls(object(ExcIndexFromPointer(pPtr))); }