Skip to content

Commit

Permalink
Merge pull request #483 from ElunaLuaEngine/autoreload
Browse files Browse the repository at this point in the history
Implement file watcher and auto reload
  • Loading branch information
Foereaper authored Jun 2, 2024
2 parents 9c6f726 + 21aeade commit 7e1febd
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 32 deletions.
1 change: 1 addition & 0 deletions ElunaConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void ElunaConfig::Initialize()
SetConfig(CONFIG_ELUNA_ENABLED, "Eluna.Enabled", true);
SetConfig(CONFIG_ELUNA_COMPATIBILITY_MODE, "Eluna.CompatibilityMode", true);
SetConfig(CONFIG_ELUNA_TRACEBACK, "Eluna.TraceBack", false);
SetConfig(CONFIG_ELUNA_SCRIPT_RELOADER, "Eluna.ScriptReloader", false);

// Load strings
SetConfig(CONFIG_ELUNA_SCRIPT_PATH, "Eluna.ScriptPath", "lua_scripts");
Expand Down
1 change: 1 addition & 0 deletions ElunaConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ enum ElunaConfigBoolValues
CONFIG_ELUNA_ENABLED,
CONFIG_ELUNA_COMPATIBILITY_MODE,
CONFIG_ELUNA_TRACEBACK,
CONFIG_ELUNA_SCRIPT_RELOADER,
CONFIG_ELUNA_BOOL_COUNT
};

Expand Down
76 changes: 76 additions & 0 deletions ElunaLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,28 @@ extern "C" {
#include <lauxlib.h>
}

#ifdef TRINITY
void ElunaUpdateListener::handleFileAction(efsw::WatchID /*watchid*/, std::string const& dir, std::string const& filename, efsw::Action /*action*/, std::string /*oldFilename*/)
{
auto const path = fs::absolute(filename, dir);
if (!path.has_extension())
return;

std::string ext = path.extension().string();
std::transform(ext.begin(), ext.end(), ext.begin(), [](unsigned char c) { return std::tolower(c); });

if (ext != ".lua" && ext != ".ext")
return;

sElunaLoader->ReloadElunaForMap(RELOAD_ALL_STATES);
}
#endif

ElunaLoader::ElunaLoader()
{
#ifdef TRINITY
lua_scriptWatcher = -1;
#endif
}

ElunaLoader* ElunaLoader::instance()
Expand All @@ -48,6 +68,13 @@ ElunaLoader* ElunaLoader::instance()

ElunaLoader::~ElunaLoader()
{
#ifdef TRINITY
if (lua_scriptWatcher >= 0)
{
lua_fileWatcher.removeWatch(lua_scriptWatcher);
lua_scriptWatcher = -1;
}
#endif
}

void ElunaLoader::LoadScripts()
Expand Down Expand Up @@ -263,6 +290,25 @@ void ElunaLoader::ProcessScript(lua_State* L, std::string filename, const std::s
ELUNA_LOG_DEBUG("[Eluna]: ProcessScript processed `%s` successfully", fullpath.c_str());
}

#ifdef TRINITY
void ElunaLoader::InitializeFileWatcher()
{
lua_scriptWatcher = lua_fileWatcher.addWatch(lua_folderpath, &elunaUpdateListener, true);
if (lua_scriptWatcher >= 0)
{
ELUNA_LOG_INFO("[Eluna]: Script reloader is listening on `%s`.",
lua_folderpath.c_str());
}
else
{
ELUNA_LOG_INFO("[Eluna]: Failed to initialize the script reloader on `%s`.",
lua_folderpath.c_str());
}

lua_fileWatcher.watch();
}
#endif

static bool ScriptPathComparator(const LuaScript& first, const LuaScript& second)
{
return first.filepath < second.filepath;
Expand All @@ -283,3 +329,33 @@ bool ElunaLoader::ShouldMapLoadEluna(uint32 id)

return (std::find(requiredMaps.begin(), requiredMaps.end(), id) != requiredMaps.end());
}

