diff --git a/bin/config/settings_zone.xml b/bin/config/settings_zone.xml index 4cbb49ad..a0d56a0a 100644 --- a/bin/config/settings_zone.xml +++ b/bin/config/settings_zone.xml @@ -10,11 +10,12 @@ ./compiledscripts/ + ./cache/ 1 ../cmake-build-debug/ - make %1% + cmake --build %1% --target %2% diff --git a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp index 79352c6f..9f6a39dd 100644 --- a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp @@ -560,7 +560,7 @@ void Core::DebugCommandHandler::script( char* data, Entity::Player &player, boos std::set< Core::Scripting::ScriptInfo* > scripts; g_scriptMgr.getNativeScriptHandler().findScripts( scripts, params ); - if( scripts.size() > 0 ) + if( !scripts.empty() ) { player.sendDebug( "Found " + std::to_string( scripts.size() ) + " scripts" ); @@ -589,6 +589,16 @@ void Core::DebugCommandHandler::script( char* data, Entity::Player &player, boos } } + else if( subCommand == "reload" || subCommand == "rl" ) + { + if( subCommand == params ) + player.sendDebug( "Command failed: requires name of script to reload" ); + else + if( g_scriptMgr.getNativeScriptHandler().reloadScript( params ) ) + player.sendDebug( "Reloaded '" + params + "' successfully" ); + else + player.sendDebug( "Failed to reload '" + params + "'" ); + } else if( subCommand == "build" || subCommand == "b" ) { if( subCommand == params ) diff --git a/src/servers/Server_Zone/Script/NativeScriptManager.cpp b/src/servers/Server_Zone/Script/NativeScriptManager.cpp index be7a29a7..2441816e 100644 --- a/src/servers/Server_Zone/Script/NativeScriptManager.cpp +++ b/src/servers/Server_Zone/Script/NativeScriptManager.cpp @@ -105,6 +105,11 @@ namespace Core { if( !info ) return false; + return unloadScript( info ); + } + + bool NativeScriptManager::unloadScript( ScriptInfo* info ) + { auto ptr = info->script; switch( info->type ) @@ -132,6 +137,21 @@ namespace Core { return m_loader.unloadScript( info ); } + bool NativeScriptManager::reloadScript( const std::string& name ) + { + auto info = m_loader.getScriptInfo( name ); + if( !info ) + return false; + + // backup actual lib path + std::string libPath( info->library_path ); + + if( !unloadScript( info ) ) + return false; + + return loadScript( libPath ); + } + void NativeScriptManager::findScripts( std::set< Core::Scripting::ScriptInfo* >& scripts, const std::string& search ) { return m_loader.findScripts( scripts, search ); diff --git a/src/servers/Server_Zone/Script/NativeScriptManager.h b/src/servers/Server_Zone/Script/NativeScriptManager.h index cdfb436c..42c4a4ed 100644 --- a/src/servers/Server_Zone/Script/NativeScriptManager.h +++ b/src/servers/Server_Zone/Script/NativeScriptManager.h @@ -26,6 +26,8 @@ namespace Scripting { ScriptLoader m_loader; + bool unloadScript( ScriptInfo* info ); + public: NativeScriptManager( ); @@ -37,6 +39,7 @@ namespace Scripting { bool loadScript( const std::string& path ); bool unloadScript( const std::string& name ); + bool reloadScript( const std::string& name ); void findScripts( std::set< Core::Scripting::ScriptInfo* >& scripts, const std::string& search ); const std::string getModuleExtension(); diff --git a/src/servers/Server_Zone/Script/ScriptInfo.h b/src/servers/Server_Zone/Script/ScriptInfo.h index a81f7570..19945723 100644 --- a/src/servers/Server_Zone/Script/ScriptInfo.h +++ b/src/servers/Server_Zone/Script/ScriptInfo.h @@ -19,6 +19,7 @@ namespace Scripting { ScriptInfo() = default; std::string library_name; + std::string cache_path; std::string library_path; std::string script_name; diff --git a/src/servers/Server_Zone/Script/ScriptLoader.cpp b/src/servers/Server_Zone/Script/ScriptLoader.cpp index b6dff3f6..2a6d82b9 100644 --- a/src/servers/Server_Zone/Script/ScriptLoader.cpp +++ b/src/servers/Server_Zone/Script/ScriptLoader.cpp @@ -11,6 +11,8 @@ extern Core::Logger g_log; extern Core::ServerZone g_serverZone; +namespace fs = boost::filesystem; + Core::Scripting::ScriptLoader::ScriptLoader() {} @@ -55,10 +57,22 @@ Core::Scripting::ScriptInfo* Core::Scripting::ScriptLoader::loadModule( const st return nullptr; } + // copy to temp dir + fs::path cacheDir( f.parent_path() /= g_serverZone.getConfig()->getValue< std::string >( "Settings.General.Scripts.CachePath", "./cache/" ) ); + fs::create_directories( cacheDir ); + fs::path dest( cacheDir /= f.filename().string() ); + + if ( fs::exists( dest ) ) + { + fs::remove( dest ); + } + + fs::copy_file( f, dest ); + #ifdef _WIN32 - ModuleHandle handle = LoadLibrary( path.c_str() ); + ModuleHandle handle = LoadLibrary( dest.string().c_str() ); #else - ModuleHandle handle = dlopen( path.c_str(), RTLD_LAZY ); + ModuleHandle handle = dlopen( dest.string().c_str(), RTLD_LAZY ); #endif if( !handle ) @@ -68,12 +82,13 @@ Core::Scripting::ScriptInfo* Core::Scripting::ScriptLoader::loadModule( const st return nullptr; } - g_log.info( "Loaded module from '" + path + "' @ 0x" + boost::str( boost::format( "%|08X|" ) % handle ) ); + g_log.info( "Loaded module '" + f.filename().string() + "' @ 0x" + boost::str( boost::format( "%|08X|" ) % handle ) ); auto info = new ScriptInfo; info->handle = handle; info->library_name = f.stem().string(); - info->library_path = path; + info->cache_path = dest.string(); + info->library_path = f.string(); m_scriptMap.insert( std::make_pair( f.stem().string(), info ) ); @@ -114,10 +129,22 @@ bool Core::Scripting::ScriptLoader::unloadScript( ModuleHandle handle ) { if( it->second->handle == handle ) { - delete it->second; + auto info = it->second; m_scriptMap.erase( it ); - return unloadModule( handle ); + if( unloadModule( handle ) ) + { + // remove cached file + fs::remove( info->cache_path ); + + delete info; + + return true; + } + + g_log.error( "failed to unload module: " + info->library_name ); + + return false; } } diff --git a/src/servers/Server_Zone/Script/ScriptManager.cpp b/src/servers/Server_Zone/Script/ScriptManager.cpp index 0ee843e6..2680618e 100644 --- a/src/servers/Server_Zone/Script/ScriptManager.cpp +++ b/src/servers/Server_Zone/Script/ScriptManager.cpp @@ -90,13 +90,6 @@ bool Core::Scripting::ScriptManager::registerBnpcTemplate( std::string templateN return g_serverZone.registerBnpcTemplate( templateName, bnpcBaseId, bnpcNameId, modelId, aiName ); } -void Core::Scripting::ScriptManager::reload() -{ -// auto handler = create_chaiscript(); -// m_pChaiHandler.swap( handler ); -// init(); -} - bool Core::Scripting::ScriptManager::onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId ) { std::string eventName = "onTalk";