mirror of https://github.com/OpenRCT2/OpenRCT2.git
Add game mutable protection
This commit is contained in:
parent
dc64d3541d
commit
a5c8ff920f
|
@ -38,7 +38,7 @@ namespace OpenRCT2::Scripting
|
|||
auto& execInfo = scriptEngine.GetExecInfo();
|
||||
auto ctx = scriptEngine.GetContext();
|
||||
|
||||
ScriptExecutionInfo::PluginScope scope(execInfo, Owner);
|
||||
ScriptExecutionInfo::PluginScope scope(execInfo, Owner, false);
|
||||
Callback.push();
|
||||
duk_pcall(ctx, 0);
|
||||
duk_pop(ctx);
|
||||
|
|
|
@ -648,7 +648,7 @@ namespace OpenRCT2::Ui::Windows
|
|||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||
auto& execInfo = scriptEngine.GetExecInfo();
|
||||
{
|
||||
ScriptExecutionInfo::PluginScope scope(execInfo, owner);
|
||||
ScriptExecutionInfo::PluginScope scope(execInfo, owner, false);
|
||||
dukHandler.push();
|
||||
for (const auto& arg : args)
|
||||
{
|
||||
|
|
|
@ -232,7 +232,8 @@ namespace OpenRCT2::Scripting
|
|||
dukglue_register_property(ctx, &ScViewport::bottom_get, &ScViewport::bottom_set, "bottom");
|
||||
dukglue_register_property(ctx, &ScViewport::rotation_get, &ScViewport::rotation_set, "rotation");
|
||||
dukglue_register_property(ctx, &ScViewport::zoom_get, &ScViewport::zoom_set, "zoom");
|
||||
dukglue_register_property(ctx, &ScViewport::visibilityFlags_get, &ScViewport::visibilityFlags_set, "visibilityFlags");
|
||||
dukglue_register_property(
|
||||
ctx, &ScViewport::visibilityFlags_get, &ScViewport::visibilityFlags_set, "visibilityFlags");
|
||||
dukglue_register_method(ctx, &ScViewport::getCentrePosition, "getCentrePosition");
|
||||
dukglue_register_method(ctx, &ScViewport::moveTo, "moveTo");
|
||||
dukglue_register_method(ctx, &ScViewport::scrollTo, "scrollTo");
|
||||
|
|
|
@ -270,7 +270,7 @@ void GameState::UpdateLogic()
|
|||
}
|
||||
|
||||
auto& hookEngine = GetContext()->GetScriptEngine().GetHookEngine();
|
||||
hookEngine.Call(HOOK_TYPE::INTERVAL_TICK);
|
||||
hookEngine.Call(HOOK_TYPE::INTERVAL_TICK, true);
|
||||
|
||||
auto day = _date.GetDay();
|
||||
|
||||
|
@ -279,7 +279,7 @@ void GameState::UpdateLogic()
|
|||
|
||||
if (day != _date.GetDay())
|
||||
{
|
||||
hookEngine.Call(HOOK_TYPE::INTERVAL_DAY);
|
||||
hookEngine.Call(HOOK_TYPE::INTERVAL_DAY, true);
|
||||
}
|
||||
|
||||
scenario_update();
|
||||
|
|
|
@ -2905,7 +2905,7 @@ void Network::Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& p
|
|||
auto e = DukValue::take_from_stack(ctx);
|
||||
|
||||
// Call the subscriptions
|
||||
hookEngine.Call(OpenRCT2::Scripting::HOOK_TYPE::NETWORK_CHAT, e);
|
||||
hookEngine.Call(OpenRCT2::Scripting::HOOK_TYPE::NETWORK_CHAT, e, false);
|
||||
|
||||
// Update text from object if subscriptions changed it
|
||||
if (e["message"].type() != DukValue::Type::STRING)
|
||||
|
|
|
@ -93,12 +93,12 @@ bool HookEngine::HasSubscriptions(HOOK_TYPE type) const
|
|||
return !hookList.Hooks.empty();
|
||||
}
|
||||
|
||||
void HookEngine::Call(HOOK_TYPE type)
|
||||
void HookEngine::Call(HOOK_TYPE type, bool isGameStateMutable)
|
||||
{
|
||||
auto& hookList = GetHookList(type);
|
||||
for (auto& hook : hookList.Hooks)
|
||||
{
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, hook.Owner);
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, hook.Owner, false);
|
||||
|
||||
const auto& function = hook.Function;
|
||||
function.push();
|
||||
|
@ -107,12 +107,12 @@ void HookEngine::Call(HOOK_TYPE type)
|
|||
}
|
||||
}
|
||||
|
||||
void HookEngine::Call(HOOK_TYPE type, DukValue args)
|
||||
void HookEngine::Call(HOOK_TYPE type, DukValue args, bool isGameStateMutable)
|
||||
{
|
||||
auto& hookList = GetHookList(type);
|
||||
for (auto& hook : hookList.Hooks)
|
||||
{
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, hook.Owner);
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, hook.Owner, false);
|
||||
|
||||
const auto& function = hook.Function;
|
||||
auto ctx = function.context();
|
||||
|
@ -124,12 +124,12 @@ void HookEngine::Call(HOOK_TYPE type, DukValue args)
|
|||
}
|
||||
}
|
||||
|
||||
void HookEngine::Call(HOOK_TYPE type, const std::initializer_list<std::pair<std::string_view, std::any>>& args)
|
||||
void HookEngine::Call(HOOK_TYPE type, const std::initializer_list<std::pair<std::string_view, std::any>>& args, bool isGameStateMutable)
|
||||
{
|
||||
auto& hookList = GetHookList(type);
|
||||
for (auto& hook : hookList.Hooks)
|
||||
{
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, hook.Owner);
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, hook.Owner, false);
|
||||
|
||||
const auto& function = hook.Function;
|
||||
auto ctx = function.context();
|
||||
|
|
|
@ -81,9 +81,9 @@ namespace OpenRCT2::Scripting
|
|||
void UnsubscribeAll(std::shared_ptr<const Plugin> owner);
|
||||
void UnsubscribeAll();
|
||||
bool HasSubscriptions(HOOK_TYPE type) const;
|
||||
void Call(HOOK_TYPE type);
|
||||
void Call(HOOK_TYPE type, DukValue args);
|
||||
void Call(HOOK_TYPE type, const std::initializer_list<std::pair<std::string_view, std::any>>& args);
|
||||
void Call(HOOK_TYPE type, bool isGameStateMutable);
|
||||
void Call(HOOK_TYPE type, DukValue args, bool isGameStateMutable);
|
||||
void Call(HOOK_TYPE type, const std::initializer_list<std::pair<std::string_view, std::any>>& args, bool isGameStateMutable);
|
||||
|
||||
private:
|
||||
HookList& GetHookList(HOOK_TYPE type);
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace OpenRCT2::Scripting
|
|||
|
||||
void monthsElapsed_set(uint32_t value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
gDateMonthsElapsed = value;
|
||||
}
|
||||
|
||||
|
@ -53,6 +54,7 @@ namespace OpenRCT2::Scripting
|
|||
|
||||
void monthProgress_set(int32_t value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
gDateMonthTicks = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "../windows/Intent.h"
|
||||
#include "../world/Park.h"
|
||||
#include "Duktape.hpp"
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -30,6 +31,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void cash_set(money32 value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
gCash = value;
|
||||
auto intent = Intent(INTENT_ACTION_UPDATE_CASH);
|
||||
context_broadcast_intent(&intent);
|
||||
|
@ -41,6 +43,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void rating_set(int32_t value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
gParkRating = std::min(std::max(0, value), 999);
|
||||
auto intent = Intent(INTENT_ACTION_UPDATE_PARK_RATING);
|
||||
context_broadcast_intent(&intent);
|
||||
|
@ -52,6 +55,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void bankLoan_set(money32 value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
gBankLoan = value;
|
||||
auto intent = Intent(INTENT_ACTION_UPDATE_CASH);
|
||||
context_broadcast_intent(&intent);
|
||||
|
@ -63,6 +67,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void maxBankLoan_set(money32 value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
gMaxBankLoan = value;
|
||||
auto intent = Intent(INTENT_ACTION_UPDATE_CASH);
|
||||
context_broadcast_intent(&intent);
|
||||
|
@ -70,6 +75,7 @@ namespace OpenRCT2::Scripting
|
|||
|
||||
void postMessage(DukValue message)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
try
|
||||
{
|
||||
uint8_t type = NEWS_ITEM_BLANK;
|
||||
|
|
|
@ -114,6 +114,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void name_set(std::string value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
_ride->custom_name = value;
|
||||
}
|
||||
|
||||
|
@ -123,6 +124,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void excitement_set(int32_t value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
_ride->excitement = value;
|
||||
}
|
||||
|
||||
|
@ -132,6 +134,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void intensity_set(int32_t value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
_ride->intensity = value;
|
||||
}
|
||||
|
||||
|
@ -141,6 +144,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void nausea_set(int32_t value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
_ride->nausea = value;
|
||||
}
|
||||
|
||||
|
@ -150,6 +154,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void totalCustomers_set(int32_t value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
_ride->total_customers = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,8 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void x_set(int32_t value)
|
||||
{
|
||||
_sprite->generic.x = value;
|
||||
ThrowIfGameStateNotMutable();
|
||||
sprite_move(value, _sprite->generic.y, _sprite->generic.z, &_sprite->generic);
|
||||
}
|
||||
|
||||
// y getter and setter
|
||||
|
@ -52,7 +53,8 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void y_set(int32_t value)
|
||||
{
|
||||
_sprite->generic.y = value;
|
||||
ThrowIfGameStateNotMutable();
|
||||
sprite_move(_sprite->generic.x, value, _sprite->generic.z, &_sprite->generic);
|
||||
}
|
||||
|
||||
// z getter and setter
|
||||
|
@ -62,7 +64,8 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void z_set(int16_t value)
|
||||
{
|
||||
_sprite->generic.z = value;
|
||||
ThrowIfGameStateNotMutable();
|
||||
sprite_move(_sprite->generic.x, _sprite->generic.y, value, &_sprite->generic);
|
||||
}
|
||||
|
||||
uint8_t tshirtColour_get()
|
||||
|
@ -71,6 +74,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void tshirtColour_set(uint8_t value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
_sprite->peep.tshirt_colour = value;
|
||||
}
|
||||
uint8_t trousersColour_get()
|
||||
|
@ -79,6 +83,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void trousersColour_set(uint8_t value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
_sprite->peep.trousers_colour = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void broken_set(bool value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
if (value)
|
||||
{
|
||||
_element->flags |= TILE_ELEMENT_FLAG_BROKEN;
|
||||
|
@ -85,6 +86,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void baseHeight_set(uint8_t newBaseHeight)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
_element->base_height = newBaseHeight;
|
||||
}
|
||||
|
||||
|
@ -94,6 +96,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void clearanceHeight_set(uint8_t newClearanceHeight)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
_element->clearance_height = newClearanceHeight;
|
||||
}
|
||||
|
||||
|
@ -106,6 +109,7 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
void grassLength_set(uint8_t value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
auto el = _element->AsSurface();
|
||||
if (el != nullptr)
|
||||
{
|
||||
|
|
|
@ -132,7 +132,7 @@ void ScriptEngine::LoadPlugin(std::shared_ptr<Plugin>& plugin)
|
|||
{
|
||||
try
|
||||
{
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, plugin);
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, plugin, false);
|
||||
plugin->Load();
|
||||
|
||||
auto metadata = plugin->GetMetadata();
|
||||
|
@ -162,7 +162,7 @@ void ScriptEngine::StopPlugin(std::shared_ptr<Plugin> plugin)
|
|||
callback(plugin);
|
||||
}
|
||||
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, plugin);
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, plugin, false);
|
||||
try
|
||||
{
|
||||
plugin->Stop();
|
||||
|
@ -214,7 +214,7 @@ void ScriptEngine::AutoReloadPlugins()
|
|||
{
|
||||
StopPlugin(plugin);
|
||||
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, plugin);
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, plugin, false);
|
||||
plugin->Load();
|
||||
LogPluginInfo(plugin, "Reloaded");
|
||||
plugin->Start();
|
||||
|
@ -247,7 +247,7 @@ void ScriptEngine::StartPlugins()
|
|||
{
|
||||
if (!plugin->HasStarted() && ShouldStartPlugin(plugin))
|
||||
{
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, plugin);
|
||||
ScriptExecutionInfo::PluginScope scope(_execInfo, plugin, false);
|
||||
try
|
||||
{
|
||||
LogPluginInfo(plugin, "Started");
|
||||
|
@ -380,3 +380,21 @@ static std::string Stringify(duk_context* ctx, duk_idx_t idx)
|
|||
return duk_safe_to_string(ctx, idx);
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenRCT2::Scripting::IsGameStateMutable()
|
||||
{
|
||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||
auto& execInfo = scriptEngine.GetExecInfo();
|
||||
return execInfo.IsGameStateMutable();
|
||||
}
|
||||
|
||||
void OpenRCT2::Scripting::ThrowIfGameStateNotMutable()
|
||||
{
|
||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||
auto& execInfo = scriptEngine.GetExecInfo();
|
||||
if (!execInfo.IsGameStateMutable())
|
||||
{
|
||||
auto ctx = scriptEngine.GetContext();
|
||||
duk_error(ctx, DUK_ERR_ERROR, "Game state is not mutable in this context.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace OpenRCT2::Scripting
|
|||
{
|
||||
private:
|
||||
std::shared_ptr<Plugin> _plugin;
|
||||
bool _isGameStateMutable{};
|
||||
|
||||
public:
|
||||
class PluginScope
|
||||
|
@ -48,16 +49,18 @@ namespace OpenRCT2::Scripting
|
|||
std::shared_ptr<Plugin> _plugin;
|
||||
|
||||
public:
|
||||
PluginScope(ScriptExecutionInfo& execInfo, std::shared_ptr<Plugin> plugin)
|
||||
PluginScope(ScriptExecutionInfo& execInfo, std::shared_ptr<Plugin> plugin, bool isGameStateMutable)
|
||||
: _execInfo(execInfo)
|
||||
, _plugin(plugin)
|
||||
{
|
||||
_execInfo._plugin = plugin;
|
||||
_execInfo._isGameStateMutable = isGameStateMutable;
|
||||
}
|
||||
PluginScope(const PluginScope&) = delete;
|
||||
~PluginScope()
|
||||
{
|
||||
_execInfo._plugin = nullptr;
|
||||
_execInfo._isGameStateMutable = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -65,6 +68,11 @@ namespace OpenRCT2::Scripting
|
|||
{
|
||||
return _plugin;
|
||||
}
|
||||
|
||||
bool IsGameStateMutable()
|
||||
{
|
||||
return _isGameStateMutable;
|
||||
}
|
||||
};
|
||||
|
||||
class DukContext
|
||||
|
@ -150,9 +158,13 @@ namespace OpenRCT2::Scripting
|
|||
void LoadPlugin(std::shared_ptr<Plugin>& plugin);
|
||||
void StopPlugin(std::shared_ptr<Plugin> plugin);
|
||||
bool ShouldLoadScript(const std::string& path);
|
||||
bool ShouldStartPlugin(const std::shared_ptr<Plugin> &plugin);
|
||||
bool ShouldStartPlugin(const std::shared_ptr<Plugin>& plugin);
|
||||
void SetupHotReloading();
|
||||
void AutoReloadPlugins();
|
||||
void ProcessREPL();
|
||||
};
|
||||
|
||||
bool IsGameStateMutable();
|
||||
void ThrowIfGameStateNotMutable();
|
||||
|
||||
} // namespace OpenRCT2::Scripting
|
||||
|
|
Loading…
Reference in New Issue