summaryrefslogtreecommitdiff
path: root/src/core/References.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/References.cpp')
-rw-r--r--src/core/References.cpp145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/core/References.cpp b/src/core/References.cpp
new file mode 100644
index 0000000..dc83d96
--- /dev/null
+++ b/src/core/References.cpp
@@ -0,0 +1,145 @@
+#include "common.h"
+
+#include "World.h"
+#include "Vehicle.h"
+#include "PlayerPed.h"
+#include "Pools.h"
+#include "References.h"
+
+CReference CReferences::aRefs[NUMREFERENCES];
+CReference *CReferences::pEmptyList;
+
+void
+CReferences::Init(void)
+{
+ int i;
+ pEmptyList = &aRefs[0];
+ for(i = 0; i < NUMREFERENCES; i++){
+ aRefs[i].pentity = nil;
+ aRefs[i].next = &aRefs[i+1];
+ }
+ aRefs[NUMREFERENCES-1].next = nil;
+}
+
+void
+CEntity::RegisterReference(CEntity **pent)
+{
+ if(IsBuilding())
+ return;
+ CReference *ref;
+ // check if already registered
+ for(ref = m_pFirstReference; ref; ref = ref->next)
+ if(ref->pentity == pent)
+ return;
+ // have to allocate new reference
+ ref = CReferences::pEmptyList;
+ if(ref){
+ CReferences::pEmptyList = ref->next;
+
+ ref->pentity = pent;
+ ref->next = m_pFirstReference;
+ m_pFirstReference = ref;
+ return;
+ }
+ return;
+}
+
+// Clean up the reference from *pent -> 'this'
+void
+CEntity::CleanUpOldReference(CEntity **pent)
+{
+ CReference* ref, ** lastnextp;
+ lastnextp = &m_pFirstReference;
+ for (ref = m_pFirstReference; ref; ref = ref->next) {
+ if (ref->pentity == pent) {
+ *lastnextp = ref->next;
+ ref->next = CReferences::pEmptyList;
+ CReferences::pEmptyList = ref;
+ break;
+ }
+ lastnextp = &ref->next;
+ }
+}
+
+// Clear all references to this entity
+void
+CEntity::ResolveReferences(void)
+{
+ CReference *ref;
+ // clear pointers to this entity
+ for(ref = m_pFirstReference; ref; ref = ref->next)
+ if(*ref->pentity == this)
+ *ref->pentity = nil;
+ // free list
+ if(m_pFirstReference){
+ for(ref = m_pFirstReference; ref->next; ref = ref->next)
+ ;
+ ref->next = CReferences::pEmptyList;
+ CReferences::pEmptyList = m_pFirstReference;
+ m_pFirstReference = nil;
+ }
+}
+
+// Free all references that no longer point to this entity
+void
+CEntity::PruneReferences(void)
+{
+ CReference *ref, *next, **lastnextp;
+ lastnextp = &m_pFirstReference;
+ for(ref = m_pFirstReference; ref; ref = next){
+ next = ref->next;
+ if(*ref->pentity == this)
+ lastnextp = &ref->next;
+ else{
+ *lastnextp = ref->next;
+ ref->next = CReferences::pEmptyList;
+ CReferences::pEmptyList = ref;
+ }
+ }
+}
+
+void
+CReferences::RemoveReferencesToPlayer(void)
+{
+ if(FindPlayerVehicle())
+ FindPlayerVehicle()->ResolveReferences();
+#ifdef FIX_BUGS
+ if (FindPlayerPed()) {
+ CPlayerPed* pPlayerPed = FindPlayerPed();
+ FindPlayerPed()->ResolveReferences();
+ CWorld::Players[CWorld::PlayerInFocus].m_pPed = pPlayerPed;
+ pPlayerPed->RegisterReference((CEntity**)&CWorld::Players[CWorld::PlayerInFocus].m_pPed);
+ }
+#else
+ if(FindPlayerPed())
+ FindPlayerPed()->ResolveReferences();
+#endif
+}
+
+void
+CReferences::PruneAllReferencesInWorld(void)
+{
+ int i;
+ CEntity *e;
+
+ i = CPools::GetPedPool()->GetSize();
+ while(--i >= 0){
+ e = CPools::GetPedPool()->GetSlot(i);
+ if(e)
+ e->PruneReferences();
+ }
+
+ i = CPools::GetVehiclePool()->GetSize();
+ while(--i >= 0){
+ e = CPools::GetVehiclePool()->GetSlot(i);
+ if(e)
+ e->PruneReferences();
+ }
+
+ i = CPools::GetObjectPool()->GetSize();
+ while(--i >= 0){
+ e = CPools::GetObjectPool()->GetSlot(i);
+ if(e)
+ e->PruneReferences();
+ }
+}