From a3359062e563ae0b571618d9f87038d6c1da0f84 Mon Sep 17 00:00:00 2001 From: Rochet2 Date: Wed, 16 Jul 2014 16:12:07 +0300 Subject: [PATCH] Eluna/Core Refactor code making LuaEngine.h lighter and splitting entities to their own files. Fixed reload crash for timed events --- CreatureMethods.h | 2 +- ElunaBinding.h | 163 +++++++++ ElunaEventMgr.cpp | 151 ++++++++ ElunaEventMgr.h | 82 +++++ ElunaIncludes.h | 124 +++++++ ElunaTemplate.h | 257 ++++++++++++++ ElunaUtilitiy.cpp | 87 +++++ ElunaUtilitiy.h | 89 +++++ HookMgr.cpp | 19 +- Includes.h | 50 --- LuaEngine.cpp | 60 +--- LuaEngine.h | 802 ++----------------------------------------- LuaFunctions.cpp | 12 +- UnitMethods.h | 4 +- WorldObjectMethods.h | 46 +-- 15 files changed, 1060 insertions(+), 888 deletions(-) create mode 100644 ElunaBinding.h create mode 100644 ElunaEventMgr.cpp create mode 100644 ElunaEventMgr.h create mode 100644 ElunaIncludes.h create mode 100644 ElunaTemplate.h create mode 100644 ElunaUtilitiy.cpp create mode 100644 ElunaUtilitiy.h delete mode 100644 Includes.h 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