diff --git a/ElunaTemplate.h b/ElunaTemplate.h index ffe7cf50d2..b1c73fe1fb 100644 --- a/ElunaTemplate.h +++ b/ElunaTemplate.h @@ -22,6 +22,13 @@ extern "C" #include "Globals/SharedDefines.h" #endif + +#ifdef TRINITY +#include "UniqueTrackablePtr.h" + +#define TRACKABLE_PTR_NAMESPACE ::Trinity:: +#endif + class ElunaGlobal { public: @@ -108,47 +115,101 @@ class ElunaObject } // Get wrapped object pointer - virtual void* GetObj() const = 0; - // Returns whether the object is valid or not - virtual bool IsValid() const = 0; + virtual void* GetObjIfValid() const = 0; // Returns pointer to the wrapped object's type name const char* GetTypeName() const { return type_name; } +#ifndef TRINITY // Invalidates the pointer if it should be invalidated virtual void Invalidate() = 0; +#endif protected: Eluna* E; const char* type_name; }; +#ifdef TRINITY +template +struct ElunaConstrainedObjectRef +{ + TRACKABLE_PTR_NAMESPACE unique_weak_ptr Obj; + Map const* BoundMap = nullptr; +}; + +ElunaConstrainedObjectRef GetWeakPtrFor(Aura const* obj); +ElunaConstrainedObjectRef GetWeakPtrFor(Battleground const* obj); +ElunaConstrainedObjectRef GetWeakPtrFor(Group const* obj); +ElunaConstrainedObjectRef GetWeakPtrFor(Guild const* obj); +ElunaConstrainedObjectRef GetWeakPtrFor(Map const* obj); +ElunaConstrainedObjectRef GetWeakPtrForObjectImpl(Object const* obj); +ElunaConstrainedObjectRef GetWeakPtrFor(Quest const* obj); +ElunaConstrainedObjectRef GetWeakPtrFor(Spell const* obj); +ElunaConstrainedObjectRef GetWeakPtrFor(Vehicle const* obj); + +template +ElunaConstrainedObjectRef GetWeakPtrFor(T const* obj) +{ + ElunaConstrainedObjectRef ref = GetWeakPtrForObjectImpl(obj); + return { TRACKABLE_PTR_NAMESPACE static_pointer_cast(ref.Obj), ref.BoundMap }; +} + +#endif + template class ElunaObjectImpl : public ElunaObject { public: +#ifdef TRINITY + ElunaObjectImpl(Eluna* E, T const* obj, char const* tname) : ElunaObject(E, tname), _obj(GetWeakPtrFor(obj)) + { + } + + void* GetObjIfValid() const override + { + if (TRACKABLE_PTR_NAMESPACE unique_strong_ref_ptr obj = _obj.Obj.lock()) + if (!E->GetBoundMap() || !_obj.BoundMap || E->GetBoundMap() == _obj.BoundMap) + return obj.get(); + + return nullptr; + } +#else ElunaObjectImpl(Eluna* E, T* obj, char const* tname) : ElunaObject(E, tname), _obj(obj), callstackid(E->GetCallstackId()) { } - void* GetObj() const override { return _obj; } - bool IsValid() const override { return callstackid == E->GetCallstackId(); } + void* GetObjIfValid() const override + { + if (callstackid == E->GetCallstackId()) + return _obj; + + return nullptr; + } + void Invalidate() override { callstackid = 1; } +#endif private: +#ifdef TRINITY + ElunaConstrainedObjectRef _obj; +#else void* _obj; uint64 callstackid; +#endif }; template class ElunaObjectValueImpl : public ElunaObject { public: - ElunaObjectValueImpl(Eluna* E, T* obj, char const* tname) : ElunaObject(E, tname), _obj(*obj /*always a copy, what gets passed here might be pointing to something not owned by us*/) + ElunaObjectValueImpl(Eluna* E, T const* obj, char const* tname) : ElunaObject(E, tname), _obj(*obj /*always a copy, what gets passed here might be pointing to something not owned by us*/) { } - void* GetObj() const override { return const_cast(&_obj); } - bool IsValid() const override { return true; } + void* GetObjIfValid() const override { return const_cast(&_obj); } + +#ifndef TRINITY void Invalidate() override { } +#endif private: T _obj; @@ -375,7 +436,8 @@ class ElunaTemplate if (!elunaObj) return NULL; - if (!elunaObj->IsValid()) + void* obj = elunaObj->GetObjIfValid(); + if (!obj) { char buff[256]; snprintf(buff, 256, "%s expected, got pointer to nonexisting (invalidated) object (%s). Check your code.", tname, luaL_typename(L, narg)); @@ -389,7 +451,7 @@ class ElunaTemplate } return NULL; } - return static_cast(elunaObj->GetObj()); + return static_cast(obj); } static int GetType(lua_State* L) diff --git a/LuaEngine.cpp b/LuaEngine.cpp index 3f8e4ac203..b35df214dd 100644 --- a/LuaEngine.cpp +++ b/LuaEngine.cpp @@ -297,15 +297,13 @@ void Eluna::RunScripts() OnLuaStateOpen(); } +#ifndef TRINITY void Eluna::InvalidateObjects() { ++callstackid; -#ifdef TRINITY - ASSERT(callstackid, "Callstackid overflow"); -#else ASSERT(callstackid && "Callstackid overflow"); -#endif } +#endif void Eluna::Report(lua_State* _L) { @@ -989,8 +987,10 @@ void Eluna::CleanUpStack(int number_of_arguments) lua_pop(L, number_of_arguments + 1); // Add 1 because the caller doesn't know about `event_id`. // Stack: (empty) +#ifndef TRINITY if (event_level == 0) InvalidateObjects(); +#endif } /* diff --git a/LuaEngine.h b/LuaEngine.h index d500b00034..f3d2ac64a9 100644 --- a/LuaEngine.h +++ b/LuaEngine.h @@ -169,11 +169,13 @@ class ELUNA_GAME_API Eluna // Indicates that the lua state should be reloaded bool reload = false; +#ifndef TRINITY // A counter for lua event stacks that occur (see event_level). // This is used to determine whether an object belongs to the current call stack or not. // 0 is reserved for always belonging to the call stack // 1 is reserved for a non valid callstackid uint64 callstackid = 2; +#endif // A counter for the amount of nested events. When the event_level // reaches 0 we are about to return back to C++. At this point the // objects used during the event stack are invalidated. @@ -200,7 +202,9 @@ class ELUNA_GAME_API Eluna void CloseLua(); void DestroyBindStores(); void CreateBindStores(); +#ifndef TRINITY void InvalidateObjects(); +#endif // Use ReloadEluna() to make eluna reload // This is called on world update to reload eluna @@ -345,7 +349,9 @@ class ELUNA_GAME_API Eluna void RunScripts(); bool HasLuaState() const { return L != NULL; } +#ifndef TRINITY uint64 GetCallstackId() const { return callstackid; } +#endif int Register(uint8 reg, uint32 entry, ObjectGuid guid, uint32 instanceId, uint32 event_id, int functionRef, uint32 shots); void UpdateEluna(uint32 diff); diff --git a/LuaFunctions.cpp b/LuaFunctions.cpp index 2814855435..17080d80c4 100644 --- a/LuaFunctions.cpp +++ b/LuaFunctions.cpp @@ -37,6 +37,29 @@ extern "C" #include "VehicleMethods.h" #include "BattleGroundMethods.h" +#ifdef TRINITY +ElunaConstrainedObjectRef GetWeakPtrFor(Aura const* obj) { return { obj->GetWeakPtr(), obj->GetOwner()->GetMap() }; } +ElunaConstrainedObjectRef GetWeakPtrFor(Battleground const* obj) { return { obj->GetWeakPtr(), obj->GetBgMap() }; } +ElunaConstrainedObjectRef GetWeakPtrFor(Group const* obj) { return { obj->GetWeakPtr(), nullptr }; } +ElunaConstrainedObjectRef GetWeakPtrFor(Guild const* obj) { return { obj->GetWeakPtr(), nullptr }; } +ElunaConstrainedObjectRef GetWeakPtrFor(Map const* obj) { return { obj->GetWeakPtr(), obj }; } +ElunaConstrainedObjectRef GetWeakPtrForObjectImpl(Object const* obj) +{ + if (obj->isType(TYPEMASK_WORLDOBJECT)) + return { obj->GetWeakPtr(), static_cast(obj)->GetMap() }; + + if (obj->GetTypeId() == TYPEID_ITEM) + if (Player const* player = static_cast(obj)->GetOwner()) + return { obj->GetWeakPtr(), player->GetMap() }; + + // possibly dangerous item + return { obj->GetWeakPtr(), nullptr }; +} +ElunaConstrainedObjectRef GetWeakPtrFor(Quest const* obj) { return { obj->GetWeakPtr(), nullptr }; } +ElunaConstrainedObjectRef GetWeakPtrFor(Spell const* obj) { return { obj->GetWeakPtr(), obj->GetCaster()->GetMap() }; } +ElunaConstrainedObjectRef GetWeakPtrFor(Vehicle const* obj) { return { obj->GetWeakPtr(), obj->GetBase()->GetMap() }; } +#endif + // Template by Mud from http://stackoverflow.com/questions/4484437/lua-integer-type/4485511#4485511 template<> int ElunaTemplate::Add(lua_State* L) { Eluna* E = Eluna::GetEluna(L); E->Push(E->CHECKVAL(1) + E->CHECKVAL(2)); return 1; } template<> int ElunaTemplate::Substract(lua_State* L) { Eluna* E = Eluna::GetEluna(L); E->Push(E->CHECKVAL(1) - E->CHECKVAL(2)); return 1; } diff --git a/hooks/ServerHooks.cpp b/hooks/ServerHooks.cpp index 3c96dd735c..2cb4c74404 100644 --- a/hooks/ServerHooks.cpp +++ b/hooks/ServerHooks.cpp @@ -75,7 +75,9 @@ void Eluna::OnTimedEvent(int funcRef, uint32 delay, uint32 calls, WorldObject* o ExecuteCall(4, 0); ASSERT(!event_level); +#ifndef TRINITY InvalidateObjects(); +#endif } void Eluna::OnGameEventStart(uint32 eventid) diff --git a/methods/TrinityCore/AuraMethods.h b/methods/TrinityCore/AuraMethods.h index 84c3d47caa..c94245afea 100644 --- a/methods/TrinityCore/AuraMethods.h +++ b/methods/TrinityCore/AuraMethods.h @@ -162,10 +162,9 @@ namespace LuaAura /** * Remove this [Aura] from the [Unit] it is applied to. */ - int Remove(Eluna* E, Aura* aura) + int Remove(Eluna* /*E*/, Aura* aura) { aura->Remove(); - E->CHECKOBJ(1)->Invalidate(); return 0; } diff --git a/methods/TrinityCore/GameObjectMethods.h b/methods/TrinityCore/GameObjectMethods.h index 8d46911a74..3e53ee767c 100644 --- a/methods/TrinityCore/GameObjectMethods.h +++ b/methods/TrinityCore/GameObjectMethods.h @@ -265,7 +265,6 @@ namespace LuaGameObject go->SetRespawnTime(0); go->Delete(); - E->CHECKOBJ(1)->Invalidate(); return 0; } diff --git a/methods/TrinityCore/PlayerMethods.h b/methods/TrinityCore/PlayerMethods.h index 71d524b9fa..9309579f47 100644 --- a/methods/TrinityCore/PlayerMethods.h +++ b/methods/TrinityCore/PlayerMethods.h @@ -3163,10 +3163,7 @@ namespace LuaPlayer } else { - bool all = itemCount >= item->GetCount(); player->DestroyItemCount(item, itemCount, true); - if (all) - E->CHECKOBJ(2)->Invalidate(); } return 0; }