diff --git a/CreatureMethods.h b/CreatureMethods.h index d8c8b50..692aaf3 100644 --- a/CreatureMethods.h +++ b/CreatureMethods.h @@ -376,7 +376,7 @@ namespace LuaCreature return 1; if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) - targetList.sort(Eluna::ObjectDistanceOrderPred(creature)); + targetList.sort(ElunaUtil::ObjectDistanceOrderPred(creature)); switch (targetType) { diff --git a/ElunaBinding.h b/ElunaBinding.h new file mode 100644 index 0000000..2ade1b0 --- /dev/null +++ b/ElunaBinding.h @@ -0,0 +1,163 @@ +/* +* Copyright (C) 2010 - 2014 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef _ELUNA_BINDING_H +#define _ELUNA_BINDING_H + +#include "Common.h" +#include "LuaEngine.h" +#include "ElunaUtilitiy.h" + +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +}; + +class ElunaBind +{ +public: + Eluna& E; + const char* groupName; + + ElunaBind(const char* bindGroupName, Eluna& _E): E(_E), groupName(bindGroupName) + { + } + + virtual ~ElunaBind() + { + Clear(); + } + + // unregisters all registered functions and clears all registered events from the bindings + virtual void Clear() {}; +}; + +template +class EventBind : public ElunaBind +{ +public: + typedef std::vector ElunaBindingMap; + typedef std::map ElunaEntryMap; + + EventBind(const char* bindGroupName, Eluna& _E): ElunaBind(bindGroupName, _E) + { + } + + // unregisters all registered functions and clears all registered events from the bind std::maps (reset) + void Clear() override + { + for (ElunaEntryMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr) + { + for (ElunaBindingMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it) + luaL_unref(E.L, LUA_REGISTRYINDEX, (*it)); + itr->second.clear(); + } + Bindings.clear(); + } + + void Insert(int eventId, int funcRef) // Inserts a new registered event + { + Bindings[eventId].push_back(funcRef); + } + + // Gets the binding std::map containing all registered events with the function refs for the entry + ElunaBindingMap* GetBindMap(T eventId) + { + if (Bindings.empty()) + return NULL; + ElunaEntryMap::iterator itr = Bindings.find(eventId); + if (itr == Bindings.end()) + return NULL; + + return &itr->second; + } + + // Checks if there are events for ID + bool HasEvents(T eventId) const + { + if (Bindings.empty()) + return false; + if (Bindings.find(eventId) == Bindings.end()) + return false; + return true; + } + + ElunaEntryMap Bindings; // Binding store Bindings[eventId] = {funcRef}; +}; + +template +class EntryBind : public ElunaBind +{ +public: + typedef std::map ElunaBindingMap; + typedef UNORDERED_MAP ElunaEntryMap; + + EntryBind(const char* bindGroupName, Eluna& _E): ElunaBind(bindGroupName, _E) + { + } + + // unregisters all registered functions and clears all registered events from the bindmap + void Clear() override + { + for (ElunaEntryMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr) + { + for (ElunaBindingMap::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it) + luaL_unref(E.L, LUA_REGISTRYINDEX, it->second); + itr->second.clear(); + } + Bindings.clear(); + } + + void Insert(uint32 entryId, int eventId, int funcRef) // Inserts a new registered event + { + if (Bindings[entryId][eventId]) + { + luaL_unref(E.L, LUA_REGISTRYINDEX, funcRef); // free the unused ref + luaL_error(E.L, "A function is already registered for entry (%d) event (%d)", entryId, eventId); + } + else + Bindings[entryId][eventId] = funcRef; + } + + // Gets the function ref of an entry for an event + int GetBind(uint32 entryId, T eventId) const + { + if (Bindings.empty()) + return 0; + ElunaEntryMap::const_iterator itr = Bindings.find(entryId); + if (itr == Bindings.end() || itr->second.empty()) + return 0; + ElunaBindingMap::const_iterator itr2 = itr->second.find(eventId); + if (itr2 == itr->second.end()) + return 0; + return itr2->second; + } + + // Gets the binding std::map containing all registered events with the function refs for the entry + const ElunaBindingMap* GetBindMap(uint32 entryId) const + { + if (Bindings.empty()) + return NULL; + ElunaEntryMap::const_iterator itr = Bindings.find(entryId); + if (itr == Bindings.end()) + return NULL; + + return &itr->second; + } + + // Returns true if the entry has registered binds + bool HasBinds(uint32 entryId) const + { + if (Bindings.empty()) + return false; + return Bindings.find(entryId) != Bindings.end(); + } + + ElunaEntryMap Bindings; // Binding store Bindings[entryId][eventId] = funcRef; +}; + +#endif diff --git a/ElunaEventMgr.cpp b/ElunaEventMgr.cpp new file mode 100644 index 0000000..d3a6cae --- /dev/null +++ b/ElunaEventMgr.cpp @@ -0,0 +1,151 @@ +/* +* Copyright (C) 2010 - 2014 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#include "ElunaEventMgr.h" +#include "LuaEngine.h" + +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +}; + +LuaEvent::LuaEvent(Eluna& _E, EventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls, Object* _obj): +E(_E), events(_events), funcRef(_funcRef), delay(_delay), calls(_calls), obj(_obj) +{ + if (_events) + E.m_EventMgr->LuaEvents[_events].insert(this); // Able to access the event if we have the processor +} + +LuaEvent::~LuaEvent() +{ + if (events) + { + // Attempt to remove the pointer from LuaEvents + EventMgr::EventMap::const_iterator it = E.m_EventMgr->LuaEvents.find(events); // Get event set + if (it != E.m_EventMgr->LuaEvents.end()) + E.m_EventMgr->LuaEvents[events].erase(this);// Remove pointer + } + luaL_unref(E.L, LUA_REGISTRYINDEX, funcRef); // Free lua function ref +} + +bool LuaEvent::Execute(uint64 /*time*/, uint32 /*diff*/) +{ + bool remove = (calls == 1); + if (!remove) + events->AddEvent(this, events->CalculateTime(delay)); // Reschedule before calling incase RemoveEvents used + lua_rawgeti(E.L, LUA_REGISTRYINDEX, funcRef); + Eluna::Push(E.L, funcRef); + Eluna::Push(E.L, delay); + Eluna::Push(E.L, calls); + if (!remove && calls) + --calls; + Eluna::Push(E.L, obj); + Eluna::ExecuteCall(E.L, 4, 0); + return remove; // Destory (true) event if not run +} + +EventMgr::EventMgr(Eluna& _E): E(_E) +{ +} + +EventMgr::~EventMgr() +{ + RemoveEvents(); +} + +void EventMgr::Update(uint32 diff) +{ + GlobalEvents.Update(diff); +} + +/* +void EventMgr::KillAllEvents(EventProcessor* events) +{ + if (!events) + return; + if (LuaEvents.empty()) + return; + EventMap::const_iterator it = LuaEvents.find(events); // Get event set + if (it == LuaEvents.end()) + return; + if (it->second.empty()) + return; + for (EventSet::const_iterator itr = it->second.begin(); itr != it->second.end();) // Loop events + (*(itr++))->to_Abort = true; // Abort event +} +*/ + +void EventMgr::RemoveEvents() +{ + if (!LuaEvents.empty()) + for (EventMap::const_iterator it = LuaEvents.begin(); it != LuaEvents.end();) // loop processors + (it++)->first->KillAllEvents(false); // KillAllEvents((it++)->first); + LuaEvents.clear(); // remove pointers + // This is handled automatically on delete + // for (ProcessorMap::iterator it = Processors.begin(); it != Processors.end();) + // (it++)->second.KillAllEvents(true); + // Processors.clear(); // remove guid saved processors + GlobalEvents.KillAllEvents(true); +} + +void EventMgr::RemoveEvents(EventProcessor* events) +{ + if (!events) + return; + // KillAllEvents(events); + events->KillAllEvents(false); + LuaEvents.erase(events); // remove pointer set +} + +int EventMgr::AddEvent(EventProcessor* events, int funcRef, uint32 delay, uint32 calls, Object* obj) +{ + if (!events || funcRef <= 0) // If funcRef <= 0, function reference failed + return 0; // on fail always return 0. funcRef can be negative. + events->AddEvent(new LuaEvent(E, events, funcRef, delay, calls, obj), events->CalculateTime(delay)); + return funcRef; // return the event ID +} + +LuaEvent* EventMgr::GetEvent(EventProcessor* events, int eventId) +{ + if (!events || !eventId) + return NULL; + if (LuaEvents.empty()) + return NULL; + EventMap::const_iterator it = LuaEvents.find(events); // Get event set + if (it == LuaEvents.end()) + return NULL; + if (it->second.empty()) + return NULL; + for (EventSet::const_iterator itr = it->second.begin(); itr != it->second.end(); ++itr) // Loop events + if ((*itr) && (*itr)->funcRef == eventId) // Check if the event has our ID + return *itr; // Return the event if found + return NULL; +} + +bool EventMgr::RemoveEvent(EventProcessor* events, int eventId) +{ + // eventId = funcRef + if (!events || !eventId) + return false; + LuaEvent* luaEvent = GetEvent(events, eventId); + if (!luaEvent) + return false; + luaEvent->to_Abort = true; // Set to remove on next call + LuaEvents[events].erase(luaEvent); // Remove pointer + return true; +} + +void EventMgr::RemoveEvent(int eventId) +{ + if (!eventId) + return; + if (LuaEvents.empty()) + return; + for (EventMap::const_iterator it = LuaEvents.begin(); it != LuaEvents.end();) // loop processors + if (RemoveEvent((it++)->first, eventId)) + break; // succesfully remove the event, stop loop. +} diff --git a/ElunaEventMgr.h b/ElunaEventMgr.h new file mode 100644 index 0000000..9a326c5 --- /dev/null +++ b/ElunaEventMgr.h @@ -0,0 +1,82 @@ +/* +* Copyright (C) 2010 - 2014 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef _ELUNA_EVENT_MGR_H +#define _ELUNA_EVENT_MGR_H + +#include "Common.h" +#ifdef TRINITY +#include "EventProcessor.h" +#else +#include "Utilities/EventProcessor.h" +#endif + +class Eluna; +class EventMgr; +class EventProcessor; +class Object; + +class LuaEvent : public BasicEvent +{ + friend class EventMgr; + +public: + LuaEvent(Eluna& _E, EventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls, Object* _obj); + ~LuaEvent(); + + // Should never execute on dead events + bool Execute(uint64 time, uint32 diff); + +private: + Eluna& E; + EventProcessor* events; // Pointer to events (holds the timed event) + int funcRef; // Lua function reference ID, also used as event ID + uint32 delay; // Delay between event calls + uint32 calls; // Amount of calls to make, 0 for infinite + Object* obj; // Object to push +}; + +class EventMgr +{ +public: + typedef std::set EventSet; + typedef std::map EventMap; + Eluna& E; + + EventMap LuaEvents; // LuaEvents[processor] = {LuaEvent, LuaEvent...} + EventProcessor GlobalEvents; + + EventMgr(Eluna& _E); + ~EventMgr(); + + // Should be run on world tick + void Update(uint32 diff); + + // Aborts all lua events + // void KillAllEvents(EventProcessor* events); + + // Remove all timed events + void RemoveEvents(); + + // Remove timed events from processor + void RemoveEvents(EventProcessor* events); + + // Adds a new event to the processor and returns the eventID or 0 (Never negative) + int AddEvent(EventProcessor* events, int funcRef, uint32 delay, uint32 calls, Object* obj = NULL); + + // Finds the event that has the ID from events + LuaEvent* GetEvent(EventProcessor* events, int eventId); + + // Remove the event with the eventId from processor + // Returns true if event is removed + // EventId is func ref + bool RemoveEvent(EventProcessor* events, int eventId); + + // Removes the eventId from all events + void RemoveEvent(int eventId); +}; + +#endif diff --git a/ElunaIncludes.h b/ElunaIncludes.h new file mode 100644 index 0000000..18b32c0 --- /dev/null +++ b/ElunaIncludes.h @@ -0,0 +1,124 @@ +/* +* Copyright (C) 2010 - 2014 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +// Required +#include "AccountMgr.h" +#include "AuctionHouseMgr.h" +#include "Cell.h" +#include "CellImpl.h" +#include "Chat.h" +#include "Channel.h" +#include "DBCStores.h" +#include "GossipDef.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "Group.h" +#include "Guild.h" +#include "GuildMgr.h" +#include "Language.h" +#include "Mail.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "Opcodes.h" +#include "Player.h" +#include "Pet.h" +#include "ReputationMgr.h" +#include "revision.h" +#include "ScriptMgr.h" +#include "Spell.h" +#include "SpellAuras.h" +#include "SpellMgr.h" +#include "TemporarySummon.h" +#include "WorldPacket.h" +#include "WorldSession.h" + +#ifdef TRINITY +#include "Config.h" +#include "ScriptedCreature.h" +#include "SpellInfo.h" +#include "WeatherMgr.h" +#else +#include "Config/Config.h" +#include "ReactorAI.h" +#include "revision_nr.h" +#endif + +#if (!defined(TBC) && !defined(CLASSIC)) +#include "Vehicle.h" +#endif + +#ifndef CLASSIC +#include "ArenaTeam.h" +#endif + +#ifndef CLASSIC +typedef Opcodes OpcodesList; +#endif + +#ifdef MANGOS +#define CORE_NAME "MaNGOS" +#define CORE_VERSION REVISION_NR +#endif + +#ifdef CMANGOS +#define CORE_NAME "cMaNGOS" +#define CORE_VERSION REVISION_NR +#endif + +#ifdef TRINITY +#define CORE_NAME "TrinityCore" +#define CORE_VERSION _DATE +#define eWorld (sWorld) +#define eMapMgr (sMapMgr) +#define eConfigMgr (sConfigMgr) +#define eGuildMgr (sGuildMgr) +#define eObjectMgr (sObjectMgr) +#define eAccountMgr (sAccountMgr) +#define eObjectAccessor (sObjectAccessor) +#define REGEN_TIME_FULL +typedef ThreatContainer::StorageType ThreatList; + +#ifdef CATA +#define NUM_MSG_TYPES NUM_OPCODE_HANDLERS +#else +typedef uint64 ObjectGuid; +#endif +#endif + +#ifndef TRINITY +#define eWorld (&sWorld) +#define eMapMgr (&sMapMgr) +#define eConfigMgr (&sConfig) +#define eGuildMgr (&sGuildMgr) +#define eObjectMgr (&sObjectMgr) +#define eAccountMgr (&sAccountMgr) +#define eObjectAccessor (&sObjectAccessor) +#define SERVER_MSG_STRING SERVER_MSG_CUSTOM +#define MAX_LOCALES MAX_LOCALE +#define DIALOG_STATUS_SCRIPTED_NO_STATUS DIALOG_STATUS_UNDEFINED +#define TARGETICONCOUNT TARGET_ICON_COUNT +#define MAX_TALENT_SPECS MAX_TALENT_SPEC_COUNT + +#ifndef CLASSIC +#define PLAYER_FIELD_LIFETIME_HONORABLE_KILLS PLAYER_FIELD_LIFETIME_HONORBALE_KILLS +#endif + +#ifdef TBC +#define SPELL_AURA_MOD_KILL_XP_PCT SPELL_AURA_MOD_XP_PCT +#endif + +typedef TemporarySummon TempSummon; +typedef SpellEntry SpellInfo; +enum SelectAggroTarget +{ + SELECT_TARGET_RANDOM = 0, // Just selects a random target + SELECT_TARGET_TOPAGGRO, // Selects targes from top aggro to bottom + SELECT_TARGET_BOTTOMAGGRO, // Selects targets from bottom aggro to top + SELECT_TARGET_NEAREST, + SELECT_TARGET_FARTHEST +}; +#endif diff --git a/ElunaTemplate.h b/ElunaTemplate.h new file mode 100644 index 0000000..ab47efd --- /dev/null +++ b/ElunaTemplate.h @@ -0,0 +1,257 @@ +/* +* Copyright (C) 2010 - 2014 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef _ELUNA_TEMPLATE_H +#define _ELUNA_TEMPLATE_H + +extern "C" +{ +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +}; +#include "LuaEngine.h" +#include "ElunaUtilitiy.h" + +template +struct ElunaRegister +{ + const char* name; + int(*mfunc)(lua_State*, T*); +}; + +template +class ElunaTemplate +{ +public: + static const char* tname; + static bool manageMemory; + + static int typeT(lua_State* L) + { + lua_pushstring(L, tname); + return 1; + } + + // name will be used as type name + // If gc is true, lua will handle the memory management for object pushed + // gc should be used if pushing for example WorldPacket, + // that will only be needed on lua side and will not be managed by TC/mangos/ + static void Register(lua_State* L, const char* name, bool gc = false) + { + tname = name; + manageMemory = gc; + + lua_newtable(L); + int methods = lua_gettop(L); + + // store method table in globals so that + // scripts can add functions in Lua + lua_pushvalue(L, methods); + lua_setglobal(L, tname); + + luaL_newmetatable(L, tname); + int metatable = lua_gettop(L); + + // tostring + lua_pushcfunction(L, tostringT); + lua_setfield(L, metatable, "__tostring"); + + // garbage collecting + if (manageMemory) + { + lua_pushcfunction(L, gcT); + lua_setfield(L, metatable, "__gc"); + } + + // make methods accessible through metatable + lua_pushvalue(L, methods); + lua_setfield(L, metatable, "__index"); + + // make new indexes saved to methods + lua_pushvalue(L, methods); + lua_setfield(L, metatable, "__newindex"); + + // special method to get the object type + lua_pushcfunction(L, typeT); + lua_setfield(L, methods, "GetObjectType"); + + // pop methods and metatable + lua_pop(L, 2); + } + + template + static void SetMethods(lua_State* L, ElunaRegister* methodTable) + { + if (!methodTable) + return; + + luaL_getmetatable(L, tname); + if (!lua_istable(L, -1)) + { + lua_remove(L, -1); + ELUNA_LOG_ERROR("%s missing metatable", tname); + return; + } + + lua_getfield(L, -1, "__index"); + lua_remove(L, -2); + if (!lua_istable(L, -1)) + { + lua_remove(L, -1); + ELUNA_LOG_ERROR("%s missing method table from metatable", tname); + return; + } + + for (; methodTable && methodTable->name && methodTable->mfunc; ++methodTable) + { + lua_pushstring(L, methodTable->name); + lua_pushlightuserdata(L, (void*)methodTable); + lua_pushcclosure(L, thunk, 1); + lua_settable(L, -3); + } + + lua_remove(L, -1); + } + + // Remember special case ElunaTemplate::gcT + static int gcT(lua_State* L) + { + if (!manageMemory) + return 0; + + // Get object pointer (and check type, no error) + T** ptrHold = static_cast(luaL_testudata(L, -1, tname)); + if (ptrHold) + delete *ptrHold; + return 0; + } + + static int push(lua_State* L, T const* obj) + { + if (!obj) + { + lua_pushnil(L); + return 1; + } + + if (!manageMemory) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, sEluna->userdata_table); + lua_pushfstring(L, "%p", obj); + lua_gettable(L, -2); + if (!lua_isnoneornil(L, -1) && luaL_checkudata(L, -1, tname)) + { + lua_remove(L, -2); + return 1; + } + lua_remove(L, -1); + // left userdata_table in stack + } + + // Create new userdata + T const** ptrHold = static_cast(lua_newuserdata(L, sizeof(T const*))); + if (!ptrHold) + { + ELUNA_LOG_ERROR("%s could not create new userdata", tname); + lua_pop(L, manageMemory ? 1 : 2); + lua_pushnil(L); + return 1; + } + *ptrHold = obj; + + // Set metatable for it + luaL_getmetatable(L, tname); + if (!lua_istable(L, -1)) + { + ELUNA_LOG_ERROR("%s missing metatable", tname); + lua_pop(L, manageMemory ? 2 : 3); + lua_pushnil(L); + return 1; + } + lua_setmetatable(L, -2); + + if (!manageMemory) + { + lua_pushfstring(L, "%p", obj); + lua_pushvalue(L, -2); + lua_settable(L, -4); + lua_remove(L, -2); + } + return 1; + } + + static T* check(lua_State* L, int narg, bool error = true) + { + T** ptrHold = static_cast(lua_touserdata(L, narg)); + if (!ptrHold) + { + if (error) + { + char buff[256]; + snprintf(buff, 256, "%s expected, got %s", tname, luaL_typename(L, narg)); + luaL_argerror(L, narg, buff); + } + return NULL; + } + + if (!manageMemory) + { + // Check pointer validity + lua_rawgeti(L, LUA_REGISTRYINDEX, sEluna->userdata_table); + lua_pushfstring(L, "%p", *ptrHold); + lua_gettable(L, -2); + lua_remove(L, -2); + bool valid = lua_isuserdata(L, -1); + lua_remove(L, -1); + if (!valid) + { + char buff[256]; + snprintf(buff, 256, "%s expected, got pointer to nonexisting object (%s). This should never happen", tname, luaL_typename(L, narg)); + if (error) + { + luaL_argerror(L, narg, buff); + } + else + { + ELUNA_LOG_ERROR("%s", buff); + } + return NULL; + } + } + return *ptrHold; + } + + static int thunk(lua_State* L) + { + T* obj = Eluna::CHECKOBJ(L, 1); // get self + if (!obj) + return 0; + ElunaRegister* l = static_cast*>(lua_touserdata(L, lua_upvalueindex(1))); + int args = lua_gettop(L); + int expected = l->mfunc(L, obj); + args = lua_gettop(L) - args; + if (args < 0 || args > expected) // Assert instead? + { + ELUNA_LOG_ERROR("[Eluna]: %s returned unexpected amount of arguments %i out of %i. Report to devs", l->name, args, expected); + } + for (; args < expected; ++args) + lua_pushnil(L); + return expected; + } + + static int tostringT(lua_State* L) + { + T* obj = Eluna::CHECKOBJ(L, 1); // get self + if (obj) + lua_pushfstring(L, "%s: (%p)", tname, obj); + else + lua_pushstring(L, "nil"); + return 1; + } +}; + +#endif diff --git a/ElunaUtilitiy.cpp b/ElunaUtilitiy.cpp new file mode 100644 index 0000000..2f6099c --- /dev/null +++ b/ElunaUtilitiy.cpp @@ -0,0 +1,87 @@ +/* +* Copyright (C) 2010 - 2014 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#include "ElunaUtilitiy.h" +#include "World.h" +#include "Object.h" +#include "Unit.h" + +uint32 ElunaUtil::GetCurrTime() +{ +#ifndef TRINITY + return WorldTimer::getMSTime(); +#else + return getMSTime(); +#endif +} + +uint32 ElunaUtil::GetTimeDiff(uint32 oldMSTime) +{ +#ifndef TRINITY + return WorldTimer::getMSTimeDiff(oldMSTime, GetCurrTime()); +#else + return GetMSTimeDiffToNow(oldMSTime); +#endif +} + +ElunaUtil::ObjectGUIDCheck::ObjectGUIDCheck(ObjectGuid guid): _guid(guid) +{ +} + +bool ElunaUtil::ObjectGUIDCheck::operator()(WorldObject* object) +{ + return object->GET_GUID() == _guid; +} + +ElunaUtil::ObjectDistanceOrderPred::ObjectDistanceOrderPred(WorldObject const* pRefObj, bool ascending): m_refObj(pRefObj), m_ascending(ascending) +{ +} +bool ElunaUtil::ObjectDistanceOrderPred::operator()(WorldObject const* pLeft, WorldObject const* pRight) const +{ + return m_ascending ? m_refObj->GetDistanceOrder(pLeft, pRight) : !m_refObj->GetDistanceOrder(pLeft, pRight); +} + +ElunaUtil::WorldObjectInRangeCheck::WorldObjectInRangeCheck(bool nearest, WorldObject const* obj, float range, + uint16 typeMask, uint32 entry, uint32 hostile): i_nearest(nearest), + i_obj(obj), i_range(range), i_typeMask(typeMask), i_entry(entry), i_hostile(hostile) +{ +} +WorldObject const& ElunaUtil::WorldObjectInRangeCheck::GetFocusObject() const +{ + return *i_obj; +} +bool ElunaUtil::WorldObjectInRangeCheck::operator()(WorldObject* u) +{ + if (i_typeMask && !u->isType(TypeMask(i_typeMask))) + return false; + if (i_entry && u->GetEntry() != i_entry) + return false; + if (i_obj->GET_GUID() == u->GET_GUID()) + return false; + if (!i_obj->IsWithinDistInMap(u, i_range)) + return false; + if (Unit* unit = u->ToUnit()) + { +#ifdef CMANGOS + if (!unit->isAlive()) + return false; +#else + if (!unit->IsAlive()) + return false; +#endif + if (i_hostile) + { + if (const Unit* obj = i_obj->ToUnit()) + { + if ((i_hostile == 1) != obj->IsHostileTo(unit)) + return false; + } + } + } + if (i_nearest) + i_range = i_obj->GetDistance(u); + return true; +} diff --git a/ElunaUtilitiy.h b/ElunaUtilitiy.h new file mode 100644 index 0000000..11da784 --- /dev/null +++ b/ElunaUtilitiy.h @@ -0,0 +1,89 @@ +/* +* Copyright (C) 2010 - 2014 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef _ELUNA_UTIL_H +#define _ELUNA_UTIL_H + +#include "Common.h" +#include "SharedDefines.h" + +#ifdef TRINITY +#ifndef CATA +typedef uint64 ObjectGuid; +#endif +#define ELUNA_LOG_INFO(...) TC_LOG_INFO("eluna", __VA_ARGS__); +#define ELUNA_LOG_ERROR(...) TC_LOG_ERROR("eluna", __VA_ARGS__); +#define ELUNA_LOG_DEBUG(...) TC_LOG_DEBUG("eluna", __VA_ARGS__); +#define GET_GUID GetGUID +#else +#define MAKE_NEW_GUID(l, e, h) ObjectGuid(h, e, l) +#define GUID_ENPART(guid) ObjectGuid(guid).GetEntry() +#define GUID_LOPART(guid) ObjectGuid(guid).GetCounter() +#define GUID_HIPART(guid) ObjectGuid(guid).GetHigh() +#define ASSERT MANGOS_ASSERT +#define ELUNA_LOG_INFO(...) sLog.outString(__VA_ARGS__); +#define ELUNA_LOG_ERROR(...) sLog.outErrorEluna(__VA_ARGS__); +#define ELUNA_LOG_DEBUG(...) sLog.outDebug(__VA_ARGS__); +#define GET_GUID GetObjectGuid +#define GetGameObjectTemplate GetGameObjectInfo +#define GetItemTemplate GetItemPrototype +#define GetTemplate GetProto +#endif + +#ifndef UNORDERED_MAP +#define UNORDERED_MAP std::unordered_map +#endif + +class Unit; +class WorldObject; + +namespace ElunaUtil +{ + uint32 GetCurrTime(); + + uint32 GetTimeDiff(uint32 oldMSTime); + + class ObjectGUIDCheck + { + public: + ObjectGUIDCheck(ObjectGuid guid); + bool operator()(WorldObject* object); + + ObjectGuid _guid; + }; + + // Binary predicate to sort WorldObjects based on the distance to a reference WorldObject + class ObjectDistanceOrderPred + { + public: + ObjectDistanceOrderPred(WorldObject const* pRefObj, bool ascending = true); + bool operator()(WorldObject const* pLeft, WorldObject const* pRight) const; + + WorldObject const* m_refObj; + const bool m_ascending; + }; + + // Doesn't get self + class WorldObjectInRangeCheck + { + public: + WorldObjectInRangeCheck(bool nearest, WorldObject const* obj, float range, + uint16 typeMask = 0, uint32 entry = 0, uint32 hostile = 0); + WorldObject const& GetFocusObject() const; + bool operator()(WorldObject* u); + + bool i_nearest; + WorldObject const* i_obj; + float i_range; + uint16 i_typeMask; + uint32 i_entry; + uint32 i_hostile; + + WorldObjectInRangeCheck(WorldObjectInRangeCheck const&); + }; +}; + +#endif diff --git a/HookMgr.cpp b/HookMgr.cpp index e183431..6360b6a 100644 --- a/HookMgr.cpp +++ b/HookMgr.cpp @@ -6,7 +6,24 @@ #include "HookMgr.h" #include "LuaEngine.h" -#include "Includes.h" +#include "ElunaBinding.h" +#include "ElunaEventMgr.h" +#include "ElunaIncludes.h" +#include "ElunaTemplate.h" + +extern "C" +{ +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +}; + +#ifndef TRINITY +class ReactorAI; +typedef ReactorAI ScriptedAI; +#else +struct ScriptedAI; +#endif using namespace HookMgr; diff --git a/Includes.h b/Includes.h deleted file mode 100644 index ffda7c9..0000000 --- a/Includes.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -* Copyright (C) 2010 - 2014 Eluna Lua Engine -* This program is free software licensed under GPL version 3 -* Please see the included DOCS/LICENSE.md for more information -*/ - -// Required -#include "AuctionHouseMgr.h" -#include "Cell.h" -#include "CellImpl.h" -#include "Chat.h" -#include "Channel.h" -#include "DBCStores.h" -#include "GossipDef.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "Group.h" -#include "Guild.h" -#include "GuildMgr.h" -#include "Language.h" -#include "Mail.h" -#include "MapManager.h" -#include "ObjectAccessor.h" -#include "ObjectMgr.h" -#include "Opcodes.h" -#include "Player.h" -#include "Pet.h" -#include "ReputationMgr.h" -#include "revision.h" -#include "ScriptMgr.h" -#include "Spell.h" -#include "SpellAuras.h" -#include "SpellMgr.h" -#include "TemporarySummon.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#ifndef TRINITY -#include "ReactorAI.h" -#include "revision_nr.h" -#else -#include "ScriptedCreature.h" -#include "SpellInfo.h" -#include "WeatherMgr.h" -#endif -#if (!defined(TBC) && !defined(CLASSIC)) -#include "Vehicle.h" -#endif -#ifndef CLASSIC -#include "ArenaTeam.h" -#endif diff --git a/LuaEngine.cpp b/LuaEngine.cpp index f2ed440..31a6293 100644 --- a/LuaEngine.cpp +++ b/LuaEngine.cpp @@ -8,7 +8,18 @@ #include #include "HookMgr.h" #include "LuaEngine.h" -#include "Includes.h" +#include "ElunaBinding.h" +#include "ElunaEventMgr.h" +#include "ElunaIncludes.h" +#include "ElunaTemplate.h" +#include "ElunaUtilitiy.h" + +extern "C" +{ +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +}; Eluna::ScriptList Eluna::lua_scripts; Eluna::ScriptList Eluna::lua_extensions; @@ -20,7 +31,7 @@ extern void RegisterFunctions(lua_State* L); void Eluna::Initialize() { - uint32 oldMSTime = GetCurrTime(); + uint32 oldMSTime = ElunaUtil::GetCurrTime(); lua_scripts.clear(); lua_extensions.clear(); @@ -35,7 +46,7 @@ void Eluna::Initialize() // GetScripts(lua_folderpath + "/extensions", lua_extensions); GetScripts(lua_folderpath, lua_scripts); - ELUNA_LOG_DEBUG("[Eluna]: Loaded %u scripts in %u ms", uint32(lua_scripts.size() + lua_extensions.size()), GetTimeDiff(oldMSTime)); + ELUNA_LOG_DEBUG("[Eluna]: Loaded %u scripts in %u ms", uint32(lua_scripts.size() + lua_extensions.size()), ElunaUtil::GetTimeDiff(oldMSTime)); // Create global eluna new Eluna(); @@ -114,11 +125,11 @@ Eluna::~Eluna() { OnLuaStateClose(); + delete m_EventMgr; + // Replace this with map remove if making multithread version Eluna::GEluna = NULL; - delete m_EventMgr; - delete ServerEventBindings; delete PlayerEventBindings; delete GuildEventBindings; @@ -203,7 +214,7 @@ void Eluna::GetScripts(std::string path, ScriptList& scripts) void Eluna::RunScripts() { - uint32 oldMSTime = GetCurrTime(); + uint32 oldMSTime = ElunaUtil::GetCurrTime(); uint32 count = 0; ScriptList scripts; @@ -242,7 +253,7 @@ void Eluna::RunScripts() } lua_pop(L, 2); - ELUNA_LOG_INFO("[Eluna]: Executed %u Lua scripts in %u ms", count, GetTimeDiff(oldMSTime)); + ELUNA_LOG_INFO("[Eluna]: Executed %u Lua scripts in %u ms", count, ElunaUtil::GetTimeDiff(oldMSTime)); } void Eluna::RemoveRef(const void* obj) @@ -747,38 +758,3 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) luaL_unref(L, LUA_REGISTRYINDEX, functionRef); luaL_error(L, "Unknown event type (regtype %d, id %d, event %d)", regtype, id, evt); } - -EventMgr::LuaEvent::LuaEvent(Eluna& _E, EventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls, Object* _obj): -E(_E), events(_events), funcRef(_funcRef), delay(_delay), calls(_calls), obj(_obj) -{ - if (_events) - E.m_EventMgr->LuaEvents[_events].insert(this); // Able to access the event if we have the processor -} - -EventMgr::LuaEvent::~LuaEvent() -{ - if (events) - { - // Attempt to remove the pointer from LuaEvents - EventMgr::EventMap::const_iterator it = E.m_EventMgr->LuaEvents.find(events); // Get event set - if (it != E.m_EventMgr->LuaEvents.end()) - E.m_EventMgr->LuaEvents[events].erase(this);// Remove pointer - } - luaL_unref(E.L, LUA_REGISTRYINDEX, funcRef); // Free lua function ref -} - -bool EventMgr::LuaEvent::Execute(uint64 /*time*/, uint32 /*diff*/) -{ - bool remove = (calls == 1); - if (!remove) - events->AddEvent(this, events->CalculateTime(delay)); // Reschedule before calling incase RemoveEvents used - lua_rawgeti(E.L, LUA_REGISTRYINDEX, funcRef); - Eluna::Push(E.L, funcRef); - Eluna::Push(E.L, delay); - Eluna::Push(E.L, calls); - if (!remove && calls) - --calls; - Eluna::Push(E.L, obj); - Eluna::ExecuteCall(E.L, 4, 0); - return remove; // Destory (true) event if not run -} diff --git a/LuaEngine.h b/LuaEngine.h index d3e552e..dc0116e 100644 --- a/LuaEngine.h +++ b/LuaEngine.h @@ -4,70 +4,55 @@ * Please see the included DOCS/LICENSE.md for more information */ -#ifndef __ELUNA__H -#define __ELUNA__H +#ifndef _LUA_ENGINE_H +#define _LUA_ENGINE_H -extern "C" -{ -#include "lua.h" -#include "lualib.h" -#include "lauxlib.h" -}; - -// Base #include "Common.h" #include "SharedDefines.h" -#include -#include -// enums & singletons -#include "HookMgr.h" -#ifndef TRINITY -#include "AccountMgr.h" -#include "Config/Config.h" -#include "Player.h" -#else -#include "Config.h" -#include "GameObjectAI.h" -#endif +#include "DBCEnums.h" + #include "Group.h" #include "Item.h" -#include "Opcodes.h" #include "Weather.h" #include "World.h" +#include "HookMgr.h" -#ifndef TRINITY -typedef SpellEffectIndex SpellEffIndex; -typedef SpellEntry SpellInfo; +#ifdef TRINITY +struct ItemTemplate; +#else +struct ItemPrototype; typedef ItemPrototype ItemTemplate; -#define GetTemplate GetProto +typedef SpellEffectIndex SpellEffIndex; #ifdef CLASSIC typedef int Difficulty; #endif #endif struct AreaTriggerEntry; -#ifndef TRINITY -class ReactorAI; -typedef ReactorAI ScriptedAI; -#else -#undef UNORDERED_MAP -#define UNORDERED_MAP std::unordered_map -struct ScriptedAI; -#endif class AuctionHouseObject; class Channel; +class Corpse; class Creature; class CreatureAI; class GameObject; +#ifdef TRINITY +class GameObjectAI; +#endif class Guild; class Group; class Item; +class Pet; class Player; class Quest; class Spell; class SpellCastTargets; +#ifdef TRINITY +class TempSummon; +#else class TemporarySummon; -class Transport; +typedef TemporarySummon TempSummon; +#endif +// class Transport; class Unit; class Weather; class WorldPacket; @@ -82,265 +67,22 @@ typedef VehicleInfo Vehicle; #endif #endif -#ifndef TRINITY -#define eWorld (&sWorld) -#define eMapMgr (&sMapMgr) -#define eConfigMgr (&sConfig) -#define eGuildMgr (&sGuildMgr) -#define eObjectMgr (&sObjectMgr) -#define eAccountMgr (&sAccountMgr) -#define eObjectAccessor (&sObjectAccessor) -#define MAKE_NEW_GUID(l, e, h) ObjectGuid(h, e, l) -#define GET_GUID GetObjectGuid -#define GetGameObjectTemplate GetGameObjectInfo -#define GetItemTemplate GetItemPrototype -#define ELUNA_LOG_INFO(...) sLog.outString(__VA_ARGS__); -#define ELUNA_LOG_ERROR(...) sLog.outErrorEluna(__VA_ARGS__); -#define ELUNA_LOG_DEBUG(...) sLog.outDebug(__VA_ARGS__); -#define CORE_VERSION REVISION_NR -#define CORE_NAME "MaNGOS" -#define SERVER_MSG_STRING SERVER_MSG_CUSTOM -#define MAX_LOCALES MAX_LOCALE -#define DIALOG_STATUS_SCRIPTED_NO_STATUS DIALOG_STATUS_UNDEFINED -#define TARGETICONCOUNT TARGET_ICON_COUNT -typedef TemporarySummon TempSummon; -#ifndef CLASSIC -#define PLAYER_FIELD_LIFETIME_HONORABLE_KILLS PLAYER_FIELD_LIFETIME_HONORBALE_KILLS -#endif -#define MAX_TALENT_SPECS MAX_TALENT_SPEC_COUNT -#define GUID_ENPART(guid) ObjectGuid(guid).GetEntry() -#define GUID_LOPART(guid) ObjectGuid(guid).GetCounter() -#define GUID_HIPART(guid) ObjectGuid(guid).GetHigh() -#define ASSERT MANGOS_ASSERT -enum SelectAggroTarget -{ - SELECT_TARGET_RANDOM = 0, // Just selects a random target - SELECT_TARGET_TOPAGGRO, // Selects targes from top aggro to bottom - SELECT_TARGET_BOTTOMAGGRO, // Selects targets from bottom aggro to top - SELECT_TARGET_NEAREST, - SELECT_TARGET_FARTHEST -}; -#ifdef TBC -#define SPELL_AURA_MOD_KILL_XP_PCT SPELL_AURA_MOD_XP_PCT -#endif -#else -#define eWorld (sWorld) -#define eMapMgr (sMapMgr) -#define eConfigMgr (sConfigMgr) -#define eGuildMgr (sGuildMgr) -#define eObjectMgr (sObjectMgr) -#define eAccountMgr (sAccountMgr) -#define eObjectAccessor (sObjectAccessor) -#ifndef CATA -typedef uint64 ObjectGuid; -#endif -#define GET_GUID GetGUID -#define CORE_VERSION _DATE -#define CORE_NAME "TrinityCore" -#define REGEN_TIME_FULL -#define ELUNA_LOG_INFO(...) TC_LOG_INFO("eluna", __VA_ARGS__); -#define ELUNA_LOG_ERROR(...) TC_LOG_ERROR("eluna", __VA_ARGS__); -#define ELUNA_LOG_DEBUG(...) TC_LOG_DEBUG("eluna", __VA_ARGS__); -typedef ThreatContainer::StorageType ThreatList; -#ifdef CATA -#define NUM_MSG_TYPES NUM_OPCODE_HANDLERS -#endif -#endif -#ifndef CLASSIC -typedef Opcodes OpcodesList; -#endif - -class Eluna; - -template -struct ElunaRegister -{ - const char* name; - int(*mfunc)(lua_State*, T*); -}; - -struct EventMgr -{ - struct LuaEvent; - - typedef std::set EventSet; - typedef std::map EventMap; - // typedef UNORDERED_MAP ProcessorMap; - Eluna& E; - - EventMap LuaEvents; // LuaEvents[processor] = {LuaEvent, LuaEvent...} - // ProcessorMap Processors; // Processors[guid] = processor - EventProcessor GlobalEvents; - - struct LuaEvent : public BasicEvent - { - LuaEvent(Eluna& _E, EventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls, Object* _obj); - - ~LuaEvent(); - - // Should never execute on dead events - bool Execute(uint64 time, uint32 diff); - - Eluna& E; - EventProcessor* events; // Pointer to events (holds the timed event) - int funcRef; // Lua function reference ID, also used as event ID - uint32 delay; // Delay between event calls - uint32 calls; // Amount of calls to make, 0 for infinite - Object* obj; // Object to push - }; - - EventMgr(Eluna& _E): E(_E) - { - } - - ~EventMgr() - { - RemoveEvents(); - } - - // Should be run on world tick - void Update(uint32 diff) - { - GlobalEvents.Update(diff); - } - - // Updates processor stored for guid || remove from Update() - // Should be run on gameobject tick - /*void Update(uint64 guid, uint32 diff) - { - if (Processors.find(guid) == Processors.end()) - return; - Processors[guid].Update(diff); - }*/ - - // Aborts all lua events - void KillAllEvents(EventProcessor* events) - { - if (!events) - return; - if (LuaEvents.empty()) - return; - EventMap::const_iterator it = LuaEvents.find(events); // Get event set - if (it == LuaEvents.end()) - return; - if (it->second.empty()) - return; - for (EventSet::const_iterator itr = it->second.begin(); itr != it->second.end();) // Loop events - (*(itr++))->to_Abort = true; // Abort event - } - - // Remove all timed events - void RemoveEvents() - { - if (!LuaEvents.empty()) - for (EventMap::const_iterator it = LuaEvents.begin(); it != LuaEvents.end();) // loop processors - KillAllEvents((it++)->first); - LuaEvents.clear(); // remove pointers - // This is handled automatically on delete - // for (ProcessorMap::iterator it = Processors.begin(); it != Processors.end();) - // (it++)->second.KillAllEvents(true); - // Processors.clear(); // remove guid saved processors - GlobalEvents.KillAllEvents(true); - } - - // Remove timed events from processor - void RemoveEvents(EventProcessor* events) - { - if (!events) - return; - KillAllEvents(events); - LuaEvents.erase(events); // remove pointer set - } - - // Remove timed events from guid - // void RemoveEvents(uint64 guid) - //{ - // if (Processors.empty()) - // return; - // if (Processors.find(guid) != Processors.end()) - // LuaEvents.erase(&Processors[guid]); - // // Processors[guid].KillAllEvents(true); // remove events - // Processors.erase(guid); // remove processor - //} - - // Adds a new event to the processor and returns the eventID or 0 (Never negative) - int AddEvent(EventProcessor* events, int funcRef, uint32 delay, uint32 calls, Object* obj = NULL) - { - if (!events || funcRef <= 0) // If funcRef <= 0, function reference failed - return 0; // on fail always return 0. funcRef can be negative. - events->AddEvent(new LuaEvent(E, events, funcRef, delay, calls, obj), events->CalculateTime(delay)); - return funcRef; // return the event ID - } - - // Creates a processor for the guid if needed and adds the event to it - // int AddEvent(uint64 guid, int funcRef, uint32 delay, uint32 calls, Object* obj = NULL) - //{ - // if (!guid) // 0 should be unused - // return 0; - // return AddEvent(&Processors[guid], funcRef, delay, calls, obj); - //} - - // Finds the event that has the ID from events - LuaEvent* GetEvent(EventProcessor* events, int eventId) - { - if (!events || !eventId) - return NULL; - if (LuaEvents.empty()) - return NULL; - EventMap::const_iterator it = LuaEvents.find(events); // Get event set - if (it == LuaEvents.end()) - return NULL; - if (it->second.empty()) - return NULL; - for (EventSet::const_iterator itr = it->second.begin(); itr != it->second.end(); ++itr) // Loop events - if ((*itr) && (*itr)->funcRef == eventId) // Check if the event has our ID - return *itr; // Return the event if found - return NULL; - } - - // Remove the event with the eventId from processor - // Returns true if event is removed - bool RemoveEvent(EventProcessor* events, int eventId) // eventId = funcRef - { - if (!events || !eventId) - return false; - LuaEvent* luaEvent = GetEvent(events, eventId); - if (!luaEvent) - return false; - luaEvent->to_Abort = true; // Set to remove on next call - LuaEvents[events].erase(luaEvent); // Remove pointer - return true; - } - - // Remove event by ID from processor stored for guid - /*bool RemoveEvent(uint64 guid, int eventId) - { - if (Processors.empty()) - return false; - if (!guid || Processors.find(guid) == Processors.end()) - return false; - return RemoveEvent(&Processors[guid], eventId); - }*/ - - // Removes the eventId from all events - void RemoveEvent(int eventId) - { - if (!eventId) - return; - if (LuaEvents.empty()) - return; - for (EventMap::const_iterator it = LuaEvents.begin(); it != LuaEvents.end();) // loop processors - if (RemoveEvent((it++)->first, eventId)) - break; // succesfully remove the event, stop loop. - } -}; - -template -struct EventBind; -template -struct EntryBind; +struct lua_State; +class EventMgr; template class ElunaTemplate; +template +class EventBind; +template +class EntryBind; + +struct LuaScript +{ + std::string fileext; + std::string filename; + std::string filepath; + std::string modulepath; +}; class Eluna { @@ -350,13 +92,6 @@ private: Eluna& operator=(const Eluna&); public: - struct LuaScript - { - std::string fileext; - std::string filename; - std::string filepath; - std::string modulepath; - }; typedef std::list ScriptList; static Eluna* GEluna; @@ -430,100 +165,6 @@ public: return ElunaTemplate::check(L, narg, error); } - static inline uint32 GetCurrTime() - { -#ifndef TRINITY - return WorldTimer::getMSTime(); -#else - return getMSTime(); -#endif - } - - static inline uint32 GetTimeDiff(uint32 oldMSTime) - { -#ifndef TRINITY - return WorldTimer::getMSTimeDiff(oldMSTime, GetCurrTime()); -#else - return GetMSTimeDiffToNow(oldMSTime); -#endif - } - - struct ObjectGUIDCheck - { - ObjectGUIDCheck(ObjectGuid guid): _guid(guid) {} - bool operator()(WorldObject* object) - { - return object->GET_GUID() == _guid; - } - - ObjectGuid _guid; - }; - - // Binary predicate to sort WorldObjects based on the distance to a reference WorldObject - struct ObjectDistanceOrderPred - { - ObjectDistanceOrderPred(WorldObject const* pRefObj, bool ascending = true): m_refObj(pRefObj), m_ascending(ascending) {} - bool operator()(WorldObject const* pLeft, WorldObject const* pRight) const - { - return m_ascending ? m_refObj->GetDistanceOrder(pLeft, pRight) : !m_refObj->GetDistanceOrder(pLeft, pRight); - } - - WorldObject const* m_refObj; - const bool m_ascending; - }; - - // Doesn't get self - struct WorldObjectInRangeCheck - { - WorldObjectInRangeCheck(bool nearest, WorldObject const* obj, float range, - uint16 typeMask = 0, uint32 entry = 0, uint32 hostile = 0): i_nearest(nearest), - i_obj(obj), i_range(range), i_typeMask(typeMask), i_entry(entry), i_hostile(hostile) - { - } - WorldObject const& GetFocusObject() const { return *i_obj; } - bool operator()(WorldObject* u) - { - if (i_typeMask && !u->isType(TypeMask(i_typeMask))) - return false; - if (i_entry && u->GetEntry() != i_entry) - return false; - if (i_obj->GET_GUID() == u->GET_GUID()) - return false; - if (!i_obj->IsWithinDistInMap(u, i_range)) - return false; - if (Unit* unit = u->ToUnit()) - { -#ifdef CMANGOS - if (!unit->isAlive()) - return false; -#else - if (!unit->IsAlive()) - return false; -#endif - if (i_hostile) - { - if (const Unit* obj = i_obj->ToUnit()) - { - if ((i_hostile == 1) != obj->IsHostileTo(unit)) - return false; - } - } - } - if (i_nearest) - i_range = i_obj->GetDistance(u); - return true; - } - - bool i_nearest; - WorldObject const* i_obj; - float i_range; - uint16 i_typeMask; - uint32 i_entry; - uint32 i_hostile; - - WorldObjectInRangeCheck(WorldObjectInRangeCheck const&); - }; - CreatureAI* GetAI(Creature* creature); #ifdef TRINITY GameObjectAI* GetAI(GameObject* gameObject); @@ -699,377 +340,4 @@ template<> Corpse* Eluna::CHECKOBJ(lua_State* L, int narg, bool error); #define sEluna Eluna::GEluna -// #define ELUNA_GUARD() ACE_Guard< ACE_Recursive_Thread_Mutex > ELUNA_GUARD_OBJECT(sEluna->lock); - -struct ElunaBind -{ - Eluna& E; - const char* groupName; - - ElunaBind(const char* bindGroupName, Eluna& _E): E(_E), groupName(bindGroupName) - { - } - - virtual ~ElunaBind() - { - Clear(); - } - - // unregisters all registered functions and clears all registered events from the bindings - virtual void Clear() {}; -}; - -template -struct EventBind : ElunaBind -{ - typedef std::vector ElunaBindingMap; - typedef std::map ElunaEntryMap; - - EventBind(const char* bindGroupName, Eluna& _E): ElunaBind(bindGroupName, _E) - { - } - - // unregisters all registered functions and clears all registered events from the bind std::maps (reset) - void Clear() override - { - for (ElunaEntryMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr) - { - for (ElunaBindingMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it) - luaL_unref(E.L, LUA_REGISTRYINDEX, (*it)); - itr->second.clear(); - } - Bindings.clear(); - } - - void Insert(int eventId, int funcRef) // Inserts a new registered event - { - Bindings[eventId].push_back(funcRef); - } - - // Gets the binding std::map containing all registered events with the function refs for the entry - ElunaBindingMap* GetBindMap(T eventId) - { - if (Bindings.empty()) - return NULL; - ElunaEntryMap::iterator itr = Bindings.find(eventId); - if (itr == Bindings.end()) - return NULL; - - return &itr->second; - } - - // Checks if there are events for ID - bool HasEvents(T eventId) const - { - if (Bindings.empty()) - return false; - if (Bindings.find(eventId) == Bindings.end()) - return false; - return true; - } - - ElunaEntryMap Bindings; // Binding store Bindings[eventId] = {funcRef}; -}; - -template -struct EntryBind : ElunaBind -{ - typedef std::map ElunaBindingMap; - typedef UNORDERED_MAP ElunaEntryMap; - - EntryBind(const char* bindGroupName, Eluna& _E): ElunaBind(bindGroupName, _E) - { - } - - // unregisters all registered functions and clears all registered events from the bindmap - void Clear() override - { - for (ElunaEntryMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr) - { - for (ElunaBindingMap::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it) - luaL_unref(E.L, LUA_REGISTRYINDEX, it->second); - itr->second.clear(); - } - Bindings.clear(); - } - - void Insert(uint32 entryId, int eventId, int funcRef) // Inserts a new registered event - { - if (Bindings[entryId][eventId]) - { - luaL_unref(E.L, LUA_REGISTRYINDEX, funcRef); // free the unused ref - luaL_error(E.L, "A function is already registered for entry (%d) event (%d)", entryId, eventId); - } - else - Bindings[entryId][eventId] = funcRef; - } - - // Gets the function ref of an entry for an event - int GetBind(uint32 entryId, T eventId) const - { - if (Bindings.empty()) - return 0; - ElunaEntryMap::const_iterator itr = Bindings.find(entryId); - if (itr == Bindings.end() || itr->second.empty()) - return 0; - ElunaBindingMap::const_iterator itr2 = itr->second.find(eventId); - if (itr2 == itr->second.end()) - return 0; - return itr2->second; - } - - // Gets the binding std::map containing all registered events with the function refs for the entry - const ElunaBindingMap* GetBindMap(uint32 entryId) const - { - if (Bindings.empty()) - return NULL; - ElunaEntryMap::const_iterator itr = Bindings.find(entryId); - if (itr == Bindings.end()) - return NULL; - - return &itr->second; - } - - // Returns true if the entry has registered binds - bool HasBinds(uint32 entryId) const - { - if (Bindings.empty()) - return false; - return Bindings.find(entryId) != Bindings.end(); - } - - ElunaEntryMap Bindings; // Binding store Bindings[entryId][eventId] = funcRef; -}; - -template -class ElunaTemplate -{ -public: - static const char* tname; - static bool manageMemory; - - static int typeT(lua_State* L) - { - lua_pushstring(L, tname); - return 1; - } - - // name will be used as type name - // If gc is true, lua will handle the memory management for object pushed - // gc should be used if pushing for example WorldPacket, - // that will only be needed on lua side and will not be managed by TC/mangos/ - static void Register(lua_State* L, const char* name, bool gc = false) - { - tname = name; - manageMemory = gc; - - lua_newtable(L); - int methods = lua_gettop(L); - - // store method table in globals so that - // scripts can add functions in Lua - lua_pushvalue(L, methods); - lua_setglobal(L, tname); - - luaL_newmetatable(L, tname); - int metatable = lua_gettop(L); - - // tostring - lua_pushcfunction(L, tostringT); - lua_setfield(L, metatable, "__tostring"); - - // garbage collecting - if (manageMemory) - { - lua_pushcfunction(L, gcT); - lua_setfield(L, metatable, "__gc"); - } - - // make methods accessible through metatable - lua_pushvalue(L, methods); - lua_setfield(L, metatable, "__index"); - - // make new indexes saved to methods - lua_pushvalue(L, methods); - lua_setfield(L, metatable, "__newindex"); - - // special method to get the object type - lua_pushcfunction(L, typeT); - lua_setfield(L, methods, "GetObjectType"); - - // pop methods and metatable - lua_pop(L, 2); - } - - template - static void SetMethods(lua_State* L, ElunaRegister* methodTable) - { - if (!methodTable) - return; - - luaL_getmetatable(L, tname); - if (!lua_istable(L, -1)) - { - lua_remove(L, -1); - ELUNA_LOG_ERROR("%s missing metatable", tname); - return; - } - - lua_getfield(L, -1, "__index"); - lua_remove(L, -2); - if (!lua_istable(L, -1)) - { - lua_remove(L, -1); - ELUNA_LOG_ERROR("%s missing method table from metatable", tname); - return; - } - - for (; methodTable && methodTable->name && methodTable->mfunc; ++methodTable) - { - lua_pushstring(L, methodTable->name); - lua_pushlightuserdata(L, (void*)methodTable); - lua_pushcclosure(L, thunk, 1); - lua_settable(L, -3); - } - - lua_remove(L, -1); - } - - // Remember special case ElunaTemplate::gcT - static int gcT(lua_State* L) - { - if (!manageMemory) - return 0; - - // Get object pointer (and check type, no error) - T** ptrHold = static_cast(luaL_testudata(L, -1, tname)); - if (ptrHold) - delete *ptrHold; - return 0; - } - - static int push(lua_State* L, T const* obj) - { - if (!obj) - { - lua_pushnil(L); - return 1; - } - - if (!manageMemory) - { - lua_rawgeti(L, LUA_REGISTRYINDEX, sEluna->userdata_table); - lua_pushfstring(L, "%p", obj); - lua_gettable(L, -2); - if (!lua_isnoneornil(L, -1) && luaL_checkudata(L, -1, tname)) - { - lua_remove(L, -2); - return 1; - } - lua_remove(L, -1); - // left userdata_table in stack - } - - // Create new userdata - T const** ptrHold = static_cast(lua_newuserdata(L, sizeof(T const*))); - if (!ptrHold) - { - ELUNA_LOG_ERROR("%s could not create new userdata", tname); - lua_pop(L, manageMemory ? 1 : 2); - lua_pushnil(L); - return 1; - } - *ptrHold = obj; - - // Set metatable for it - luaL_getmetatable(L, tname); - if (!lua_istable(L, -1)) - { - ELUNA_LOG_ERROR("%s missing metatable", tname); - lua_pop(L, manageMemory ? 2 : 3); - lua_pushnil(L); - return 1; - } - lua_setmetatable(L, -2); - - if (!manageMemory) - { - lua_pushfstring(L, "%p", obj); - lua_pushvalue(L, -2); - lua_settable(L, -4); - lua_remove(L, -2); - } - return 1; - } - - static T* check(lua_State* L, int narg, bool error = true) - { - T** ptrHold = static_cast(lua_touserdata(L, narg)); - if (!ptrHold) - { - if (error) - { - char buff[256]; - snprintf(buff, 256, "%s expected, got %s", tname, luaL_typename(L, narg)); - luaL_argerror(L, narg, buff); - } - return NULL; - } - - if (!manageMemory) - { - // Check pointer validity - lua_rawgeti(L, LUA_REGISTRYINDEX, sEluna->userdata_table); - lua_pushfstring(L, "%p", *ptrHold); - lua_gettable(L, -2); - lua_remove(L, -2); - bool valid = lua_isuserdata(L, -1); - lua_remove(L, -1); - if (!valid) - { - char buff[256]; - snprintf(buff, 256, "%s expected, got pointer to nonexisting object (%s). This should never happen", tname, luaL_typename(L, narg)); - if (error) - { - luaL_argerror(L, narg, buff); - } - else - { - ELUNA_LOG_ERROR("%s", buff); - } - return NULL; - } - } - return *ptrHold; - } - - static int thunk(lua_State* L) - { - T* obj = Eluna::CHECKOBJ(L, 1); // get self - if (!obj) - return 0; - ElunaRegister* l = static_cast*>(lua_touserdata(L, lua_upvalueindex(1))); - int args = lua_gettop(L); - int expected = l->mfunc(L, obj); - args = lua_gettop(L) - args; - if (args < 0 || args > expected) // Assert instead? - { - ELUNA_LOG_ERROR("[Eluna]: %s returned unexpected amount of arguments %i out of %i. Report to devs", l->name, args, expected); - } - for (; args < expected; ++args) - lua_pushnil(L); - return expected; - } - - static int tostringT(lua_State* L) - { - T* obj = Eluna::CHECKOBJ(L, 1); // get self - if (obj) - lua_pushfstring(L, "%s: (%p)", tname, obj); - else - lua_pushstring(L, "nil"); - return 1; - } -}; - #endif diff --git a/LuaFunctions.cpp b/LuaFunctions.cpp index 2798caa..b64b41d 100644 --- a/LuaFunctions.cpp +++ b/LuaFunctions.cpp @@ -4,10 +4,18 @@ * Please see the included DOCS/LICENSE.md for more information */ +extern "C" +{ +#include "lua.h" +}; + // Eluna -#include "HookMgr.h" #include "LuaEngine.h" -#include "Includes.h" +#include "ElunaEventMgr.h" +#include "ElunaIncludes.h" +#include "ElunaTemplate.h" +#include "ElunaUtilitiy.h" + // Method includes #include "GlobalMethods.h" #include "ObjectMethods.h" diff --git a/UnitMethods.h b/UnitMethods.h index 46e6984..b9c9ebe 100644 --- a/UnitMethods.h +++ b/UnitMethods.h @@ -732,7 +732,7 @@ namespace LuaUnit Trinity::UnitListSearcher searcher(unit, list, checker); unit->VisitNearbyObject(range, searcher); #endif - Eluna::ObjectGUIDCheck guidCheck(unit->GET_GUID()); + ElunaUtil::ObjectGUIDCheck guidCheck(unit->GET_GUID()); list.remove_if(guidCheck); lua_newtable(L); @@ -764,7 +764,7 @@ namespace LuaUnit Trinity::UnitListSearcher searcher(unit, list, checker); unit->VisitNearbyObject(range, searcher); #endif - Eluna::ObjectGUIDCheck guidCheck(unit->GET_GUID()); + ElunaUtil::ObjectGUIDCheck guidCheck(unit->GET_GUID()); list.remove_if(guidCheck); lua_newtable(L); diff --git a/WorldObjectMethods.h b/WorldObjectMethods.h index 67c6c07..b7dad84 100644 --- a/WorldObjectMethods.h +++ b/WorldObjectMethods.h @@ -92,12 +92,12 @@ namespace LuaWorldObject float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); Unit* target = NULL; - Eluna::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_PLAYER); + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_PLAYER); #ifndef TRINITY - MaNGOS::UnitLastSearcher searcher(target, checker); + MaNGOS::UnitLastSearcher searcher(target, checker); Cell::VisitWorldObjects(obj, searcher, range); #else - Trinity::UnitLastSearcher searcher(obj, target, checker); + Trinity::UnitLastSearcher searcher(obj, target, checker); obj->VisitNearbyObject(range, searcher); #endif @@ -111,12 +111,12 @@ namespace LuaWorldObject uint32 entry = Eluna::CHECKVAL(L, 3, 0); GameObject* target = NULL; - Eluna::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_GAMEOBJECT, entry); + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_GAMEOBJECT, entry); #ifndef TRINITY - MaNGOS::GameObjectLastSearcher searcher(target, checker); + MaNGOS::GameObjectLastSearcher searcher(target, checker); Cell::VisitGridObjects(obj, searcher, range); #else - Trinity::GameObjectLastSearcher searcher(obj, target, checker); + Trinity::GameObjectLastSearcher searcher(obj, target, checker); obj->VisitNearbyObject(range, searcher); #endif @@ -130,12 +130,12 @@ namespace LuaWorldObject uint32 entry = Eluna::CHECKVAL(L, 3, 0); Creature* target = NULL; - Eluna::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_UNIT, entry); + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_UNIT, entry); #ifndef TRINITY - MaNGOS::CreatureLastSearcher searcher(target, checker); + MaNGOS::CreatureLastSearcher searcher(target, checker); Cell::VisitGridObjects(obj, searcher, range); #else - Trinity::CreatureLastSearcher searcher(obj, target, checker); + Trinity::CreatureLastSearcher searcher(obj, target, checker); obj->VisitNearbyObject(range, searcher); #endif @@ -148,12 +148,12 @@ namespace LuaWorldObject float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); std::list list; - Eluna::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_PLAYER); + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_PLAYER); #ifndef TRINITY - MaNGOS::PlayerListSearcher searcher(list, checker); + MaNGOS::PlayerListSearcher searcher(list, checker); Cell::VisitWorldObjects(obj, searcher, range); #else - Trinity::PlayerListSearcher searcher(obj, list, checker); + Trinity::PlayerListSearcher searcher(obj, list, checker); obj->VisitNearbyObject(range, searcher); #endif @@ -178,12 +178,12 @@ namespace LuaWorldObject uint32 entry = Eluna::CHECKVAL(L, 3, 0); std::list list; - Eluna::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_UNIT, entry); + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_UNIT, entry); #ifndef TRINITY - MaNGOS::CreatureListSearcher searcher(list, checker); + MaNGOS::CreatureListSearcher searcher(list, checker); Cell::VisitGridObjects(obj, searcher, range); #else - Trinity::CreatureListSearcher searcher(obj, list, checker); + Trinity::CreatureListSearcher searcher(obj, list, checker); obj->VisitNearbyObject(range, searcher); #endif @@ -208,12 +208,12 @@ namespace LuaWorldObject uint32 entry = Eluna::CHECKVAL(L, 3, 0); std::list list; - Eluna::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_GAMEOBJECT, entry); + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_GAMEOBJECT, entry); #ifndef TRINITY - MaNGOS::GameObjectListSearcher searcher(list, checker); + MaNGOS::GameObjectListSearcher searcher(list, checker); Cell::VisitGridObjects(obj, searcher, range); #else - Trinity::GameObjectListSearcher searcher(obj, list, checker); + Trinity::GameObjectListSearcher searcher(obj, list, checker); obj->VisitNearbyObject(range, searcher); #endif @@ -242,15 +242,15 @@ namespace LuaWorldObject float x, y, z; obj->GetPosition(x, y, z); - Eluna::WorldObjectInRangeCheck checker(nearest, obj, range, type, entry, hostile); + ElunaUtil::WorldObjectInRangeCheck checker(nearest, obj, range, type, entry, hostile); if (nearest) { WorldObject* target = NULL; #ifndef TRINITY - MaNGOS::WorldObjectLastSearcher searcher(target, checker); + MaNGOS::WorldObjectLastSearcher searcher(target, checker); Cell::VisitAllObjects(obj, searcher, range); #else - Trinity::WorldObjectLastSearcher searcher(obj, target, checker); + Trinity::WorldObjectLastSearcher searcher(obj, target, checker); obj->VisitNearbyObject(range, searcher); #endif @@ -261,10 +261,10 @@ namespace LuaWorldObject { std::list list; #ifndef TRINITY - MaNGOS::WorldObjectListSearcher searcher(list, checker); + MaNGOS::WorldObjectListSearcher searcher(list, checker); Cell::VisitAllObjects(obj, searcher, range); #else - Trinity::WorldObjectListSearcher searcher(obj, list, checker); + Trinity::WorldObjectListSearcher searcher(obj, list, checker); obj->VisitNearbyObject(range, searcher); #endif