mirror of https://github.com/OpenRCT2/OpenRCT2.git
Change API for interacting with park storage
This commit is contained in:
parent
1182ff5f19
commit
ed8b7cb6ee
|
@ -186,15 +186,18 @@ declare global {
|
|||
sharedStorage: Configuration;
|
||||
|
||||
/**
|
||||
* Shared generic storage for all plugins. Data is persisted for the current
|
||||
* loaded park, and is stored inside the .park file. 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
|
||||
* Gets the storage for the current plugin if no name is specified.
|
||||
* If a plugin name is specified, the storage for the plugin with that name will be returned.
|
||||
* Data is persisted for the current loaded park, and is stored inside the .park file.
|
||||
* 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.
|
||||
* Keep in mind that all data here will be serialised every time the park is
|
||||
* 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.
|
||||
|
@ -313,7 +316,7 @@ declare global {
|
|||
}
|
||||
|
||||
interface Configuration {
|
||||
getAll(namespace: string): { [name: string]: any };
|
||||
getAll(namespace?: string): { [name: string]: any };
|
||||
get<T>(key: string): T | undefined;
|
||||
get<T>(key: string, defaultValue: T): T;
|
||||
set<T>(key: string, value: T): void;
|
||||
|
|
|
@ -172,7 +172,7 @@ if (!h) {
|
|||
|
||||
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?
|
||||
|
||||
|
|
|
@ -19,22 +19,30 @@
|
|||
|
||||
namespace OpenRCT2::Scripting
|
||||
{
|
||||
enum class ScConfigurationKind
|
||||
{
|
||||
User,
|
||||
Shared,
|
||||
Park
|
||||
};
|
||||
|
||||
class ScConfiguration
|
||||
{
|
||||
private:
|
||||
bool _isUserConfig{};
|
||||
ScConfigurationKind _kind;
|
||||
DukValue _backingObject;
|
||||
|
||||
public:
|
||||
// context.configuration
|
||||
ScConfiguration()
|
||||
: _isUserConfig(true)
|
||||
: _kind(ScConfigurationKind::User)
|
||||
{
|
||||
}
|
||||
|
||||
// context.sharedStorage
|
||||
ScConfiguration(const DukValue& backingObject)
|
||||
: _backingObject(backingObject)
|
||||
// context.sharedStorage / context.getParkStorage
|
||||
ScConfiguration(ScConfigurationKind kind, const DukValue& backingObject)
|
||||
: _kind(kind)
|
||||
, _backingObject(backingObject)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -68,15 +76,18 @@ namespace OpenRCT2::Scripting
|
|||
std::optional<DukValue> GetNamespaceObject(std::string_view ns) const
|
||||
{
|
||||
auto store = _backingObject;
|
||||
auto k = ns;
|
||||
bool end;
|
||||
do
|
||||
if (!ns.empty())
|
||||
{
|
||||
auto [next, remainder] = GetNextNamespace(k);
|
||||
store = store[next];
|
||||
k = remainder;
|
||||
end = store.type() == DukValue::Type::UNDEFINED || remainder.empty();
|
||||
} while (!end);
|
||||
auto k = ns;
|
||||
bool end;
|
||||
do
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -112,17 +123,26 @@ namespace OpenRCT2::Scripting
|
|||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
for (size_t i = 1; i < ns.size() - 1; i++)
|
||||
{
|
||||
if (ns[i - 1] == '.' && ns[i] == '.')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -131,13 +151,24 @@ namespace OpenRCT2::Scripting
|
|||
return !key.empty() && key.find('.') == std::string_view::npos;
|
||||
}
|
||||
|
||||
DukValue getAll(const std::string& ns) const
|
||||
DukValue getAll(const DukValue& dukNamespace) const
|
||||
{
|
||||
DukValue result;
|
||||
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 (_isUserConfig)
|
||||
if (_kind == ScConfigurationKind::User)
|
||||
{
|
||||
DukObject obj(ctx);
|
||||
if (ns == "general")
|
||||
|
@ -163,7 +194,7 @@ namespace OpenRCT2::Scripting
|
|||
DukValue get(const std::string& key, const DukValue& defaultValue) const
|
||||
{
|
||||
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
||||
if (_isUserConfig)
|
||||
if (_kind == ScConfigurationKind::User)
|
||||
{
|
||||
if (key == "general.language")
|
||||
{
|
||||
|
@ -214,7 +245,7 @@ namespace OpenRCT2::Scripting
|
|||
{
|
||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||
auto ctx = scriptEngine.GetContext();
|
||||
if (_isUserConfig)
|
||||
if (_kind == ScConfigurationKind::User)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -55,13 +55,59 @@ namespace OpenRCT2::Scripting
|
|||
std::shared_ptr<ScConfiguration> sharedStorage_get()
|
||||
{
|
||||
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();
|
||||
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)
|
||||
|
@ -387,7 +433,7 @@ namespace OpenRCT2::Scripting
|
|||
dukglue_register_property(ctx, &ScContext::apiVersion_get, nullptr, "apiVersion");
|
||||
dukglue_register_property(ctx, &ScContext::configuration_get, nullptr, "configuration");
|
||||
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::getObject, "getObject");
|
||||
dukglue_register_method(ctx, &ScContext::getAllObjects, "getAllObjects");
|
||||
|
|
Loading…
Reference in New Issue