mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
no longer crashes on startup :3
This commit is contained in:
parent
90ed885d89
commit
1032d9afa8
7 changed files with 85 additions and 27 deletions
|
@ -6,6 +6,8 @@
|
|||
// todo: remove this header in 4.0.0
|
||||
#include "Setting.hpp"
|
||||
#include "../utils/cocos.hpp"
|
||||
// this unfortunately has to be included because of C++ templates
|
||||
#include "../utils/JsonValidation.hpp"
|
||||
|
||||
// todo in v4: these can be removed as well as the friend decl in UnresolvedCustomSettingV3
|
||||
class ModSettingsManager;
|
||||
|
@ -13,7 +15,6 @@ class LegacyCustomSettingToV3Node;
|
|||
|
||||
namespace geode {
|
||||
class SettingNodeV3;
|
||||
class JsonExpectedValue;
|
||||
|
||||
class GEODE_DLL SettingV3 : public std::enable_shared_from_this<SettingV3> {
|
||||
private:
|
||||
|
@ -70,11 +71,28 @@ namespace geode {
|
|||
class Impl;
|
||||
std::shared_ptr<Impl> m_impl;
|
||||
|
||||
Result<> parseSharedBase(JsonExpectedValue& json);
|
||||
|
||||
protected:
|
||||
Result<> parseShared(JsonExpectedValue& json);
|
||||
Result<> isValidShared() const;
|
||||
|
||||
template <class T>
|
||||
Result<> parseShared(JsonExpectedValue& json, T& defaultValue) {
|
||||
GEODE_UNWRAP(this->parseSharedBase(json));
|
||||
auto value = json.needs("default");
|
||||
// Check if this is a platform-specific default value
|
||||
if (value.isObject() && value.has(GEODE_PLATFORM_SHORT_IDENTIFIER_NOARCH)) {
|
||||
value.needs(GEODE_PLATFORM_SHORT_IDENTIFIER_NOARCH).into(defaultValue);
|
||||
}
|
||||
else {
|
||||
value.into(defaultValue);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
public:
|
||||
GeodeSettingBaseV3();
|
||||
|
||||
std::string getName() const;
|
||||
std::optional<std::string> getDescription() const;
|
||||
std::optional<std::string> getEnableIf() const;
|
||||
|
@ -116,6 +134,8 @@ namespace geode {
|
|||
Result<> onParse(std::string const& key, std::string const& modID, matjson::Value const& json) override;
|
||||
|
||||
public:
|
||||
TitleSettingV3();
|
||||
|
||||
std::string getTitle() const;
|
||||
|
||||
bool load(matjson::Value const& json) override;
|
||||
|
@ -138,6 +158,8 @@ namespace geode {
|
|||
Result<> onParse(std::string const& key, std::string const& modID, matjson::Value const& json) override;
|
||||
|
||||
public:
|
||||
UnresolvedCustomSettingV3();
|
||||
|
||||
bool load(matjson::Value const& json) override;
|
||||
bool save(matjson::Value& json) const override;
|
||||
SettingNodeV3* createNode(float width) override;
|
||||
|
@ -159,6 +181,8 @@ namespace geode {
|
|||
Result<> onParse(std::string const& key, std::string const& modID, matjson::Value const& json) override;
|
||||
|
||||
public:
|
||||
BoolSettingV3();
|
||||
|
||||
bool getDefaultValue() const override;
|
||||
Result<> isValid(bool value) const override;
|
||||
|
||||
|
@ -180,6 +204,8 @@ namespace geode {
|
|||
Result<> onParse(std::string const& key, std::string const& modID, matjson::Value const& json) override;
|
||||
|
||||
public:
|
||||
IntSettingV3();
|
||||
|
||||
int64_t getDefaultValue() const override;
|
||||
Result<> isValid(int64_t value) const override;
|
||||
|
||||
|
@ -212,6 +238,8 @@ namespace geode {
|
|||
Result<> onParse(std::string const& key, std::string const& modID, matjson::Value const& json) override;
|
||||
|
||||
public:
|
||||
FloatSettingV3();
|
||||
|
||||
double getDefaultValue() const override;
|
||||
Result<> isValid(double value) const override;
|
||||
|
||||
|
@ -244,6 +272,8 @@ namespace geode {
|
|||
Result<> onParse(std::string const& key, std::string const& modID, matjson::Value const& json) override;
|
||||
|
||||
public:
|
||||
StringSettingV3();
|
||||
|
||||
std::string getDefaultValue() const override;
|
||||
Result<> isValid(std::string_view value) const override;
|
||||
|
||||
|
@ -269,6 +299,8 @@ namespace geode {
|
|||
Result<> onParse(std::string const& key, std::string const& modID, matjson::Value const& json) override;
|
||||
|
||||
public:
|
||||
FileSettingV3();
|
||||
|
||||
std::filesystem::path getDefaultValue() const override;
|
||||
Result<> isValid(std::filesystem::path const& value) const override;
|
||||
|
||||
|
@ -292,6 +324,8 @@ namespace geode {
|
|||
Result<> onParse(std::string const& key, std::string const& modID, matjson::Value const& json) override;
|
||||
|
||||
public:
|
||||
Color3BSettingV3();
|
||||
|
||||
cocos2d::ccColor3B getDefaultValue() const override;
|
||||
Result<> isValid(cocos2d::ccColor3B value) const override;
|
||||
|
||||
|
@ -313,6 +347,8 @@ namespace geode {
|
|||
Result<> onParse(std::string const& key, std::string const& modID, matjson::Value const& json) override;
|
||||
|
||||
public:
|
||||
Color4BSettingV3();
|
||||
|
||||
cocos2d::ccColor4B getDefaultValue() const override;
|
||||
Result<> isValid(cocos2d::ccColor4B value) const override;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define GEODE_PLATFORM_NAME "Windows"
|
||||
#define GEODE_PLATFORM_EXTENSION ".dll"
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER "win"
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER_NOARCH "win"
|
||||
#define CC_TARGET_OS_WIN32
|
||||
|
||||
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64) && !defined(__CYGWIN__)
|
||||
|
@ -47,6 +48,7 @@
|
|||
#define GEODE_PLATFORM_NAME "iOS"
|
||||
#define GEODE_PLATFORM_EXTENSION ".ios.dylib"
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER "ios"
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER_NOARCH "ios"
|
||||
#define CC_TARGET_OS_IPHONE
|
||||
#else
|
||||
#define GEODE_IOS(...)
|
||||
|
@ -54,6 +56,7 @@
|
|||
#define GEODE_IS_MACOS
|
||||
#define GEODE_IS_DESKTOP
|
||||
#define GEODE_PLATFORM_EXTENSION ".dylib"
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER_NOARCH "mac"
|
||||
#define CC_TARGET_OS_MAC
|
||||
|
||||
#if TARGET_CPU_ARM64
|
||||
|
@ -85,6 +88,7 @@
|
|||
#define GEODE_IS_MOBILE
|
||||
#define GEODE_CALL
|
||||
#define CC_TARGET_OS_ANDROID
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER_NOARCH "android"
|
||||
|
||||
#if defined(__arm__)
|
||||
#define GEODE_ANDROID32(...) __VA_ARGS__
|
||||
|
|
|
@ -321,7 +321,8 @@ namespace geode {
|
|||
try {
|
||||
return this->getJSONRef().template as<T>();
|
||||
}
|
||||
catch(matjson::JsonException const& e) {
|
||||
// matjson can throw variant exceptions too so you need to do this
|
||||
catch(std::exception const& e) {
|
||||
this->setError("invalid json type: {}", e);
|
||||
}
|
||||
return std::nullopt;
|
||||
|
|
|
@ -164,9 +164,7 @@ SettingValue* Mod::getSetting(std::string_view const key) const {
|
|||
}
|
||||
|
||||
std::shared_ptr<SettingV3> Mod::getSettingV3(std::string_view const key) const {
|
||||
auto sett = m_impl->m_settings->get(std::string(key));
|
||||
(void)file::writeString(".AAAAAk2", fmt::format("got it: {}, {}", key, fmt::ptr(sett)));
|
||||
return sett;
|
||||
return m_impl->m_settings->get(std::string(key));
|
||||
}
|
||||
|
||||
void Mod::registerCustomSetting(std::string_view const key, std::unique_ptr<SettingValue> value) {
|
||||
|
|
|
@ -125,8 +125,6 @@ Result<ModMetadata> ModMetadata::Impl::createFromSchemaV010(ModJson const& rawJs
|
|||
}
|
||||
catch (...) { }
|
||||
|
||||
return Ok(info);
|
||||
|
||||
auto root = checkJson(impl->m_rawJSON, checkerRoot);
|
||||
root.needs("geode").into(impl->m_geodeVersion);
|
||||
|
||||
|
@ -283,6 +281,7 @@ Result<ModMetadata> ModMetadata::Impl::createFromSchemaV010(ModJson const& rawJs
|
|||
impl->m_binaryName = impl->m_id + GEODE_PLATFORM_EXTENSION;
|
||||
|
||||
root.checkUnknownKeys();
|
||||
|
||||
return root.ok(info);
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ public:
|
|||
std::optional<std::string> enableIf;
|
||||
};
|
||||
|
||||
geode::detail::GeodeSettingBaseV3::GeodeSettingBaseV3() : m_impl(std::make_shared<Impl>()) {}
|
||||
|
||||
std::string geode::detail::GeodeSettingBaseV3::getName() const {
|
||||
return m_impl->name.value_or(this->getKey());
|
||||
}
|
||||
|
@ -77,7 +79,11 @@ std::optional<std::string> geode::detail::GeodeSettingBaseV3::getEnableIf() cons
|
|||
return m_impl->enableIf;
|
||||
}
|
||||
|
||||
Result<> geode::detail::GeodeSettingBaseV3::parseShared(JsonExpectedValue& json) {
|
||||
Result<> geode::detail::GeodeSettingBaseV3::parseSharedBase(JsonExpectedValue& json) {
|
||||
// Mark keys that have been checked before-hand
|
||||
json.needs("type");
|
||||
json.has("platforms");
|
||||
|
||||
json.has("name").into(m_impl->name);
|
||||
json.has("description").into(m_impl->description);
|
||||
json.has("enable-if").into(m_impl->enableIf);
|
||||
|
@ -94,6 +100,8 @@ public:
|
|||
std::string title;
|
||||
};
|
||||
|
||||
TitleSettingV3::TitleSettingV3() : m_impl(std::make_shared<Impl>()) {}
|
||||
|
||||
std::string TitleSettingV3::getTitle() const {
|
||||
return m_impl->title;
|
||||
}
|
||||
|
@ -126,6 +134,8 @@ void TitleSettingV3::reset() {}
|
|||
// replace this comment with it
|
||||
// put it riiiiiight here
|
||||
|
||||
UnresolvedCustomSettingV3::UnresolvedCustomSettingV3() : m_impl(std::make_shared<Impl>()) {}
|
||||
|
||||
Result<> UnresolvedCustomSettingV3::onParse(std::string const& key, std::string const& modID, matjson::Value const& json) {
|
||||
m_impl->json = json;
|
||||
return Ok();
|
||||
|
@ -167,6 +177,8 @@ public:
|
|||
bool defaultValue;
|
||||
};
|
||||
|
||||
BoolSettingV3::BoolSettingV3() : m_impl(std::make_shared<Impl>()) {}
|
||||
|
||||
bool& BoolSettingV3::getValueMut() const {
|
||||
return m_impl->value;
|
||||
}
|
||||
|
@ -181,8 +193,7 @@ Result<> BoolSettingV3::isValid(bool value) const {
|
|||
Result<> BoolSettingV3::onParse(std::string const& key, std::string const& modID, matjson::Value const& json) {
|
||||
auto root = checkJson(json, "BoolSettingV3");
|
||||
|
||||
GEODE_UNWRAP(this->parseShared(root));
|
||||
root.needs("default").into(m_impl->defaultValue);
|
||||
GEODE_UNWRAP(this->parseShared(root, m_impl->defaultValue));
|
||||
m_impl->value = m_impl->defaultValue;
|
||||
|
||||
root.checkUnknownKeys();
|
||||
|
@ -233,6 +244,8 @@ public:
|
|||
} controls;
|
||||
};
|
||||
|
||||
IntSettingV3::IntSettingV3() : m_impl(std::make_shared<Impl>()) {}
|
||||
|
||||
int64_t& IntSettingV3::getValueMut() const {
|
||||
return m_impl->value;
|
||||
}
|
||||
|
@ -282,8 +295,7 @@ bool IntSettingV3::isInputEnabled() const {
|
|||
Result<> IntSettingV3::onParse(std::string const& key, std::string const& modID, matjson::Value const& json) {
|
||||
auto root = checkJson(json, "IntSettingV3");
|
||||
|
||||
GEODE_UNWRAP(this->parseShared(root));
|
||||
root.needs("default").into(m_impl->defaultValue);
|
||||
GEODE_UNWRAP(this->parseShared(root, m_impl->defaultValue));
|
||||
m_impl->value = m_impl->defaultValue;
|
||||
|
||||
root.has("min").into(m_impl->minValue);
|
||||
|
@ -362,6 +374,8 @@ public:
|
|||
} controls;
|
||||
};
|
||||
|
||||
FloatSettingV3::FloatSettingV3() : m_impl(std::make_shared<Impl>()) {}
|
||||
|
||||
double& FloatSettingV3::getValueMut() const {
|
||||
return m_impl->value;
|
||||
}
|
||||
|
@ -411,8 +425,7 @@ bool FloatSettingV3::isInputEnabled() const {
|
|||
Result<> FloatSettingV3::onParse(std::string const& key, std::string const& modID, matjson::Value const& json) {
|
||||
auto root = checkJson(json, "FloatSettingV3");
|
||||
|
||||
GEODE_UNWRAP(this->parseShared(root));
|
||||
root.needs("default").into(m_impl->defaultValue);
|
||||
GEODE_UNWRAP(this->parseShared(root, m_impl->defaultValue));
|
||||
m_impl->value = m_impl->defaultValue;
|
||||
|
||||
root.has("min").into(m_impl->minValue);
|
||||
|
@ -483,6 +496,8 @@ public:
|
|||
std::optional<std::vector<std::string>> oneOf;
|
||||
};
|
||||
|
||||
StringSettingV3::StringSettingV3() : m_impl(std::make_shared<Impl>()) {}
|
||||
|
||||
std::string& StringSettingV3::getValueMut() const {
|
||||
return m_impl->value;
|
||||
}
|
||||
|
@ -517,8 +532,7 @@ std::optional<std::vector<std::string>> StringSettingV3::getEnumOptions() const
|
|||
Result<> StringSettingV3::onParse(std::string const& key, std::string const& modID, matjson::Value const& json) {
|
||||
auto root = checkJson(json, "StringSettingV3");
|
||||
|
||||
GEODE_UNWRAP(this->parseShared(root));
|
||||
root.needs("default").into(m_impl->defaultValue);
|
||||
GEODE_UNWRAP(this->parseShared(root, m_impl->defaultValue));
|
||||
m_impl->value = m_impl->defaultValue;
|
||||
|
||||
root.has("match").into(m_impl->match);
|
||||
|
@ -566,6 +580,8 @@ public:
|
|||
std::optional<std::vector<utils::file::FilePickOptions::Filter>> filters;
|
||||
};
|
||||
|
||||
FileSettingV3::FileSettingV3() : m_impl(std::make_shared<Impl>()) {}
|
||||
|
||||
std::filesystem::path& FileSettingV3::getValueMut() const {
|
||||
return m_impl->value;
|
||||
}
|
||||
|
@ -584,9 +600,7 @@ std::optional<std::vector<utils::file::FilePickOptions::Filter>> FileSettingV3::
|
|||
Result<> FileSettingV3::onParse(std::string const& key, std::string const& modID, matjson::Value const& json) {
|
||||
auto root = checkJson(json, "FileSettingV3");
|
||||
|
||||
GEODE_UNWRAP(this->parseShared(root));
|
||||
|
||||
root.needs("default").into(m_impl->defaultValue);
|
||||
GEODE_UNWRAP(this->parseShared(root, m_impl->defaultValue));
|
||||
|
||||
// Replace known paths like `{gd-save-dir}/`
|
||||
try {
|
||||
|
@ -655,6 +669,8 @@ public:
|
|||
ccColor3B defaultValue;
|
||||
};
|
||||
|
||||
Color3BSettingV3::Color3BSettingV3() : m_impl(std::make_shared<Impl>()) {}
|
||||
|
||||
ccColor3B& Color3BSettingV3::getValueMut() const {
|
||||
return m_impl->value;
|
||||
}
|
||||
|
@ -669,8 +685,7 @@ Result<> Color3BSettingV3::isValid(ccColor3B value) const {
|
|||
Result<> Color3BSettingV3::onParse(std::string const& key, std::string const& modID, matjson::Value const& json) {
|
||||
auto root = checkJson(json, "Color3BSettingV3");
|
||||
|
||||
GEODE_UNWRAP(this->parseShared(root));
|
||||
root.needs("default").into(m_impl->defaultValue);
|
||||
GEODE_UNWRAP(this->parseShared(root, m_impl->defaultValue));
|
||||
m_impl->value = m_impl->defaultValue;
|
||||
|
||||
root.checkUnknownKeys();
|
||||
|
@ -710,6 +725,8 @@ public:
|
|||
ccColor4B defaultValue;
|
||||
};
|
||||
|
||||
Color4BSettingV3::Color4BSettingV3() : m_impl(std::make_shared<Impl>()) {}
|
||||
|
||||
ccColor4B& Color4BSettingV3::getValueMut() const {
|
||||
return m_impl->value;
|
||||
}
|
||||
|
@ -724,8 +741,7 @@ Result<> Color4BSettingV3::isValid(ccColor4B value) const {
|
|||
Result<> Color4BSettingV3::onParse(std::string const& key, std::string const& modID, matjson::Value const& json) {
|
||||
auto root = checkJson(json, "Color4BSettingV3");
|
||||
|
||||
GEODE_UNWRAP(this->parseShared(root));
|
||||
root.needs("default").into(m_impl->defaultValue);
|
||||
GEODE_UNWRAP(this->parseShared(root, m_impl->defaultValue));
|
||||
m_impl->value = m_impl->defaultValue;
|
||||
|
||||
root.checkUnknownKeys();
|
||||
|
|
|
@ -320,6 +320,7 @@ JsonExpectedValue JsonExpectedValue::has(std::string_view key) {
|
|||
if (!this->assertIs(matjson::Type::Object)) {
|
||||
return JsonExpectedValue();
|
||||
}
|
||||
m_impl->knownKeys.insert(std::string(key));
|
||||
if (!m_impl->scope.contains(key)) {
|
||||
return JsonExpectedValue();
|
||||
}
|
||||
|
@ -332,6 +333,7 @@ JsonExpectedValue JsonExpectedValue::needs(std::string_view key) {
|
|||
if (!this->assertIs(matjson::Type::Object)) {
|
||||
return JsonExpectedValue();
|
||||
}
|
||||
m_impl->knownKeys.insert(std::string(key));
|
||||
if (!m_impl->scope.contains(key)) {
|
||||
this->setError("missing required key {}", key);
|
||||
return JsonExpectedValue();
|
||||
|
@ -352,8 +354,9 @@ std::vector<std::pair<std::string, JsonExpectedValue>> JsonExpectedValue::proper
|
|||
return res;
|
||||
}
|
||||
void JsonExpectedValue::checkUnknownKeys() {
|
||||
for (auto& [key, _] : this->properties()) {
|
||||
if (!m_impl->knownKeys.count(key)) {
|
||||
if (this->hasError()) return;
|
||||
for (auto&& [key, _] : this->properties()) {
|
||||
if (!m_impl->knownKeys.contains(key)) {
|
||||
log::warn("{} contains unknown key \"{}\"", m_impl->scopeName, key);
|
||||
}
|
||||
}
|
||||
|
@ -401,7 +404,8 @@ std::vector<JsonExpectedValue> JsonExpectedValue::items() {
|
|||
}
|
||||
|
||||
JsonExpectedValue::operator bool() const {
|
||||
return !this->hasError();
|
||||
// The shared check is because null values should evaluate to false so `obj.has("key")` evaluates to false
|
||||
return m_impl->shared && !this->hasError();
|
||||
}
|
||||
|
||||
Result<> JsonExpectedValue::ok() {
|
||||
|
|
Loading…
Reference in a new issue