void ElunaLoader::ReloadElunaForMap(int mapId)
{
// If a mapid is provided but does not match any map or reserved id then only script storage is loaded
LoadScripts();

if (mapId != RELOAD_CACHE_ONLY)
{
if (mapId == RELOAD_GLOBAL_STATE || mapId == RELOAD_ALL_STATES)
#ifdef TRINITY
if (sWorld->GetEluna())
sWorld->GetEluna()->ReloadEluna();
#else
if (sWorld.GetEluna())
sWorld.GetEluna()->ReloadEluna();
#endif

#ifdef TRINITY
sMapMgr->DoForAllMaps([&](Map* map)
#else
sMapMgr.DoForAllMaps([&](Map* map)
#endif
{
if (mapId == RELOAD_ALL_STATES || mapId == static_cast<int>(map->GetId()))
if (map->GetEluna())
map->GetEluna()->ReloadEluna();
}
);
}
}
34 changes: 34 additions & 0 deletions ElunaLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,22 @@

#include "ElunaUtility.h"

#ifdef TRINITY
#include <efsw/efsw.hpp>
#endif

extern "C"
{
#include "lua.h"
};

enum ElunaReloadActions
{
RELOAD_CACHE_ONLY = -3,
RELOAD_ALL_STATES = -2,
RELOAD_GLOBAL_STATE = -1
};

struct LuaScript;

class ElunaLoader
Expand All @@ -37,6 +48,7 @@ class ElunaLoader
bool ShouldMapLoadEluna(uint32 mapId);
bool CompileScript(lua_State* L, LuaScript& script);
static int LoadBytecodeChunk(lua_State* L, uint8* bytes, size_t len, BytecodeBuffer* buffer);
void ReloadElunaForMap(int mapId);

// Lua script folder path
std::string lua_folderpath;
Expand All @@ -49,8 +61,30 @@ class ElunaLoader
ScriptList lua_extensions;
std::vector<LuaScript> combined_scripts;
std::list<uint32> requiredMaps;

#ifdef TRINITY
// efsw file watcher
void InitializeFileWatcher();
efsw::FileWatcher lua_fileWatcher;
efsw::WatchID lua_scriptWatcher;
#endif
};

#ifdef TRINITY
/// File watcher responsible for watching lua scripts
class ElunaUpdateListener : public efsw::FileWatchListener
{
public:
ElunaUpdateListener() { }
virtual ~ElunaUpdateListener() { }

void handleFileAction(efsw::WatchID /*watchid*/, std::string const& dir,
std::string const& filename, efsw::Action /*action*/, std::string oldFilename = "") final override;
};

static ElunaUpdateListener elunaUpdateListener;
#endif

#define sElunaLoader ElunaLoader::instance()

#endif
34 changes: 2 additions & 32 deletions hooks/PlayerHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,43 +80,13 @@ bool Eluna::OnCommand(Player* player, const char* text)
const std::string reload_command = "reload eluna";
if (reload.find(reload_command) == 0)
{
const int mapid_reload_cache_only = -3;
const int mapid_reload_all = -2; // reserved for reloading all states (default if no args)
const int mapid_reload_global = -1; // reserved for reloading global state
// otherwise reload the state of the specific mapid
// If a mapid is provided but does not match any map or reserved id then only script storage is loaded

int mapId = mapid_reload_all;
int mapId = RELOAD_ALL_STATES;
std::string args = reload.substr(reload_command.length());
if (!args.empty())
mapId = strtol(args.c_str(), nullptr, 10);

sElunaLoader->LoadScripts();
if (mapid_reload_cache_only != mapId)
{
if (mapId == mapid_reload_global || mapId == mapid_reload_all)
#ifdef TRINITY
if (sWorld->GetEluna())
sWorld->GetEluna()->ReloadEluna();
#else
if (sWorld.GetEluna())
sWorld.GetEluna()->ReloadEluna();
#endif
sElunaLoader->ReloadElunaForMap(mapId);

#ifdef TRINITY
sMapMgr->DoForAllMaps([&](Map* map)
#else
sMapMgr.DoForAllMaps([&](Map* map)
#endif
{
if (mapId == mapid_reload_all || mapId == static_cast<int>(map->GetId()))
{
if (map->GetEluna())
map->GetEluna()->ReloadEluna();
}
}
);
}
return false;
}
}
Expand Down

0 comments on commit 7e1febd

Please sign in to comment.