2018-03-02 08:13:45 -03:00
|
|
|
#include "ScriptLoader.h"
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <Logging/Logger.h>
|
2018-06-10 16:34:26 +00:00
|
|
|
#include <Config/ConfigMgr.h>
|
2018-10-25 23:50:18 +02:00
|
|
|
#include <Util/Util.h>
|
2018-03-09 00:06:44 +01:00
|
|
|
#include "ServerZone.h"
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2018-10-25 13:38:06 +11:00
|
|
|
#include <experimental/filesystem>
|
2018-03-02 08:13:45 -03:00
|
|
|
|
2018-03-09 00:06:44 +01:00
|
|
|
#include "Framework.h"
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2018-03-09 10:19:38 +01:00
|
|
|
extern Core::Framework g_fw;
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2018-10-25 13:38:06 +11:00
|
|
|
namespace fs = std::experimental::filesystem;
|
2017-12-14 13:23:59 +11:00
|
|
|
|
2017-12-10 15:31:48 +11:00
|
|
|
const std::string Core::Scripting::ScriptLoader::getModuleExtension()
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
2018-08-29 21:40:59 +02:00
|
|
|
return ".dll";
|
2017-12-10 15:31:48 +11:00
|
|
|
#elif __APPLE__
|
2018-08-29 21:40:59 +02:00
|
|
|
return ".dylib";
|
2017-12-10 15:31:48 +11:00
|
|
|
#else
|
2018-08-29 21:40:59 +02:00
|
|
|
return ".so";
|
2017-12-10 15:31:48 +11:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Core::Scripting::ScriptLoader::unloadModule( ModuleHandle handle )
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
2018-08-29 21:40:59 +02:00
|
|
|
bool success = FreeLibrary( handle ) != 0;
|
2017-12-10 15:31:48 +11:00
|
|
|
#else
|
2018-08-29 21:40:59 +02:00
|
|
|
bool success = dlclose( handle ) == 0;
|
2017-12-10 15:31:48 +11:00
|
|
|
#endif
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pLog = g_fw.get< Logger >();
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !success )
|
|
|
|
{
|
2018-10-25 23:50:18 +02:00
|
|
|
pLog->error( "Failed to unload module " );
|
2018-08-29 21:40:59 +02:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2018-10-25 23:50:18 +02:00
|
|
|
pLog->debug( "Unloaded module" );
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return true;
|
2017-12-10 15:31:48 +11:00
|
|
|
}
|
|
|
|
|
2017-12-12 14:57:13 +11:00
|
|
|
Core::Scripting::ScriptInfo* Core::Scripting::ScriptLoader::loadModule( const std::string& path )
|
2017-12-10 15:31:48 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pLog = g_fw.get< Logger >();
|
|
|
|
auto pConfig = g_fw.get< ConfigMgr >();
|
|
|
|
fs::path f( path );
|
2017-12-12 13:17:43 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( isModuleLoaded( f.stem().string() ) )
|
|
|
|
{
|
|
|
|
pLog->error( "Unable to load module '" + f.stem().string() + "' as it is already loaded" );
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-12-12 13:17:43 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// copy to temp dir
|
2018-10-25 17:48:22 +11:00
|
|
|
fs::path cacheDir( f.parent_path() /= pConfig->getValue< std::string >( "Scripts", "CachePath", "./cache/" ) );
|
2018-08-29 21:40:59 +02:00
|
|
|
fs::create_directories( cacheDir );
|
|
|
|
fs::path dest( cacheDir /= f.filename().string() );
|
2017-12-14 13:23:59 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
try
|
|
|
|
{
|
2018-10-25 13:38:06 +11:00
|
|
|
fs::copy_file( f, dest, fs::copy_options::overwrite_existing );
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2018-10-25 13:38:06 +11:00
|
|
|
catch( const fs::filesystem_error& err )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
pLog->error( "Error copying file to cache: " + err.code().message() );
|
2017-12-14 22:30:06 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
2017-12-14 13:23:59 +11:00
|
|
|
|
|
|
|
|
2017-12-10 15:31:48 +11:00
|
|
|
#ifdef _WIN32
|
2018-10-25 13:38:06 +11:00
|
|
|
ModuleHandle handle = LoadLibrary( dest.c_str() );
|
2017-12-10 15:31:48 +11:00
|
|
|
#else
|
2018-10-25 13:38:06 +11:00
|
|
|
ModuleHandle handle = dlopen( dest.c_str(), RTLD_LAZY );
|
2017-12-10 15:31:48 +11:00
|
|
|
#endif
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !handle )
|
|
|
|
{
|
|
|
|
pLog->error( "Failed to load module from: " + path );
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2018-10-25 23:50:18 +02:00
|
|
|
pLog->debug( "Loaded module '" + f.filename().string() );
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto info = new ScriptInfo;
|
|
|
|
info->handle = handle;
|
|
|
|
info->library_name = f.stem().string();
|
|
|
|
info->cache_path = dest.string();
|
|
|
|
info->library_path = f.string();
|
2017-12-12 01:45:24 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
m_scriptMap.insert( std::make_pair( f.stem().string(), info ) );
|
2017-12-12 01:45:24 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return info;
|
2017-12-10 15:31:48 +11:00
|
|
|
}
|
|
|
|
|
2017-12-27 18:47:51 +11:00
|
|
|
ScriptObject** Core::Scripting::ScriptLoader::getScripts( ModuleHandle handle )
|
2017-12-10 15:31:48 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
using getScripts = ScriptObject** ( * )();
|
|
|
|
auto pLog = g_fw.get< Logger >();
|
2017-12-10 15:31:48 +11:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
2018-08-29 21:40:59 +02:00
|
|
|
getScripts func = reinterpret_cast< getScripts >( GetProcAddress( handle, "getScripts" ) );
|
2017-12-10 15:31:48 +11:00
|
|
|
#else
|
2018-08-29 21:40:59 +02:00
|
|
|
getScripts func = reinterpret_cast< getScripts >( dlsym( handle, "getScripts" ) );
|
2017-12-10 15:31:48 +11:00
|
|
|
#endif
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( func )
|
|
|
|
{
|
|
|
|
auto ptr = func();
|
2017-12-11 21:10:54 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return nullptr;
|
2017-12-10 15:31:48 +11:00
|
|
|
}
|
|
|
|
|
2017-12-12 13:17:43 +11:00
|
|
|
bool Core::Scripting::ScriptLoader::unloadScript( Core::Scripting::ScriptInfo* info )
|
2017-12-10 15:31:48 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return unloadScript( info->handle );
|
2017-12-10 15:31:48 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Core::Scripting::ScriptLoader::unloadScript( ModuleHandle handle )
|
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pLog = g_fw.get< Logger >();
|
|
|
|
for( auto it = m_scriptMap.begin(); it != m_scriptMap.end(); ++it )
|
|
|
|
{
|
|
|
|
if( it->second->handle == handle )
|
|
|
|
{
|
|
|
|
auto info = it->second;
|
|
|
|
|
|
|
|
if( unloadModule( handle ) )
|
2017-12-10 15:31:48 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
m_scriptMap.erase( it );
|
2017-12-12 01:45:24 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// remove cached file
|
|
|
|
fs::remove( info->cache_path );
|
2018-01-04 16:14:14 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
delete info;
|
2017-12-14 13:23:59 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return true;
|
|
|
|
}
|
2017-12-14 13:23:59 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
pLog->error( "failed to unload module: " + info->library_name );
|
2017-12-14 13:23:59 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return false;
|
2017-12-12 01:45:24 +11:00
|
|
|
}
|
|
|
|
|
2017-12-12 13:17:43 +11:00
|
|
|
bool Core::Scripting::ScriptLoader::isModuleLoaded( std::string name )
|
2017-12-12 01:45:24 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
for( auto it = m_scriptMap.begin(); it != m_scriptMap.end(); ++it )
|
|
|
|
{
|
2018-10-25 23:50:18 +02:00
|
|
|
|
|
|
|
if( Util::toLowerCopy( it->second->library_name) == Util::toLowerCopy( name ) )
|
2018-08-29 21:40:59 +02:00
|
|
|
return true;
|
|
|
|
}
|
2017-12-12 13:17:43 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return false;
|
2017-12-12 13:17:43 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
Core::Scripting::ScriptInfo* Core::Scripting::ScriptLoader::getScriptInfo( std::string name )
|
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
for( auto it = m_scriptMap.begin(); it != m_scriptMap.end(); ++it )
|
|
|
|
{
|
|
|
|
if( it->second->library_name == name )
|
|
|
|
{
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2017-12-12 17:29:31 +11:00
|
|
|
}
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
void Core::Scripting::ScriptLoader::findScripts( std::set< Core::Scripting::ScriptInfo* >& scripts,
|
|
|
|
const std::string& search )
|
2017-12-12 17:29:31 +11:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
for( auto it = m_scriptMap.begin(); it != m_scriptMap.end(); ++it )
|
|
|
|
{
|
|
|
|
if( it->second->library_name.find( search ) != std::string::npos )
|
|
|
|
{
|
|
|
|
scripts.insert( it->second );
|
|
|
|
}
|
|
|
|
}
|
2017-12-18 12:36:52 +01:00
|
|
|
}
|