mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-24 00:03:11 +01:00
Change API for interacting with park storage
This commit is contained in:
15
distribution/openrct2.d.ts
vendored
15
distribution/openrct2.d.ts
vendored
@@ -186,15 +186,18 @@ declare global {
|
|||||||
sharedStorage: Configuration;
|
sharedStorage: Configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shared generic storage for all plugins. Data is persisted for the current
|
* Gets the storage for the current plugin if no name is specified.
|
||||||
* loaded park, and is stored inside the .park file. Any references to objects,
|
* If a plugin name is specified, the storage for the plugin with that name will be returned.
|
||||||
* or arrays are copied by reference. If these arrays, objects, or any other
|
* Data is persisted for the current loaded park, and is stored inside the .park file.
|
||||||
* arrays, or objects that they reference change without a subsequent call to
|
* Any references to objects, or arrays are copied by reference. If these arrays, objects,
|
||||||
|
* or any other arrays, or objects that they reference change without a subsequent call to
|
||||||
* the `set` method, their new state will still be serialised.
|
* the `set` method, their new state will still be serialised.
|
||||||
* Keep in mind that all data here will be serialised every time the park is
|
* Keep in mind that all data here will be serialised every time the park is
|
||||||
* saved, including when the park is periodically saved automatically.
|
* saved, including when the park is periodically saved automatically.
|
||||||
|
* @param pluginName The name of the plugin to get a store for. If undefined, the
|
||||||
|
* current plugin's name will be used. Plugin names are case sensitive.
|
||||||
*/
|
*/
|
||||||
parkStorage: Configuration;
|
getParkStorage(pluginName?: string): Configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the current state of the map and save to disc.
|
* Render the current state of the map and save to disc.
|
||||||
@@ -313,7 +316,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Configuration {
|
interface Configuration {
|
||||||
getAll(namespace: string): { [name: string]: any };
|
getAll(namespace?: string): { [name: string]: any };
|
||||||
get<T>(key: string): T | undefined;
|
get<T>(key: string): T | undefined;
|
||||||
get<T>(key: string, defaultValue: T): T;
|
get<T>(key: string, defaultValue: T): T;
|
||||||
set<T>(key: string, value: T): void;
|
set<T>(key: string, value: T): void;
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ if (!h) {
|
|||||||
|
|
||||||
All plugins have access to the same shared storage.
|
All plugins have access to the same shared storage.
|
||||||
|
|
||||||
If you want to only store data specific to the current park that is loaded, use `context.parkStorage`. Any data stored here will be written to the .park file.
|
If you want to only store data specific to the current park that is loaded, use `context.getParkStorage`. Any data stored here will be written to the .park file.
|
||||||
|
|
||||||
> Can plugins communicate with other processes, or the internet?
|
> Can plugins communicate with other processes, or the internet?
|
||||||
|
|
||||||
|
|||||||
@@ -19,22 +19,30 @@
|
|||||||
|
|
||||||
namespace OpenRCT2::Scripting
|
namespace OpenRCT2::Scripting
|
||||||
{
|
{
|
||||||
|
enum class ScConfigurationKind
|
||||||
|
{
|
||||||
|
User,
|
||||||
|
Shared,
|
||||||
|
Park
|
||||||
|
};
|
||||||
|
|
||||||
class ScConfiguration
|
class ScConfiguration
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool _isUserConfig{};
|
ScConfigurationKind _kind;
|
||||||
DukValue _backingObject;
|
DukValue _backingObject;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// context.configuration
|
// context.configuration
|
||||||
ScConfiguration()
|
ScConfiguration()
|
||||||
: _isUserConfig(true)
|
: _kind(ScConfigurationKind::User)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// context.sharedStorage
|
// context.sharedStorage / context.getParkStorage
|
||||||
ScConfiguration(const DukValue& backingObject)
|
ScConfiguration(ScConfigurationKind kind, const DukValue& backingObject)
|
||||||
: _backingObject(backingObject)
|
: _kind(kind)
|
||||||
|
, _backingObject(backingObject)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,15 +76,18 @@ namespace OpenRCT2::Scripting
|
|||||||
std::optional<DukValue> GetNamespaceObject(std::string_view ns) const
|
std::optional<DukValue> GetNamespaceObject(std::string_view ns) const
|
||||||
{
|
{
|
||||||
auto store = _backingObject;
|
auto store = _backingObject;
|
||||||
auto k = ns;
|
if (!ns.empty())
|
||||||
bool end;
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
auto [next, remainder] = GetNextNamespace(k);
|
auto k = ns;
|
||||||
store = store[next];
|
bool end;
|
||||||
k = remainder;
|
do
|
||||||
end = store.type() == DukValue::Type::UNDEFINED || remainder.empty();
|
{
|
||||||
} while (!end);
|
auto [next, remainder] = GetNextNamespace(k);
|
||||||
|
store = store[next];
|
||||||
|
k = remainder;
|
||||||
|
end = store.type() == DukValue::Type::UNDEFINED || remainder.empty();
|
||||||
|
} while (!end);
|
||||||
|
}
|
||||||
return store.type() == DukValue::OBJECT ? std::make_optional(store) : std::nullopt;
|
return store.type() == DukValue::OBJECT ? std::make_optional(store) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,17 +123,26 @@ namespace OpenRCT2::Scripting
|
|||||||
|
|
||||||
bool IsValidNamespace(std::string_view ns) const
|
bool IsValidNamespace(std::string_view ns) const
|
||||||
{
|
{
|
||||||
if (ns.empty() || ns[0] == '.' || ns[ns.size() - 1] == '.')
|
if (!ns.empty() && (ns[0] == '.' || ns[ns.size() - 1] == '.'))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (size_t i = 1; i < ns.size() - 1; i++)
|
|
||||||
|
if (_kind != ScConfigurationKind::Park)
|
||||||
{
|
{
|
||||||
if (ns[i - 1] == '.' && ns[i] == '.')
|
if (ns.empty())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
for (size_t i = 1; i < ns.size() - 1; i++)
|
||||||
|
{
|
||||||
|
if (ns[i - 1] == '.' && ns[i] == '.')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,13 +151,24 @@ namespace OpenRCT2::Scripting
|
|||||||
return !key.empty() && key.find('.') == std::string_view::npos;
|
return !key.empty() && key.find('.') == std::string_view::npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
DukValue getAll(const std::string& ns) const
|
DukValue getAll(const DukValue& dukNamespace) const
|
||||||
{
|
{
|
||||||
DukValue result;
|
DukValue result;
|
||||||
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
||||||
|
|
||||||
|
std::string ns = "";
|
||||||
|
if (dukNamespace.type() == DukValue::Type::STRING)
|
||||||
|
{
|
||||||
|
ns = dukNamespace.as_string();
|
||||||
|
}
|
||||||
|
else if (dukNamespace.type() != DukValue::Type::UNDEFINED)
|
||||||
|
{
|
||||||
|
duk_error(ctx, DUK_ERR_ERROR, "Namespace was invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
if (IsValidNamespace(ns))
|
if (IsValidNamespace(ns))
|
||||||
{
|
{
|
||||||
if (_isUserConfig)
|
if (_kind == ScConfigurationKind::User)
|
||||||
{
|
{
|
||||||
DukObject obj(ctx);
|
DukObject obj(ctx);
|
||||||
if (ns == "general")
|
if (ns == "general")
|
||||||
@@ -163,7 +194,7 @@ namespace OpenRCT2::Scripting
|
|||||||
DukValue get(const std::string& key, const DukValue& defaultValue) const
|
DukValue get(const std::string& key, const DukValue& defaultValue) const
|
||||||
{
|
{
|
||||||
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
||||||
if (_isUserConfig)
|
if (_kind == ScConfigurationKind::User)
|
||||||
{
|
{
|
||||||
if (key == "general.language")
|
if (key == "general.language")
|
||||||
{
|
{
|
||||||
@@ -214,7 +245,7 @@ namespace OpenRCT2::Scripting
|
|||||||
{
|
{
|
||||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||||
auto ctx = scriptEngine.GetContext();
|
auto ctx = scriptEngine.GetContext();
|
||||||
if (_isUserConfig)
|
if (_kind == ScConfigurationKind::User)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,13 +55,59 @@ namespace OpenRCT2::Scripting
|
|||||||
std::shared_ptr<ScConfiguration> sharedStorage_get()
|
std::shared_ptr<ScConfiguration> sharedStorage_get()
|
||||||
{
|
{
|
||||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||||
return std::make_shared<ScConfiguration>(scriptEngine.GetSharedStorage());
|
return std::make_shared<ScConfiguration>(ScConfigurationKind::Shared, scriptEngine.GetSharedStorage());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ScConfiguration> parkStorage_get()
|
std::shared_ptr<ScConfiguration> GetParkStorageForPlugin(std::string_view pluginName)
|
||||||
{
|
{
|
||||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||||
return std::make_shared<ScConfiguration>(scriptEngine.GetParkStorage());
|
auto parkStore = scriptEngine.GetParkStorage();
|
||||||
|
auto pluginStore = parkStore[pluginName];
|
||||||
|
|
||||||
|
// Create if it doesn't exist
|
||||||
|
if (pluginStore.type() != DukValue::Type::OBJECT)
|
||||||
|
{
|
||||||
|
auto* ctx = scriptEngine.GetContext();
|
||||||
|
parkStore.push();
|
||||||
|
duk_push_object(ctx);
|
||||||
|
duk_put_prop_lstring(ctx, -2, pluginName.data(), pluginName.size());
|
||||||
|
duk_pop(ctx);
|
||||||
|
|
||||||
|
pluginStore = parkStore[pluginName];
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_shared<ScConfiguration>(ScConfigurationKind::Park, pluginStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ScConfiguration> getParkStorage(const DukValue& dukPluginName)
|
||||||
|
{
|
||||||
|
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||||
|
|
||||||
|
std::shared_ptr<ScConfiguration> result;
|
||||||
|
if (dukPluginName.type() == DukValue::Type::STRING)
|
||||||
|
{
|
||||||
|
auto& pluginName = dukPluginName.as_string();
|
||||||
|
if (pluginName.empty())
|
||||||
|
{
|
||||||
|
duk_error(scriptEngine.GetContext(), DUK_ERR_ERROR, "Plugin name is empty");
|
||||||
|
}
|
||||||
|
result = GetParkStorageForPlugin(pluginName);
|
||||||
|
}
|
||||||
|
else if (dukPluginName.type() == DukValue::Type::UNDEFINED)
|
||||||
|
{
|
||||||
|
auto plugin = _execInfo.GetCurrentPlugin();
|
||||||
|
if (plugin == nullptr)
|
||||||
|
{
|
||||||
|
duk_error(
|
||||||
|
scriptEngine.GetContext(), DUK_ERR_ERROR, "Plugin name must be specified when used from console.");
|
||||||
|
}
|
||||||
|
result = GetParkStorageForPlugin(plugin->GetMetadata().Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
duk_error(scriptEngine.GetContext(), DUK_ERR_ERROR, "Invalid plugin name.");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void captureImage(const DukValue& options)
|
void captureImage(const DukValue& options)
|
||||||
@@ -387,7 +433,7 @@ namespace OpenRCT2::Scripting
|
|||||||
dukglue_register_property(ctx, &ScContext::apiVersion_get, nullptr, "apiVersion");
|
dukglue_register_property(ctx, &ScContext::apiVersion_get, nullptr, "apiVersion");
|
||||||
dukglue_register_property(ctx, &ScContext::configuration_get, nullptr, "configuration");
|
dukglue_register_property(ctx, &ScContext::configuration_get, nullptr, "configuration");
|
||||||
dukglue_register_property(ctx, &ScContext::sharedStorage_get, nullptr, "sharedStorage");
|
dukglue_register_property(ctx, &ScContext::sharedStorage_get, nullptr, "sharedStorage");
|
||||||
dukglue_register_property(ctx, &ScContext::parkStorage_get, nullptr, "parkStorage");
|
dukglue_register_method(ctx, &ScContext::getParkStorage, "getParkStorage");
|
||||||
dukglue_register_method(ctx, &ScContext::captureImage, "captureImage");
|
dukglue_register_method(ctx, &ScContext::captureImage, "captureImage");
|
||||||
dukglue_register_method(ctx, &ScContext::getObject, "getObject");
|
dukglue_register_method(ctx, &ScContext::getObject, "getObject");
|
||||||
dukglue_register_method(ctx, &ScContext::getAllObjects, "getAllObjects");
|
dukglue_register_method(ctx, &ScContext::getAllObjects, "getAllObjects");
|
||||||
|
|||||||
Reference in New Issue
Block a user