1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-24 21:57:44 +00:00

Merge pull request #202 from GokuWeedLord/feature/nativescripting

automagically reload rebuilt scripts
This commit is contained in:
Mordred 2017-12-14 23:54:48 +01:00 committed by GitHub
commit e574d4035d
12 changed files with 134 additions and 31 deletions

View file

@ -32,6 +32,7 @@ before_install:
- sudo add-apt-repository -y ppa:rexut/recoil
- sudo apt-get update
- sudo apt-get install -y libboost1.63-dev libboost1.63-all-dev
- sudo apt-get install -y libmysqlclient-dev
# Build steps
script:

View file

@ -8,15 +8,16 @@
<DataPath>H:\\SteamLibrary\\steamapps\\common\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv</DataPath>
<Scripts>
<!-- where compiled scripts are placed -->
<Path>./compiledscripts/</Path>
<CachePath>./cache/</CachePath>
<!-- where compiled scripts are placed -->
<Path>./compiledscripts/</Path>
<CachePath>./cache/</CachePath>
<HotSwap>
<Enabled>1</Enabled>
<BuildDir>../cmake-build-debug/</BuildDir>
<BuildCmd>cmake --build %1% --target %2%</BuildCmd>
</HotSwap>
<HotSwap>
<Enabled>1</Enabled>
<ScriptsDir>../scripts/native/</ScriptsDir>
<BuildDir>../cmake-build-debug/</BuildDir>
<BuildCmd>cmake --build %1% --target %2%</BuildCmd>
</HotSwap>
</Scripts>
<!-- Path of Chai script files -->
@ -28,13 +29,13 @@
<Username>root</Username>
<Pass></Pass>
<Database>sapphire</Database>
<SyncThreads>2</SyncThreads>
<AsyncThreads>2</AsyncThreads>
<SyncThreads>2</SyncThreads>
<AsyncThreads>2</AsyncThreads>
</Mysql>
</General>
<Parameters>
<!-- Messages players see upon logging in - These *must* be smaller than 307 characters -->
<!-- Messages players see upon logging in - These *must* be smaller than 307 characters -->
<MotDArray>
<MotD>&lt;&lt;&lt;Welcome to Sapphire&gt;&gt;&gt;</MotD>
<MotD>This is a very good server</MotD>

View file

@ -5,6 +5,7 @@
#include <Forwards.h>
#include <Actor/Actor.h>
#include <Actor/Player.h>
#include <Event/EventHelper.h>
#endif //SAPPHIRE_SCRIPTOBJECT_H

View file

@ -63,6 +63,8 @@ public:
Scene00030( player );
}
};
player.eventPlay( getId(), 40, 1, 2, 1, callback );
}
///////////////////////////////

@ -1 +1 @@
Subproject commit 8a26ae78e37701a9b66e7200f1e0ad3387da17c3
Subproject commit f4d3c5b38d13a15efc42686c9bac768c2be28be1

View file

