#include "object/client/Util.hpp" #include "object/client/CClientObjCreate.hpp" #include "object/client/CGContainer_C.hpp" #include "object/client/CGCorpse_C.hpp" #include "object/client/CGDynamicObject_C.hpp" #include "object/client/CGGameObject_C.hpp" #include "object/client/CGItem_C.hpp" #include "object/client/CGObject_C.hpp" #include "object/client/CGPlayer_C.hpp" #include "object/client/CGUnit_C.hpp" #include "object/client/ObjMgr.hpp" #include CGObject_C* FindActiveObject(WOWGUID guid) { return ClntObjMgrGetCurrent()->m_objects.Ptr(guid, CHashKeyGUID(guid)); } /** * Given an object type and collection age, free the object at the head of that type's FIFO queue * if it was disabled longer ago than the collection age. Only frees at most one object per call. */ void GarbageCollect(OBJECT_TYPE_ID typeID, uint32_t collectAgeMs) { auto object = ClntObjMgrGetCurrent()->m_lazyCleanupFifo[typeID - 1].Head(); if (!object) { return; } uint32_t disableAgeMs = OsGetAsyncTimeMsPrecise() - object->m_disableTimeMs; if (disableAgeMs < collectAgeMs) { return; } ClntObjMgrGetCurrent()->m_lazyCleanupObjects.Unlink(object); object->m_link.Unlink(); ClntObjMgrFreeObject(object); } CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenable) { *reenable = false; // Active object auto activeObject = FindActiveObject(guid); if (activeObject) { activeObject->SetDisablePending(false); return activeObject; } // Disabled object auto disabledObject = ClntObjMgrGetCurrent()->m_lazyCleanupObjects.Ptr(guid, CHashKeyGUID(guid)); if (disabledObject) { ClntObjMgrGetCurrent()->m_lazyCleanupObjects.Unlink(disabledObject); disabledObject->m_link.Unlink(); ClntObjMgrGetCurrent()->m_objects.Insert(disabledObject, guid, CHashKeyGUID(guid)); // These link checks are guaranteed to pass because of the unlink above (both lists share // the same link). This check is either from an inlined function or is cruft left behind // after a refactor. if ( !ClntObjMgrGetCurrent()->m_visibleObjects.IsLinked(disabledObject) && !ClntObjMgrGetCurrent()->m_reenabledObjects.IsLinked(disabledObject) ) { *reenable = true; ClntObjMgrGetCurrent()->m_reenabledObjects.LinkToTail(disabledObject); } return disabledObject; } // Object not found return nullptr; } int32_t HandleObjectOutOfRangePass1(CGObject_C* object, OUT_OF_RANGE_TYPE type) { // TODO arena unit out of range handling object->HandleOutOfRange(type); if (object->IsObjectLocked()) { object->SetDisablePending(true); return false; } object->SetDisablePending(false); object->Disable(); return true; } void HandleObjectOutOfRangePass2(CGObject_C* object) { // TODO ClearObjectMirrorHandlers(object); ClntObjMgrGetCurrent()->m_objects.Unlink(object); if (ClntObjMgrGetCurrent()->m_visibleObjects.IsLinked(object)) { ClntObjMgrGetCurrent()->m_visibleObjects.UnlinkNode(object); } ClntObjMgrGetCurrent()->m_lazyCleanupObjects.Insert(object, object->m_hashval, CHashKeyGUID(object->m_key)); ClntObjMgrGetCurrent()->m_lazyCleanupFifo[object->m_typeID - 1].LinkToTail(object); } void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate) { switch (object->m_typeID) { case ID_ITEM: { new (object) CGItem_C(time, objCreate); break; } case ID_CONTAINER: { new (object) CGContainer_C(time, objCreate); break; } case ID_UNIT: { new (object) CGUnit_C(time, objCreate); object->AddWorldObject(); break; } case ID_PLAYER: { new (object) CGPlayer_C(time, objCreate); object->AddWorldObject(); break; } case ID_GAMEOBJECT: { new (object) CGGameObject_C(time, objCreate); object->AddWorldObject(); break; } case ID_DYNAMICOBJECT: { new (object) CGDynamicObject_C(time, objCreate); object->AddWorldObject(); break; } case ID_CORPSE: { new (object) CGCorpse_C(time, objCreate); object->AddWorldObject(); break; } default: { break; } } } int32_t SkipPartialObjectUpdate(CDataStore* msg) { // TODO return 0; }