@ -105,6 +105,7 @@ DBG_DECLARE(core,script,DebugCategory::LINFO);
static const std : : string CONFIG_PATH = " dfhack-config/ " ;
static const std : : string CONFIG_DEFAULTS_PATH = " hack/data/dfhack-config-defaults/ " ;
static const std : : string MOD_PATH = " data/installed_mods/ " ;
class MainThread {
public :
@ -440,6 +441,12 @@ bool Core::addScriptPath(std::string path, bool search_before)
return true ;
}
bool Core : : setModScriptPaths ( const std : : vector < std : : string > & mod_script_paths ) {
std : : lock_guard < std : : mutex > lock ( script_path_mutex ) ;
script_paths [ 2 ] = mod_script_paths ;
return true ;
}
bool Core : : removeScriptPath ( std : : string path )
{
std : : lock_guard < std : : mutex > lock ( script_path_mutex ) ;
@ -464,20 +471,21 @@ void Core::getScriptPaths(std::vector<std::string> *dest)
std : : lock_guard < std : : mutex > lock ( script_path_mutex ) ;
dest - > clear ( ) ;
std : : string df_path = this - > p - > getPath ( ) + " / " ;
for ( auto it = script_paths [ 0 ] . begin ( ) ; it ! = script_paths [ 0 ] . end ( ) ; + + it )
dest - > push_back( * it ) ;
for ( auto & path : script_paths [ 0 ] )
dest - > emplace_back( path ) ;
dest - > push_back ( df_path + CONFIG_PATH + " scripts " ) ;
if ( df : : global : : world & & isWorldLoaded ( ) ) {
std : : string save = World : : ReadWorldFolder ( ) ;
if ( save . size ( ) )
dest - > push _back( df_path + " / save/" + save + " /scripts " ) ;
dest - > emplace _back( df_path + " save/" + save + " /scripts " ) ;
}
dest - > push_back ( df_path + " /hack/scripts " ) ;
for ( auto it = script_paths [ 1 ] . begin ( ) ; it ! = script_paths [ 1 ] . end ( ) ; + + it )
dest - > push_back ( * it ) ;
dest - > emplace_back ( df_path + " hack/scripts " ) ;
for ( auto & path : script_paths [ 2 ] )
dest - > emplace_back ( path ) ;
for ( auto & path : script_paths [ 1 ] )
dest - > emplace_back ( path ) ;
}
std : : string Core : : findScript ( std : : string name )
{
std : : vector < std : : string > paths ;
@ -526,6 +534,61 @@ bool loadScriptPaths(color_ostream &out, bool silent = false)
return true ;
}
bool loadModScriptPaths ( color_ostream & out ) {
std : : map < std : : string , bool > files ;
Filesystem : : listdir_recursive ( MOD_PATH , files , 0 ) ;
DEBUG ( script , out ) . print ( " found %zd installed mods \n " , files . size ( ) ) ;
if ( ! files . size ( ) )
return true ;
for ( auto & entry : files ) {
DEBUG ( script , out ) . print ( " %s \n " , entry . first . c_str ( ) ) ;
}
std : : vector < std : : string > mod_paths ;
if ( Core : : getInstance ( ) . isWorldLoaded ( ) ) {
DEBUG ( script , out ) . print ( " active load order: \n " ) ;
for ( auto & path : df : : global : : world - > object_loader . object_load_order_src_dir ) {
DEBUG ( script , out ) . print ( " %s \n " , path - > c_str ( ) ) ;
if ( 0 = = path - > find ( MOD_PATH ) )
mod_paths . emplace_back ( * path ) ;
}
}
std : : vector < std : : string > mod_script_paths ;
for ( auto pathit = mod_paths . rbegin ( ) ; pathit ! = mod_paths . rend ( ) ; + + pathit ) {
std : : string active_path = * pathit + " scripts_modactive " ;
std : : string installed_path = * pathit + " scripts_modinstalled " ;
DEBUG ( script , out ) . print ( " checking active path: %s \n " , pathit - > c_str ( ) ) ;
if ( Filesystem : : isdir ( active_path ) )
mod_script_paths . emplace_back ( active_path ) ;
if ( Filesystem : : isdir ( installed_path ) )
mod_script_paths . emplace_back ( installed_path ) ;
std : : string slashless = * pathit ;
slashless . resize ( slashless . size ( ) - 1 ) ;
if ( 0 = = files . erase ( slashless ) )
WARN ( script , out ) . print ( " script path not found: '%s' \n " , pathit - > c_str ( ) ) ;
}
for ( auto & entry : files ) {
if ( ! entry . second )
continue ;
DEBUG ( script , out ) . print ( " checking inactive path: %s \n " , entry . first . c_str ( ) ) ;
std : : string installed_path = entry . first + " /scripts_modinstalled " ;
if ( Filesystem : : isdir ( installed_path ) )
mod_script_paths . emplace_back ( installed_path ) ;
}
DEBUG ( script , out ) . print ( " final mod script paths: \n " ) ;
for ( auto & path : mod_script_paths )
DEBUG ( script , out ) . print ( " %s \n " , path . c_str ( ) ) ;
Core : : getInstance ( ) . setModScriptPaths ( mod_script_paths ) ;
return true ;
}
static std : : map < std : : string , state_change_event > state_change_event_map ;
static void sc_event_map_init ( ) {
if ( ! state_change_event_map . size ( ) )
@ -2113,14 +2176,22 @@ void Core::onStateChange(color_ostream &out, state_change_event event)
switch ( event )
{
case SC_CORE_INITIALIZED :
{
auto L = Lua : : Core : : State ;
Lua : : StackUnwinder top ( L ) ;
Lua : : CallLuaModuleFunction ( con , L , " helpdb " , " refresh " ) ;
Lua : : CallLuaModuleFunction ( con , L , " script-manager" , " reload " ) ;
}
{
loadModScriptPaths ( out ) ;
auto L = Lua : : Core : : State ;
Lua : : StackUnwinder top ( L ) ;
Lua : : CallLuaModuleFunction ( con , L , " helpdb" , " refresh " ) ;
Lua : : CallLuaModuleFunction ( con , L , " script-manager " , " reload " ) ;
break ;
}
case SC_WORLD_LOADED :
{
loadModScriptPaths ( out ) ;
auto L = Lua : : Core : : State ;
Lua : : StackUnwinder top ( L ) ;
Lua : : CallLuaModuleFunction ( con , L , " script-manager " , " reload " ) ;
// fallthrough
}
case SC_WORLD_UNLOADED :
case SC_MAP_LOADED :
case SC_MAP_UNLOADED :
@ -2185,6 +2256,10 @@ void Core::onStateChange(color_ostream &out, state_change_event event)
if ( event = = SC_WORLD_UNLOADED )
{
Persistence : : Internal : : clear ( ) ;
loadModScriptPaths ( out ) ;
auto L = Lua : : Core : : State ;
Lua : : StackUnwinder top ( L ) ;
Lua : : CallLuaModuleFunction ( con , L , " script-manager " , " reload " ) ;
}
}