Skip to content

Commit f04ba19

Browse files
committed
Updated CollisionHash.
1 parent dc08465 commit f04ba19

File tree

4 files changed

+103
-58
lines changed

4 files changed

+103
-58
lines changed

addons/source-python/docs/source-python/source/developing/module_tutorials/listeners.rst

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,11 @@ OnEntityCollision
329329

330330
Called when a non-player entity is about to collide with another entity.
331331

332-
.. note:: This listener can be extremely noisy. Use :class:`entities.collisions.CollisionHash` if you don't have dynamic conditions to test for.
332+
.. note::
333+
334+
This listener can be extremely noisy. Use :class:`entities.collisions.CollisionHash`,
335+
:class:`entities.collisions.CollisionMap`, or :class:`entities.collisions.CollisionSet`
336+
if you don't have dynamic conditions to test for.
333337

334338
.. code-block:: python
335339
@@ -428,7 +432,11 @@ OnPlayerCollision
428432

429433
Called when a player is about to collide with an entity.
430434

431-
.. note:: This listener can be extremely noisy. Use :class:`entities.collisions.CollisionHash` if you don't have dynamic conditions to test for.
435+
.. note::
436+
437+
This listener can be extremely noisy. Use :class:`entities.collisions.CollisionHash`,
438+
:class:`entities.collisions.CollisionMap`, or :class:`entities.collisions.CollisionSet`
439+
if you don't have dynamic conditions to test for.
432440

433441
.. code-block:: python
434442

src/core/modules/entities/entities_collisions.cpp

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
// Externals.
4141
//-----------------------------------------------------------------------------
4242
extern IEngineTrace *enginetrace;
43-
extern IPhysics *physics;
4443
extern CGlobalVars *gpGlobals;
4544

4645

@@ -323,7 +322,10 @@ bool CCollisionManager::EnterScope(HookType_t eHookType, CHook *pHook)
323322
}
324323