@ -589,15 +589,15 @@ void Core::DebugCommandHandler::script( char* data, Entity::Player &player, boos
}
}
else if( subCommand == "reload" || subCommand == "rl" )
else if( subCommand == "queuereload" || subCommand == "qrl" )
{
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 + "'" );
{
g_scriptMgr.getNativeScriptHandler().queueScriptReload( params );
player.sendDebug( "Queued script reload for script: " + params );
}
}
else if( subCommand == "build" || subCommand == "b" )
{

View file

@ -137,19 +137,41 @@ namespace Core {
return m_loader.unloadScript( info );
}
bool NativeScriptManager::reloadScript( const std::string& name )
void NativeScriptManager::queueScriptReload( const std::string &name )
{
auto info = m_loader.getScriptInfo( name );
if( !info )
return false;
return;
// backup actual lib path
std::string libPath( info->library_path );
if( !unloadScript( info ) )
return false;
return;
return loadScript( libPath );
m_scriptLoadQueue.push( libPath );
}
void NativeScriptManager::processLoadQueue()
{
std::vector< std::string > deferredLoads;
while( !m_scriptLoadQueue.empty() )
{
auto item = m_scriptLoadQueue.front();
// if it fails, we defer the loading to the next tick
if( !loadScript( item ) )
deferredLoads.push_back( item );
m_scriptLoadQueue.pop();
}
if( !deferredLoads.empty() )
{
for( auto& item : deferredLoads )
m_scriptLoadQueue.push( item );
}
}
void NativeScriptManager::findScripts( std::set< Core::Scripting::ScriptInfo* >& scripts, const std::string& search )
@ -157,6 +179,11 @@ namespace Core {
return m_loader.findScripts( scripts, search );
}
bool NativeScriptManager::isModuleLoaded( const std::string &name )
{
return m_loader.isModuleLoaded( name );
}
boost::shared_ptr< NativeScriptManager > createNativeScriptMgr()

View file

@ -3,6 +3,7 @@
#include <unordered_map>
#include <set>
#include <queue>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
@ -26,6 +27,8 @@ namespace Scripting {
ScriptLoader m_loader;
std::queue< std::string > m_scriptLoadQueue;
bool unloadScript( ScriptInfo* info );
public:
@ -39,10 +42,13 @@ namespace Scripting {
bool loadScript( const std::string& path );
bool unloadScript( const std::string& name );
bool reloadScript( const std::string& name );
void queueScriptReload( const std::string& name );
void findScripts( std::set< Core::Scripting::ScriptInfo* >& scripts, const std::string& search );
void processLoadQueue();
const std::string getModuleExtension();
bool isModuleLoaded( const std::string& name );
template< typename key, typename val >
bool removeValueFromMap( ScriptObject* ptr, std::unordered_map< key, val >& map )

View file

@ -62,12 +62,17 @@ Core::Scripting::ScriptInfo* Core::Scripting::ScriptLoader::loadModule( const st
fs::create_directories( cacheDir );
fs::path dest( cacheDir /= f.filename().string() );
if ( fs::exists( dest ) )
try
{
fs::remove( dest );
fs::copy_file( f, dest, fs::copy_option::overwrite_if_exists );
}
catch( const boost::filesystem::filesystem_error& err )
{
g_log.error( "Error copying file to cache: " + err.code().message() );
return nullptr;
}
fs::copy_file( f, dest );
#ifdef _WIN32
ModuleHandle handle = LoadLibrary( dest.string().c_str() );
@ -82,7 +87,7 @@ Core::Scripting::ScriptInfo* Core::Scripting::ScriptLoader::loadModule( const st
return nullptr;
}
g_log.info( "Loaded module '" + f.filename().string() + "' @ 0x" + boost::str( boost::format( "%|08X|" ) % handle ) );
g_log.debug( "Loaded module '" + f.filename().string() + "' @ 0x" + boost::str( boost::format( "%|08X|" ) % handle ) );
auto info = new ScriptInfo;
info->handle = handle;

View file

@ -21,18 +21,28 @@
#include <Server_Common/Config/XMLConfig.h>
// enable the ambiguity fix for every platform to avoid #define nonsense
#define WIN_AMBIGUITY_FIX
#include <libraries/external/watchdog/Watchdog.h>
extern Core::Logger g_log;
extern Core::Data::ExdData g_exdData;
extern Core::ServerZone g_serverZone;
Core::Scripting::ScriptManager::ScriptManager()
Core::Scripting::ScriptManager::ScriptManager() :
m_firstScriptChangeNotificiation( false )
{
m_nativeScriptManager = createNativeScriptMgr();
}
Core::Scripting::ScriptManager::~ScriptManager()
{
Watchdog::unwatchAll();
}
void Core::Scripting::ScriptManager::update()
{
m_nativeScriptManager->processLoadQueue();
}
bool Core::Scripting::ScriptManager::init()
@ -42,24 +52,66 @@ bool Core::Scripting::ScriptManager::init()
loadDir( g_serverZone.getConfig()->getValue< std::string >( "Settings.General.Scripts.Path", "./compiledscripts/" ),
files, m_nativeScriptManager->getModuleExtension() );
uint32_t scriptsFound = 0;
uint32_t scriptsLoaded = 0;
for( auto itr = files.begin(); itr != files.end(); ++itr )
{
auto& path = *itr;
m_nativeScriptManager->loadScript( path );
scriptsFound++;
if( m_nativeScriptManager->loadScript( path ) )
scriptsLoaded++;
}
g_log.info( "ScriptManager: Loaded " + std::to_string( scriptsLoaded ) + "/" + std::to_string( scriptsFound ) + " scripts successfully" );
watchDirectories();
return true;
}
void Core::Scripting::ScriptManager::loadDir( std::string dirname, std::set<std::string>& files, std::string ext )
void Core::Scripting::ScriptManager::watchDirectories()
{
Watchdog::watchMany( g_serverZone.getConfig()->getValue< std::string >( "Settings.General.Scripts.Path", "./compiledscripts/" ) + "*" + m_nativeScriptManager->getModuleExtension(),
[ this ]( const std::vector< ci::fs::path >& paths )
{
if( !m_firstScriptChangeNotificiation )
{
// for whatever reason, the first time this runs, it detects every file as changed
// so we're always going to ignore the first notification
m_firstScriptChangeNotificiation = true;
return;
}
for( auto path : paths )
{
if( m_nativeScriptManager->isModuleLoaded( path.stem().string() ) )
{
g_log.debug( "Reloading changed script: " + path.stem().string() );
m_nativeScriptManager->queueScriptReload( path.stem( ).string( ));
}
else
{
g_log.debug( "Loading new script: " + path.stem().string() );
m_nativeScriptManager->loadScript( path.string() );
}
}
});
}
void Core::Scripting::ScriptManager::loadDir( const std::string& dirname, std::set<std::string> &files, const std::string& ext )
{
g_log.info( "ScriptEngine: loading scripts from " + dirname );
boost::filesystem::path targetDir( dirname );
boost::filesystem::recursive_directory_iterator iter( targetDir ), eod;
boost::filesystem::directory_iterator iter( targetDir );
boost::filesystem::directory_iterator eod;
BOOST_FOREACH( boost::filesystem::path const& i, make_pair( iter, eod ) )
{

View file

@ -22,6 +22,8 @@ namespace Core
std::function< std::string( Entity::Player& ) > m_onFirstEnterWorld;
// auto fn = m_pChaiHandler->eval< std::function<const std::string( Entity::Player ) > >( "onFirstEnterWorld" );
bool m_firstScriptChangeNotificiation;
public:
ScriptManager();
~ScriptManager();
@ -29,6 +31,10 @@ namespace Core
bool init();
void reload();
void update();
void watchDirectories();
void onPlayerFirstEnterWorld( Entity::Player& player );
static bool registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId, uint32_t bnpcNameId, uint32_t modelId, std::string aiName );
@ -54,7 +60,7 @@ namespace Core
bool onEventHandlerTradeReturn( Entity::Player& player, uint32_t eventId, uint16_t subEvent, uint16_t param, uint32_t catalogId );
void loadDir( std::string dirname, std::set<std::string>& files, std::string ext );
void loadDir( const std::string& dirname, std::set<std::string> &files, const std::string& ext );
NativeScriptManager& getNativeScriptHandler();
};

View file

@ -260,6 +260,8 @@ void Core::ServerZone::mainLoop()
g_zoneMgr.updateZones();
g_scriptMgr.update();
auto currTime = static_cast< uint32_t >( time( nullptr ) );
lock_guard< std::mutex > lock( this->m_sessionMutex );