diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index b0f0739be9..433a10f67a 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -502,14 +502,14 @@ void game_load_init() void game_load_scripts() { #ifdef ENABLE_SCRIPTING - GetContext()->GetScriptEngine().LoadPlugins(); + GetContext()->GetScriptEngine().LoadTransientPlugins(); #endif } void game_unload_scripts() { #ifdef ENABLE_SCRIPTING - GetContext()->GetScriptEngine().UnloadPlugins(); + GetContext()->GetScriptEngine().UnloadTransientPlugins(); #endif } diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index 6a039c66c9..a49ab36964 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -436,10 +436,10 @@ void ScriptEngine::Initialise() dukglue_register_global(ctx, std::make_shared(), "scenario"); _initialised = true; - _pluginsLoaded = false; - _pluginsStarted = false; + _transientPluginsEnabled = false; + _transientPluginsStarted = false; - InitSharedStorage(); + LoadSharedStorage(); ClearParkStorage(); } @@ -477,7 +477,7 @@ void ScriptEngine::RefreshPlugins() } // Turn on hot reload if not already enabled - if (!_hotReloading && gConfigPlugin.enable_hot_reloading && network_get_mode() == NETWORK_MODE_NONE) + if (!_hotReloadingInitialised && gConfigPlugin.enable_hot_reloading && network_get_mode() == NETWORK_MODE_NONE) { SetupHotReloading(); } @@ -493,8 +493,8 @@ std::vector ScriptEngine::GetPluginFiles() const auto base = _env.GetDirectoryPath(DIRBASE::USER, DIRID::PLUGIN); if (Path::DirectoryExists(base)) { - auto pattern = Path::Combine(base, "*.js"); - auto scanner = std::unique_ptr(Path::ScanDirectory(pattern, true)); + auto pattern = Path::Combine(base, u8"*.js"); + auto scanner = Path::ScanDirectory(pattern, true); while (scanner->Next()) { auto path = std::string(scanner->GetPath()); @@ -558,6 +558,8 @@ void ScriptEngine::RegisterPlugin(std::string_view path) void ScriptEngine::StartIntransientPlugins() { + LoadSharedStorage(); + for (auto& plugin : _plugins) { if (!plugin->HasStarted() && !plugin->IsTransient()) @@ -586,38 +588,9 @@ void ScriptEngine::StopUnloadRegisterAllPlugins() } } -void ScriptEngine::LoadPlugins() +void ScriptEngine::LoadTransientPlugins() { - if (!_initialised) - { - Initialise(); - } - if (_pluginsLoaded) - { - UnloadPlugins(); - } - - auto base = _env.GetDirectoryPath(DIRBASE::USER, DIRID::PLUGIN); - if (Path::DirectoryExists(base)) - { - auto pattern = Path::Combine(base, u8"*.js"); - auto scanner = Path::ScanDirectory(pattern, true); - while (scanner->Next()) - { - auto path = std::string(scanner->GetPath()); - if (ShouldLoadScript(path)) - { - LoadPlugin(path); - } - } - - if (gConfigPlugin.enable_hot_reloading && network_get_mode() == NETWORK_MODE_NONE) - { - SetupHotReloading(); - } - } - _pluginsLoaded = true; - _pluginsStarted = false; + _transientPluginsEnabled = true; } void ScriptEngine::LoadPlugin(const std::string& path) @@ -705,7 +678,7 @@ void ScriptEngine::SetupHotReloading() std::lock_guard guard(_changedPluginFilesMutex); _changedPluginFiles.emplace(path); }; - _hotReloading = true; + _hotReloadingInitialised = true; } } catch (const std::exception& e) @@ -714,6 +687,19 @@ void ScriptEngine::SetupHotReloading() } } +void ScriptEngine::DoAutoReloadPluginCheck() +{ + if (_hotReloadingInitialised) + { + auto tick = Platform::GetTicks(); + if (tick - _lastHotReloadCheckTick > 1000) + { + AutoReloadPlugins(); + _lastHotReloadCheckTick = tick; + } + } +} + void ScriptEngine::AutoReloadPlugins() { if (_changedPluginFiles.size() > 0) @@ -746,39 +732,54 @@ void ScriptEngine::AutoReloadPlugins() } } -void ScriptEngine::UnloadPlugins() +void ScriptEngine::UnloadTransientPlugins() { - StopPlugins(); + // Stop them all first for (auto& plugin : _plugins) { - LogPluginInfo(plugin, "Unloaded"); - } - _plugins.clear(); - _pluginsLoaded = false; - _pluginsStarted = false; -} - -void ScriptEngine::StartPlugins() -{ - LoadSharedStorage(); - - for (auto& plugin : _plugins) - { - if (!plugin->HasStarted() && ShouldStartPlugin(plugin)) + if (plugin->IsTransient()) { - ScriptExecutionInfo::PluginScope scope(_execInfo, plugin, false); - try + if (plugin->HasStarted()) { - LogPluginInfo(plugin, "Started"); - plugin->Start(); - } - catch (const std::exception& e) - { - _console.WriteLineError(e.what()); + StopPlugin(plugin); + LogPluginInfo(plugin, "Stopped"); } } } - _pluginsStarted = true; + + // Now unload them + for (auto& plugin : _plugins) + { + UnloadPlugin(plugin); + } + + _transientPluginsEnabled = false; + _transientPluginsStarted = false; +} + +void ScriptEngine::StartTransientPlugins() +{ + LoadSharedStorage(); + + // Load transient plugins + for (auto& plugin : _plugins) + { + if (plugin->IsTransient() && !plugin->IsLoaded() && ShouldStartPlugin(plugin)) + { + LoadPlugin(plugin); + } + } + + // Start transient plugins + for (auto& plugin : _plugins) + { + if (plugin->IsTransient() && plugin->IsLoaded() && !plugin->HasStarted()) + { + StartPlugin(plugin); + } + } + + _transientPluginsStarted = true; } bool ScriptEngine::ShouldStartPlugin(const std::shared_ptr& plugin) @@ -797,19 +798,6 @@ bool ScriptEngine::ShouldStartPlugin(const std::shared_ptr& plugin) return true; } -void ScriptEngine::StopPlugins() -{ - for (auto& plugin : _plugins) - { - if (plugin->HasStarted()) - { - StopPlugin(plugin); - LogPluginInfo(plugin, "Stopped"); - } - } - _pluginsStarted = false; -} - void ScriptEngine::Tick() { PROFILED_FUNCTION(); @@ -820,26 +808,15 @@ void ScriptEngine::Tick() RefreshPlugins(); } - if (_pluginsLoaded) + if (_transientPluginsEnabled && !_transientPluginsStarted) { - if (!_pluginsStarted) - { - StartPlugins(); - } - else - { - auto tick = Platform::GetTicks(); - if (tick - _lastHotReloadCheckTick > 1000) - { - AutoReloadPlugins(); - _lastHotReloadCheckTick = tick; - } - } + StartTransientPlugins(); } UpdateIntervals(); UpdateSockets(); ProcessREPL(); + DoAutoReloadPluginCheck(); } void ScriptEngine::ProcessREPL() diff --git a/src/openrct2/scripting/ScriptEngine.h b/src/openrct2/scripting/ScriptEngine.h index 10d3253f74..17020fc7cc 100644 --- a/src/openrct2/scripting/ScriptEngine.h +++ b/src/openrct2/scripting/ScriptEngine.h @@ -145,9 +145,9 @@ namespace OpenRCT2::Scripting IPlatformEnvironment& _env; DukContext _context; bool _initialised{}; - bool _hotReloading{}; - bool _pluginsLoaded{}; - bool _pluginsStarted{}; + bool _hotReloadingInitialised{}; + bool _transientPluginsEnabled{}; + bool _transientPluginsStarted{}; std::queue, std::string>> _evalQueue; std::vector> _plugins; uint32_t _lastHotReloadCheckTick{}; @@ -212,6 +212,8 @@ namespace OpenRCT2::Scripting void LoadPlugins(); void UnloadPlugins(); + void LoadTransientPlugins(); + void UnloadTransientPlugins(); void Tick(); std::future Eval(const std::string& s); DukValue ExecutePluginCall( @@ -253,8 +255,7 @@ namespace OpenRCT2::Scripting void UnregisterPlugin(std::string_view path); void RegisterPlugin(std::string_view path); void StartIntransientPlugins(); - void StartPlugins(); - void StopPlugins(); + void StartTransientPlugins(); void LoadPlugin(const std::string& path); void LoadPlugin(std::shared_ptr& plugin); void UnloadPlugin(std::shared_ptr& plugin); @@ -264,6 +265,7 @@ namespace OpenRCT2::Scripting static bool ShouldLoadScript(std::string_view path); bool ShouldStartPlugin(const std::shared_ptr& plugin); void SetupHotReloading(); + void DoAutoReloadPluginCheck(); void AutoReloadPlugins(); void ProcessREPL(); void RemoveCustomGameActions(const std::shared_ptr& plugin);