mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 19:13:07 +01:00
Close plugin's windows gracefully when stopped
When a plugin is stopped, close all windows created by that plugin. Ensure the close event on the window can not open a new window if the plugin is being stopped.
This commit is contained in:
@@ -9,16 +9,17 @@
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
|
||||
# include "../UiContext.h"
|
||||
# include "../interface/Dropdown.h"
|
||||
# include "../interface/Widget.h"
|
||||
# include "../scripting/ScGraphicsContext.hpp"
|
||||
# include "../scripting/ScWidget.hpp"
|
||||
# include "../windows/Window.h"
|
||||
# include "CustomListView.h"
|
||||
# include "ScUi.hpp"
|
||||
# include "ScWindow.hpp"
|
||||
|
||||
# include <limits>
|
||||
# include <openrct2-ui/interface/Widget.h>
|
||||
# include <openrct2-ui/windows/Window.h>
|
||||
# include <openrct2/drawing/Drawing.h>
|
||||
# include <openrct2/interface/Window.h>
|
||||
# include <openrct2/localisation/Formatter.h>
|
||||
@@ -1433,6 +1434,29 @@ namespace OpenRCT2::Ui::Windows
|
||||
}
|
||||
}
|
||||
|
||||
void CloseWindowsOwnedByPlugin(std::shared_ptr<Plugin> plugin)
|
||||
{
|
||||
// Get all the windows that need closing
|
||||
std::vector<std::shared_ptr<rct_window>> customWindows;
|
||||
for (const auto& window : g_window_list)
|
||||
{
|
||||
if (window->classification == WC_CUSTOM)
|
||||
{
|
||||
auto customWindow = reinterpret_cast<CustomWindow*>(window.get());
|
||||
auto customInfo = reinterpret_cast<CustomWindowInfo*>(customWindow->custom_info);
|
||||
if (customInfo != nullptr && customInfo->Owner == plugin)
|
||||
{
|
||||
customWindows.push_back(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& window : customWindows)
|
||||
{
|
||||
window_close(window.get());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenRCT2::Ui::Windows
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace OpenRCT2::Ui::Windows
|
||||
CustomListView* GetCustomListView(rct_window* w, rct_widgetindex widgetIndex);
|
||||
int32_t GetWidgetMaxLength(rct_window* w, rct_widgetindex widgetIndex);
|
||||
void SetWidgetMaxLength(rct_window* w, rct_widgetindex widgetIndex, int32_t value);
|
||||
void CloseWindowsOwnedByPlugin(std::shared_ptr<Plugin> plugin);
|
||||
} // namespace OpenRCT2::Ui::Windows
|
||||
|
||||
#endif
|
||||
|
||||
@@ -162,6 +162,8 @@ namespace OpenRCT2::Scripting
|
||||
auto& execInfo = _scriptEngine.GetExecInfo();
|
||||
auto owner = execInfo.GetCurrentPlugin();
|
||||
|
||||
owner->ThrowIfStopping();
|
||||
|
||||
std::shared_ptr<ScWindow> scWindow = nullptr;
|
||||
auto w = window_custom_open(owner, desc);
|
||||
if (w != nullptr)
|
||||
|
||||
@@ -56,6 +56,8 @@ void UiScriptExtensions::Extend(ScriptEngine& scriptEngine)
|
||||
ScWindow::Register(ctx);
|
||||
|
||||
InitialiseCustomMenuItems(scriptEngine);
|
||||
scriptEngine.SubscribeToPluginStoppedEvent(
|
||||
[](std::shared_ptr<Plugin> plugin) -> void { CloseWindowsOwnedByPlugin(plugin); });
|
||||
}
|
||||
|
||||
std::shared_ptr<ScWindow> ScWidget::window_get() const
|
||||
|
||||
@@ -96,11 +96,25 @@ void Plugin::Start()
|
||||
_hasStarted = true;
|
||||
}
|
||||
|
||||
void Plugin::Stop()
|
||||
void Plugin::StopBegin()
|
||||
{
|
||||
_isStopping = true;
|
||||
}
|
||||
|
||||
void Plugin::StopEnd()
|
||||
{
|
||||
_isStopping = false;
|
||||
_hasStarted = false;
|
||||
}
|
||||
|
||||
void Plugin::ThrowIfStopping() const
|
||||
{
|
||||
if (IsStopping())
|
||||
{
|
||||
duk_error(_context, DUK_ERR_ERROR, "Plugin is stopping.");
|
||||
}
|
||||
}
|
||||
|
||||
void Plugin::LoadCodeFromFile()
|
||||
{
|
||||
_code = File::ReadAllText(_path);
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace OpenRCT2::Scripting
|
||||
PluginMetadata _metadata{};
|
||||
std::string _code;
|
||||
bool _hasStarted{};
|
||||
bool _isStopping{};
|
||||
|
||||
public:
|
||||
std::string GetPath() const
|
||||
@@ -81,6 +82,11 @@ namespace OpenRCT2::Scripting
|
||||
return _hasStarted;
|
||||
}
|
||||
|
||||
bool IsStopping() const
|
||||
{
|
||||
return _isStopping;
|
||||
}
|
||||
|
||||
int32_t GetTargetAPIVersion() const;
|
||||
|
||||
Plugin() = default;
|
||||
@@ -91,7 +97,10 @@ namespace OpenRCT2::Scripting
|
||||
void SetCode(std::string_view code);
|
||||
void Load();
|
||||
void Start();
|
||||
void Stop();
|
||||
void StopBegin();
|
||||
void StopEnd();
|
||||
|
||||
void ThrowIfStopping() const;
|
||||
|
||||
private:
|
||||
void LoadCodeFromFile();
|
||||
|
||||
@@ -509,24 +509,18 @@ void ScriptEngine::StopPlugin(std::shared_ptr<Plugin> plugin)
|
||||
{
|
||||
if (plugin->HasStarted())
|
||||
{
|
||||
RemoveCustomGameActions(plugin);
|
||||
RemoveIntervals(plugin);
|
||||
RemoveSockets(plugin);
|
||||
_hookEngine.UnsubscribeAll(plugin);
|
||||
plugin->StopBegin();
|
||||
|
||||
for (const auto& callback : _pluginStoppedSubscriptions)
|
||||
{
|
||||
callback(plugin);
|
||||
}
|
||||
RemoveCustomGameActions(plugin);
|
||||
RemoveIntervals(plugin);
|
||||
RemoveSockets(plugin);
|
||||
_hookEngine.UnsubscribeAll(plugin);
|
||||
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, plugin, false);
|
||||
try
|
||||
{
|
||||
plugin->Stop();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
_console.WriteLineError(e.what());
|
||||
}
|
||||
plugin->StopEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user