325324
scope.m_pFilter = pWrapper;
326-
scope.m_nMask = nMask;
325+
326+
static object ContentFlags = import("engines").attr("trace").attr("ContentFlags");
327+
scope.m_oMask = ContentFlags(nMask);
328+
327329
scope.m_bSolidContents = bSolidContents;
328330
scope.m_uiIndex = uiIndex;
329331
scope.m_bIsPlayer = ((CBaseEntityWrapper *)pWrapper->m_pPassEnt)->IsPlayer();
@@ -399,12 +401,9 @@ bool CCollisionManager::ShouldHitEntity(IHandleEntity *pHandleEntity, int conten
399401

400402
object oFilter = object(ptr((ITraceFilter *)scope.m_pFilter));
401403

402-
static object ContentFlags = import("engines").attr("trace").attr("ContentFlags");
403-
object oMask = ContentFlags(scope.m_nMask);
404-
405404
FOR_EACH_VEC(pManager->m_pCollisionHooks->m_vecCallables, i) {
406405
BEGIN_BOOST_PY()
407-
object oResult = pManager->m_pCollisionHooks->m_vecCallables[i](oEntity, oOther, oFilter, oMask);
406+
object oResult = pManager->m_pCollisionHooks->m_vecCallables[i](oEntity, oOther, oFilter, scope.m_oMask);
408407
if (!oResult.is_none() && !extract<bool>(oResult)) {
409408
scope.m_pCache->SetResult(uiIndex, false);
410409
return false;
@@ -546,27 +545,6 @@ void CCollisionCache::SetResult(unsigned int uiIndex, bool bResult)
546545
//-----------------------------------------------------------------------------
547546
// CCollisionHash class.
548547
//-----------------------------------------------------------------------------
549-
CCollisionHash::CCollisionHash()
550-
{
551-
m_pHash = physics->CreateObjectPairHash();
552-
553-
if (!m_pHash) {
554-
BOOST_RAISE_EXCEPTION(
555-
PyExc_RuntimeError,
556-
"Failed to create a collision hash."
557-
)
558-
}
559-
}
560-
561-
CCollisionHash::~CCollisionHash()
562-
{
563-
if (!m_pHash) {
564-
return;
565-
}
566-
567-
physics->DestroyObjectPairHash(m_pHash);
568-
}
569-
570548
void CCollisionHash::OnEntityDeleted(CBaseEntity *pEntity)
571549
{
572550
RemovePairs(pEntity);
@@ -586,58 +564,82 @@ void CCollisionHash::AddPair(CBaseEntityWrapper *pEntity, CBaseEntityWrapper *pO
586564
)
587565
}
588566

589-
m_pHash->AddObjectPair(pEntity, pOther);
567+
m_setPairs.insert(CollisionPair_t(pEntity, pOther));
590568
}
591569

592570
void CCollisionHash::RemovePair(void *pObject, void *pOther)
593571
{
594-
m_pHash->RemoveObjectPair(pObject, pOther);
572+
m_setPairs.erase(CollisionPair_t(pObject, pOther));
595573
}
596574

597575
void CCollisionHash::RemovePairs(void *pObject)
598576
{
599-
m_pHash->RemoveAllPairsForObject(pObject);
577+
for (CollisionPairs_t::const_iterator it = m_setPairs.begin(); it != m_setPairs.end(); ) {
578+
CollisionPair_t p = *it;
579+
if (p.first == pObject || p.second == pObject) {
580+
m_setPairs.erase(it);
581+
}
582+
583+
++it;
584+
}
585+
}
586+
587+
void CCollisionHash::Clear()
588+
{
589+
m_setPairs.clear();
600590
}
601591

602592
bool CCollisionHash::Contains(void *pObject)
603593
{
604-
return m_pHash->IsObjectInHash(pObject);
594+
for (CollisionPairs_t::const_iterator it = m_setPairs.begin(); it != m_setPairs.end(); ++it) {
595+
CollisionPair_t p = *it;
596+
if (p.first == pObject || p.second == pObject) {
597+
return true;
598+
}
599+
}
600+
601+
return false;
605602
}
606603

607604
bool CCollisionHash::HasPair(void *pObject, void *pOther)
608605
{
609-
return m_pHash->IsObjectPairInHash(pObject, pOther);
606+
return m_setPairs.find(CollisionPair_t(pObject, pOther)) != m_setPairs.end();
610607
}
611608

612-
int CCollisionHash::GetCount(void *pObject)
609+
unsigned int CCollisionHash::GetCount(void *pObject)
613610
{
614-
return m_pHash->GetPairCountForObject(pObject);
611+
unsigned int nCount = 0;
612+
for (CollisionPairs_t::const_iterator it = m_setPairs.begin(); it != m_setPairs.end(); ++it) {
613+
CollisionPair_t p = *it;
614+
if (p.first == pObject || p.second == pObject) {
615+
++nCount;
616+
}
617+
}
618+
619+
return nCount;
615620
}
616621

617622
list CCollisionHash::GetPairs(void *pObject)
618623
{
619624
list oObjects;
620-
int nCount = m_pHash->GetPairCountForObject(pObject);
621-
622-
if (!nCount) {
623-
return oObjects;
624-
}
625-
626-
void **ppObjects = (void **)stackalloc(nCount * sizeof(void *));
627-
m_pHash->GetPairListForObject(pObject, nCount, ppObjects);
628-
629-
for (int i = 0; i < nCount; ++i) {
630-
pObject = ppObjects[i];
631-
if (!pObject) {
632-
continue;
625+
for (CollisionPairs_t::const_iterator it = m_setPairs.begin(); it != m_setPairs.end(); ++it) {
626+
CollisionPair_t p = *it;
627+
if (p.first == pObject) {
628+
oObjects.append(p.second);
629+
}
630+
else if (p.second == pObject) {
631+
oObjects.append(p.first);
633632
}
634-
635-
oObjects.append(pObject);
636633
}
637634

638635
return oObjects;
639636
}
640637

638+
unsigned int CCollisionHash::GetSize()
639+
{
640+
return m_setPairs.size();
641+
}
642+
641643

642644
//-----------------------------------------------------------------------------
643645
// CCollisionSet class.

src/core/modules/entities/entities_collisions.h

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
#include "sp_main.h"
3535
#include "modules/listeners/listeners_manager.h"
3636
#include "modules/entities/entities_entity.h"
37-
#include "modules/physics/physics.h"
3837
#include "modules/memory/memory_hooks.h"
3938

4039
// Boost
@@ -65,6 +64,8 @@ typedef boost::unordered_map<CHook *, CollisionHookData_t> CollisionHooksMap_t;
6564
typedef CBitVec<MAX_EDICTS> CollisionCache_t;
6665
typedef boost::unordered_map<unsigned int, CCollisionCache *> CollisionCacheMap_t;
6766

67+
typedef std::pair<void *, void *> CollisionPair_t;
68+
6869

6970
//-----------------------------------------------------------------------------
7071
// CTraceFilterSimpleWrapper class.
@@ -89,7 +90,7 @@ struct CollisionScope_t
8990
CTraceFilterSimpleWrapper *m_pFilter;
9091
ShouldHitFunc_t m_pExtraShouldHitCheckFunction;
9192
CCollisionCache *m_pCache;
92-
int m_nMask;
93+
object m_oMask;
9394
bool m_bSolidContents;
9495
};
9596

@@ -120,30 +121,52 @@ class ICollisionRules
120121
};
121122

122123

124+
//-----------------------------------------------------------------------------
125+
// CollisionPairs_t definition and specializations.
126+
//-----------------------------------------------------------------------------
127+
namespace boost {
128+
inline std::size_t hash_value(CollisionPair_t const &p) {
129+
std::size_t s = 0;
130+
boost::hash_combine(s, p.first < p.second ? p.first : p.second);
131+
boost::hash_combine(s, p.first < p.second ? p.second : p.first);
132+
return s;
133+
}
134+
135+
struct hash_equals {
136+
inline bool operator()(const CollisionPair_t &a, const CollisionPair_t &b) const {
137+
return (a.first == b.first && a.second == b.second) || (a.first == b.second && a.second == b.first);
138+
}
139+
};
140+
}
141+
142+
typedef boost::unordered_set<CollisionPair_t, boost::hash<CollisionPair_t>, boost::hash_equals> CollisionPairs_t;
143+
144+
123145
//-----------------------------------------------------------------------------
124146
// CCollisionHash class.
125147
//-----------------------------------------------------------------------------
126148
class CCollisionHash : public ICollisionRules
127149
{
128150
public:
129-
CCollisionHash();
130-
~CCollisionHash();
131-
132151
void OnEntityDeleted(CBaseEntity *pEntity);
133152
bool ShouldHitEntity(CBaseEntity *pEntity, CBaseEntity *pOther);
134153

135154
void AddPair(CBaseEntityWrapper *pEntity, CBaseEntityWrapper *pOther);
136155
void RemovePair(void *pObject, void *pOther);
137156
void RemovePairs(void *pObject);
138157

158+
void Clear();
159+
139160
bool Contains(void *pObject);
140161
bool HasPair(void *pObject, void *pOther);
141162

142-
int GetCount(void *pObject);
163+
unsigned int GetCount(void *pObject);
143164
list GetPairs(void *pObject);
144165

166+
unsigned int GetSize();
167+
145168
private:
146-
IPhysicsObjectPairHash *m_pHash;
169+
CollisionPairs_t m_setPairs;
147170
};
148171

149172

src/core/modules/entities/entities_collisions_wrap.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,24 @@ void export_collision_hash(scope _collisions)
157157
"Returns a list of all entities associated with the given entity."
158158
);
159159

160+
CollisionHash.def(
161+
"clear",
162+
&CCollisionHash::Clear,
163+
"Removes all elements from the hash."
164+
);
165+
160166
// Special methods...
161167
CollisionHash.def(
162168
"__contains__",
163169
&CCollisionHash::Contains,
164170
"Returns whether the given entity is in the hash."
165171
);
172+
173+
CollisionHash.def(
174+
"__len__",
175+
&CCollisionHash::GetSize,
176+
"Returns the size of the collision hash."
177+
);
166178
}
167179

168180

0 commit comments

Comments
 (0)