Compare commits

..

No commits in common. "108721dd3ff36287d725acbd994db123501c7fb2" and "088eddbb7b7c381089dcefb517506b3699f349db" have entirely different histories.

31 changed files with 282 additions and 188 deletions

View file

@ -189,8 +189,8 @@ include(cmake/Platform.cmake)
include(cmake/GeodeFile.cmake)
if (NOT DEFINED GEODE_GD_VERSION)
set(GEODE_GD_VERSION 2.207)
set(GEODE_COMP_GD_VERSION 22070)
set(GEODE_GD_VERSION 2.206)
set(GEODE_COMP_GD_VERSION 22060)
endif()
target_compile_definitions(
@ -236,8 +236,8 @@ if (ANDROID)
endif()
set(MAT_JSON_AS_INTERFACE ON)
CPMAddPackage("gh:geode-sdk/json#1b182dd")
CPMAddPackage("gh:geode-sdk/result@1.1.0")
CPMAddPackage("gh:geode-sdk/json#cda9807")
CPMAddPackage("gh:geode-sdk/result@1.0.1")
CPMAddPackage("gh:fmtlib/fmt#10.2.1")
target_compile_definitions(${PROJECT_NAME} INTERFACE MAT_JSON_DYNAMIC=1)

View file

@ -41,7 +41,7 @@
#include <Geode/utils/casts.hpp>
#ifndef GEODE_IS_MEMBER_TEST
#include <matjson3.hpp>
#include <matjson.hpp>
#endif
namespace geode {

View file

@ -2,7 +2,7 @@
#include "../DefaultInclude.hpp"
#include "../utils/general.hpp"
#include <matjson3.hpp>
#include <matjson.hpp>
#include "Tulip.hpp"
#include <cinttypes>
#include <string_view>

View file

@ -3,7 +3,7 @@
#include "Event.hpp"
#include "Loader.hpp"
#include "Mod.hpp"
#include <matjson3.hpp>
#include <matjson.hpp>
namespace geode::ipc {
#ifdef GEODE_IS_WINDOWS

View file

@ -8,7 +8,7 @@
#include "Types.hpp"
#include <atomic>
#include <matjson3.hpp>
#include <matjson.hpp>
#include <mutex>
#include <optional>
#include <string_view>
@ -121,17 +121,22 @@ namespace geode {
* @param name The argument name
*/
template <class T>
Result<T, std::string_view> parseLaunchArgument(std::string_view const name) const {
std::optional<T> parseLaunchArgument(std::string_view const name) const {
auto str = this->getLaunchArgument(name);
if (!str.has_value()) {
return Err("Launch argument '{}' not found", name);
return std::nullopt;
}
auto jsonOpt = matjson::Value::parse(str.value());
if (jsonOpt.isErr()) {
return Err("Parsing launch argument '{}' failed: {}", name, jsonOpt.unwrapErr());
std::string parseError;
auto jsonOpt = matjson::parse(str.value(), parseError);
if (!jsonOpt.has_value()) {
log::debug("Parsing launch argument '{}' failed: {}", name, parseError);
return std::nullopt;
}
auto value = jsonOpt.unwrap();
return value.template as<T>();
auto value = jsonOpt.value();
if (!value.is<T>()) {
return std::nullopt;
}
return value.as<T>();
}
void queueInMainThread(ScheduledFunction&& func);

View file

@ -7,7 +7,7 @@
#include <ccTypes.h>
#include <chrono>
#include <filesystem>
#include <matjson3.hpp>
#include <matjson.hpp>
#include <type_traits>
#include <fmt/core.h>
// for formatting std::vector and such
@ -65,6 +65,12 @@ namespace std::filesystem {
}
}
namespace matjson {
GEODE_INLINE GEODE_HIDDEN std::string format_as(matjson::Value const& value) {
return value.dump(matjson::NO_INDENTATION);
}
}
namespace geode {
class Mod;

View file

@ -13,7 +13,7 @@
#include "Types.hpp"
#include "Loader.hpp"
#include <matjson3.hpp>
#include <matjson.hpp>
#include <matjson/stl_serialize.hpp>
#include <optional>
#include <string_view>
@ -51,6 +51,22 @@ namespace geode {
return action == ModRequestedAction::Uninstall || action == ModRequestedAction::UninstallWithSaveData;
}
template <class T>
static consteval bool typeImplementsIsJSON() {
using namespace matjson;
if constexpr (requires(const Value& json) { Serialize<std::decay_t<T>>::is_json(json); })
return true;
if constexpr (std::is_same_v<T, Value>) return true;
if constexpr (std::is_same_v<T, Array>) return true;
if constexpr (std::is_same_v<T, Object>) return true;
if constexpr (std::is_constructible_v<std::string, T>) return true;
if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) return true;
if constexpr (std::is_same_v<T, bool>) return true;
if constexpr (std::is_same_v<T, std::nullptr_t>) return true;
return false;
}
GEODE_HIDDEN Mod* takeNextLoaderMod();
class ModImpl;
@ -248,24 +264,26 @@ namespace geode {
template <class T>
T getSavedValue(std::string_view const key) {
static_assert(geode::typeImplementsIsJSON<T>(), "T must implement is_json in matjson::Serialize<T>, otherwise this always returns default value.");
auto& saved = this->getSaveContainer();
if (auto res = saved.get(key).andThen([](auto&& v) {
return v.template as<T>();
}); res.isOk()) {
return res.unwrap();
if (saved.contains(key)) {
if (auto value = saved.try_get<T>(key)) {
return *value;
}
}
return T();
}
template <class T>
T getSavedValue(std::string_view const key, T const& defaultValue) {
static_assert(geode::typeImplementsIsJSON<T>(), "T must implement is_json in matjson::Serialize<T>, otherwise this always returns default value.");
auto& saved = this->getSaveContainer();
if (auto res = saved.get(key).andThen([](auto&& v) {
return v.template as<T>();
}); res.isOk()) {
return res.unwrap();
if (saved.contains(key)) {
if (auto value = saved.try_get<T>(key)) {
return *value;
}
saved[key] = matjson::Value(defaultValue);
}
saved[key] = defaultValue;
return defaultValue;
}

View file

@ -4,7 +4,7 @@
#include "../utils/VersionInfo.hpp"
#include "Types.hpp"
#include <matjson3.hpp>
#include <matjson.hpp>
#include <memory>
namespace geode {
@ -290,8 +290,7 @@ namespace geode {
template <>
struct matjson::Serialize<geode::ModMetadata> {
static Value toJson(geode::ModMetadata const& value)
{
return Value(value.toJSON());
static matjson::Value to_json(geode::ModMetadata const& info) {
return info.toJSON();
}
};

View file

@ -306,15 +306,14 @@ namespace geode {
}
bool load(matjson::Value const& json) override {
auto res = json.as<T>();
if (res.isErr()) {
return false;
}
m_impl->value = res.unwrap();
if (json.is<T>()) {
m_impl->value = json.as<T>();
return true;
}
return false;
}
bool save(matjson::Value& json) const override {
json = matjson::Value(m_impl->value);
json = m_impl->value;
return true;
}
};

View file

@ -2,7 +2,7 @@
#include "../DefaultInclude.hpp"
#include "../platform/cplatform.h"
#include <matjson3.hpp>
#include <matjson.hpp>
#include <string>

View file

@ -1,6 +1,6 @@
#pragma once
#include <matjson3.hpp>
#include <matjson.hpp>
#include "../loader/Log.hpp"
#include <set>
#include <variant>
@ -104,15 +104,22 @@ namespace geode {
return this->getJSONRef();
}
else {
auto res = this->getJSONRef().as<T>();
if (res) {
return res.unwrap();
try {
if (this->getJSONRef().is<T>()) {
return this->getJSONRef().as<T>();
}
else {
this->setError(
"unexpected type {}",
this->matJsonTypeToString(this->getJSONRef().type())
);
}
}
// matjson can throw variant exceptions too so you need to do this
catch(std::exception const& e) {
this->setError("unable to parse json: {}", e);
}
}
return std::nullopt;
}

View file

@ -2,7 +2,7 @@
#include "../DefaultInclude.hpp"
#include <string_view>
#include <matjson3.hpp>
#include <matjson.hpp>
#include <tuple>
#include <Geode/Result.hpp>
@ -256,17 +256,25 @@ namespace geode {
template <class V>
requires std::is_same_v<V, geode::VersionInfo> || std::is_same_v<V, geode::ComparableVersionInfo>
struct matjson::Serialize<V> {
static geode::Result<V, std::string> fromJson(Value const& value)
{
auto str = GEODE_UNWRAP(value.asString());
auto version = GEODE_UNWRAP(V::parse(str).mapErr([](auto&& err) {
return geode::Err("Invalid version format: {}", err);
}));
return geode::Ok(version);
static matjson::Value to_json(V const& info) {
return info.toString();
}
static Value toJson(V const& value)
{
return Value(value.toString());
static bool is_json(matjson::Value const& json) {
if (json.is_string()) {
auto ver = V::parse(json.as_string());
return !ver.isErr();
}
return false;
}
static V from_json(matjson::Value const& json) {
auto ver = V::parse(json.as_string());
if (!ver) {
throw matjson::JsonException(
"Invalid version format: " + ver.unwrapErr()
);
}
return ver.unwrap();
}
};

View file

@ -1,6 +1,6 @@
#pragma once
#include <matjson3.hpp>
#include <matjson.hpp>
#include "casts.hpp"
#include "general.hpp"
#include "../DefaultInclude.hpp"
@ -15,14 +15,16 @@
template <>
struct matjson::Serialize<cocos2d::ccColor3B> {
static geode::Result<cocos2d::ccColor3B, std::string> fromJson(Value const& value);
static Value toJson(cocos2d::ccColor3B const& value);
static matjson::Value GEODE_DLL to_json(cocos2d::ccColor3B const& color);
static cocos2d::ccColor3B GEODE_DLL from_json(matjson::Value const& color);
static bool GEODE_DLL is_json(matjson::Value const& json);
};
template <>
struct matjson::Serialize<cocos2d::ccColor4B> {
static geode::Result<cocos2d::ccColor4B, std::string> fromJson(Value const& value);
static Value toJson(cocos2d::ccColor4B const& value);
static matjson::Value GEODE_DLL to_json(cocos2d::ccColor4B const& color);
static cocos2d::ccColor4B GEODE_DLL from_json(matjson::Value const& color);
static bool GEODE_DLL is_json(matjson::Value const& json);
};
// operators for CC geometry

View file

@ -5,7 +5,7 @@
#include "../loader/Event.hpp"
#include "Task.hpp"
#include <matjson3.hpp>
#include <matjson.hpp>
#include <Geode/DefaultInclude.hpp>
#include <filesystem>
#include <string>
@ -13,15 +13,14 @@
template <>
struct matjson::Serialize<std::filesystem::path> {
static geode::Result<std::filesystem::path, std::string> fromJson(Value const& value)
{
auto str = GEODE_UNWRAP(value.asString());
return geode::Ok(std::filesystem::path(str).make_preferred());
static matjson::Value to_json(std::filesystem::path const& path) {
return path.string();
}
static Value toJson(std::filesystem::path const& value)
{
return Value(value.string());
static std::filesystem::path from_json(matjson::Value const& value) {
return std::filesystem::path(value.as_string()).make_preferred();
}
static bool is_json(matjson::Value const& value) {
return value.is_string();
}
};
@ -33,7 +32,10 @@ namespace geode::utils::file {
template <class T>
Result<T> readFromJson(std::filesystem::path const& file) {
GEODE_UNWRAP_INTO(auto json, readJson(file));
return json.as<T>();
if (!json.is<T>()) {
return Err("JSON is not of type {}", typeid(T).name());
}
return Ok(json.as<T>());
}
GEODE_DLL Result<> writeString(std::filesystem::path const& path, std::string const& data);

View file

@ -9,7 +9,7 @@
#include <string>
#include <vector>
#include <filesystem>
#include <matjson3.hpp>
#include <matjson.hpp>
#include <charconv>
#include <clocale>
#include <type_traits>
@ -170,8 +170,7 @@ namespace geode {
template<>
struct matjson::Serialize<geode::ByteVector> {
static Value toJson(geode::ByteVector const& bytes)
{
static matjson::Value to_json(geode::ByteVector const& bytes) {
return matjson::Array(bytes.begin(), bytes.end());
}
};

View file

@ -1,7 +1,7 @@
#pragma once
#include <Geode/loader/Loader.hpp> // another great circular dependency fix
#include <matjson3.hpp>
#include <matjson.hpp>
#include <Geode/Result.hpp>
#include "Task.hpp"
#include <chrono>

View file

@ -1,6 +1,6 @@
#include <Geode/loader/IPC.hpp>
#include "IPC.hpp"
#include <matjson3.hpp>
#include <matjson.hpp>
#include <Geode/loader/Mod.hpp>
using namespace geode::prelude;
@ -33,18 +33,19 @@ ipc::IPCFilter::IPCFilter(std::string const& modID, std::string const& messageID
matjson::Value ipc::processRaw(void* rawHandle, std::string const& buffer) {
matjson::Value reply;
auto res = matjson::Value::parse(buffer);
std::string error;
auto res = matjson::parse(buffer, error);
if (error.size() > 0) {
log::warn("Received IPC message that isn't valid JSON: {}", res.unwrapErr());
log::warn("Received IPC message that isn't valid JSON: {}", error);
return reply;
}
matjson::Value json = res.unwrap();
matjson::Value json = res.value();
if (!json.contains("mod") || !json["mod"].isString()) {
if (!json.contains("mod") || !json["mod"].is_string()) {
log::warn("Received IPC message without 'mod' field");
return reply;
}
if (!json.contains("message") || !json["message"].isString()) {
if (!json.contains("message") || !json["message"].is_string()) {
log::warn("Received IPC message without 'message' field");
return reply;
}
@ -54,6 +55,6 @@ matjson::Value ipc::processRaw(void* rawHandle, std::string const& buffer) {
}
// log::debug("Posting IPC event");
// ! warning: if the event system is ever made asynchronous this will break!
IPCEvent(rawHandle, json["mod"].asString().unwrap(), json["message"].asString().unwrap(), data, reply).post();
IPCEvent(rawHandle, json["mod"].as_string(), json["message"].as_string(), data, reply).post();
return reply;
}

View file

@ -1,7 +1,7 @@
#pragma once
#include <string>
#include <matjson3.hpp>
#include <matjson.hpp>
namespace geode::ipc {
void setup();

View file

@ -2,7 +2,7 @@
#include "FileWatcher.hpp"
#include <matjson3.hpp>
#include <matjson.hpp>
#include <Geode/loader/Dirs.hpp>
#include <Geode/loader/Loader.hpp>
#include <Geode/loader/Log.hpp>

View file

@ -1,6 +1,6 @@
#pragma once
#include <matjson3.hpp>
#include <matjson.hpp>
#include "ModPatch.hpp"
#include <Geode/loader/Loader.hpp>
#include <string_view>
@ -47,7 +47,7 @@ namespace geode {
/**
* Saved values
*/
matjson::Value m_saved = matjson::Value();
matjson::Value m_saved = matjson::Object();
/**
* Setting values. This is behind unique_ptr for interior mutability
*/

View file

@ -5,7 +5,7 @@
#include <Geode/utils/string.hpp>
#include <Geode/utils/general.hpp>
#include <about.hpp>
#include <matjson3.hpp>
#include <matjson.hpp>
#include <utility>
#include <clocale>

View file

@ -74,44 +74,52 @@ namespace geode {
template <>
struct matjson::Serialize<geode::ModMetadata::Dependency::Importance> {
static geode::Result<geode::ModMetadata::Dependency::Importance, std::string> fromJson(Value const& value)
{
auto str = GEODE_UNWRAP(value.asString());
if (str == "required") return geode::Ok(geode::ModMetadata::Dependency::Importance::Required);
if (str == "recommended") return geode::Ok(geode::ModMetadata::Dependency::Importance::Recommended);
if (str == "suggested") return geode::Ok(geode::ModMetadata::Dependency::Importance::Suggested);
return geode::Err("Invalid importance");
static matjson::Value GEODE_DLL to_json(geode::ModMetadata::Dependency::Importance const& importance) {
switch (importance) {
case geode::ModMetadata::Dependency::Importance::Required: return {"required"};
case geode::ModMetadata::Dependency::Importance::Recommended: return {"recommended"};
case geode::ModMetadata::Dependency::Importance::Suggested: return {"suggested"};
default: return {"unknown"};
}
}
static geode::ModMetadata::Dependency::Importance GEODE_DLL from_json(matjson::Value const& importance) {
auto impStr = importance.as_string();
if (impStr == "required")
return geode::ModMetadata::Dependency::Importance::Required;
if (impStr == "recommended")
return geode::ModMetadata::Dependency::Importance::Recommended;
if (impStr == "suggested")
return geode::ModMetadata::Dependency::Importance::Suggested;
throw matjson::JsonException(R"(Expected importance to be "required", "recommended" or "suggested")");
}
static Value toJson(geode::ModMetadata::Dependency::Importance const& value)
{
switch (value) {
case geode::ModMetadata::Dependency::Importance::Required: return "required";
case geode::ModMetadata::Dependency::Importance::Recommended: return "recommended";
case geode::ModMetadata::Dependency::Importance::Suggested: return "suggested";
}
return "unknown";
static bool is_json(matjson::Value const& value) {
return value.is_string();
}
};
template <>
struct matjson::Serialize<geode::ModMetadata::Incompatibility::Importance> {
static geode::Result<geode::ModMetadata::Incompatibility::Importance, std::string> fromJson(Value const& value)
{
auto str = GEODE_UNWRAP(value.asString());
if (str == "breaking") return geode::Ok(geode::ModMetadata::Incompatibility::Importance::Breaking);
if (str == "conflicting") return geode::Ok(geode::ModMetadata::Incompatibility::Importance::Conflicting);
if (str == "superseded") return geode::Ok(geode::ModMetadata::Incompatibility::Importance::Superseded);
return geode::Err("Invalid importance");
static matjson::Value GEODE_DLL to_json(geode::ModMetadata::Incompatibility::Importance const& importance) {
switch (importance) {
case geode::ModMetadata::Incompatibility::Importance::Breaking: return {"breaking"};
case geode::ModMetadata::Incompatibility::Importance::Conflicting: return {"conflicting"};
case geode::ModMetadata::Incompatibility::Importance::Superseded: return {"superseded"};
default: return {"unknown"};
}
}
static geode::ModMetadata::Incompatibility::Importance GEODE_DLL from_json(matjson::Value const& importance) {
auto impStr = importance.as_string();
if (impStr == "breaking")
return geode::ModMetadata::Incompatibility::Importance::Breaking;
if (impStr == "conflicting")
return geode::ModMetadata::Incompatibility::Importance::Conflicting;
if (impStr == "superseded")
return geode::ModMetadata::Incompatibility::Importance::Superseded;
throw matjson::JsonException(R"(Expected importance to be "breaking", "conflicting", or "superseded")");
}
static Value toJson(geode::ModMetadata::Incompatibility::Importance const& value)
{
switch (value) {
case geode::ModMetadata::Incompatibility::Importance::Breaking: return "breaking";
case geode::ModMetadata::Incompatibility::Importance::Conflicting: return "conflicting";
case geode::ModMetadata::Incompatibility::Importance::Superseded: return "superseded";
}
return "unknown";
static bool is_json(matjson::Value const& value) {
return value.is_string();
}
};

View file

@ -1,7 +1,7 @@
#pragma once
#include <string>
#include <matjson3.hpp>
#include <matjson.hpp>
#include <Geode/loader/Event.hpp>
namespace geode::updater {

View file

@ -32,7 +32,6 @@ static auto const& getGDVersionTimestampMap() {
{ 1704948277, "2.203" },
{ 1705041028, "2.204" },
{ 1717243515, "2.206" },
{ 1731098609, "2.207" },
};
return map;
}

View file

@ -4,7 +4,7 @@
#include <Geode/DefaultInclude.hpp>
#include <Geode/utils/web.hpp>
#include <chrono>
#include <matjson3.hpp>
#include <matjson.hpp>
#include <vector>
using namespace geode::prelude;

View file

@ -4,7 +4,7 @@
#include <Geode/utils/VersionInfo.hpp>
#include <Geode/utils/general.hpp>
#include <matjson3.hpp>
#include <matjson.hpp>
using namespace geode::prelude;

View file

@ -1,82 +1,123 @@
#include <Geode/modify/LoadingLayer.hpp>
#include <Geode/utils/cocos.hpp>
#include <matjson3.hpp>
#include <matjson.hpp>
#include <charconv>
#include <Geode/binding/CCTextInputNode.hpp>
#include <Geode/binding/GameManager.hpp>
using namespace geode::prelude;
Result<cocos2d::ccColor3B, std::string> matjson::Serialize<ccColor3B>::fromJson(matjson::Value const& value) {
if (value.isArray()) {
auto arr = GEODE_UNWRAP(value.asArray());
if (arr.size() == 3) {
auto r = GEODE_UNWRAP(arr[0].asInt());
auto g = GEODE_UNWRAP(arr[1].asInt());
auto b = GEODE_UNWRAP(arr[2].asInt());
return Ok(cocos2d::ccc3(r, g, b));
bool matjson::Serialize<ccColor3B>::is_json(matjson::Value const& json) {
if (json.is_array()) {
return json.as_array().size() == 3;
}
return Err("Expected color array to have 3 items");
if (json.is_object()) {
return json.contains("r") && json.contains("g") && json.contains("b");
}
if (value.isObject()) {
auto r = GEODE_UNWRAP(GEODE_UNWRAP(value.get("r")).asInt());
auto g = GEODE_UNWRAP(GEODE_UNWRAP(value.get("g")).asInt());
auto b = GEODE_UNWRAP(GEODE_UNWRAP(value.get("b")).asInt());
return Ok(cocos2d::ccc3(r, g, b));
if (json.is_string()) {
return !cc3bFromHexString(json.as_string()).isErr();
}
if (value.isString()) {
auto hex = GEODE_UNWRAP(value.asString());
auto res = cc3bFromHexString(hex);
if (!res) {
return Err("Invalid hex color string: {}", res.unwrapErr());
}
return Ok(res.unwrap());
}
}
matjson::Value matjson::Serialize<ccColor3B>::toJson(cocos2d::ccColor3B const& value) {
return matjson::makeObject({
{ "r", value.r },
{ "g", value.g },
{ "b", value.b }
});
return false;
}
Result<cocos2d::ccColor4B, std::string> matjson::Serialize<ccColor4B>::fromJson(matjson::Value const& value) {
if (value.isArray()) {
auto arr = GEODE_UNWRAP(value.asArray());
if (arr.size() == 4) {
auto r = GEODE_UNWRAP(arr[0].asInt());
auto g = GEODE_UNWRAP(arr[1].asInt());
auto b = GEODE_UNWRAP(arr[2].asInt());
auto a = GEODE_UNWRAP(arr[3].asInt());
return Ok(cocos2d::ccc4(r, g, b, a));
}
return Err("Expected color array to have 4 items");
}
if (value.isObject()) {
auto r = GEODE_UNWRAP(GEODE_UNWRAP(value.get("r")).asInt());
auto g = GEODE_UNWRAP(GEODE_UNWRAP(value.get("g")).asInt());
auto b = GEODE_UNWRAP(GEODE_UNWRAP(value.get("b")).asInt());
auto a = GEODE_UNWRAP(GEODE_UNWRAP(value.get("a")).asInt());
return Ok(cocos2d::ccc4(r, g, b, a));
}
if (value.isString()) {
auto hex = GEODE_UNWRAP(value.asString());
auto res = cc4bFromHexString(hex);
if (!res) {
return Err("Invalid hex color string: {}", res.unwrapErr());
}
return Ok(res.unwrap());
}
matjson::Value matjson::Serialize<ccColor3B>::to_json(ccColor3B const& color) {
return matjson::Object {
{ "r", color.r },
{ "g", color.g },
{ "b", color.b }
};
}
matjson::Value matjson::Serialize<ccColor4B>::toJson(cocos2d::ccColor4B const& value) {
return matjson::makeObject({
{ "r", value.r },
{ "g", value.g },
{ "b", value.b },
{ "a", value.a }
});
ccColor3B matjson::Serialize<ccColor3B>::from_json(matjson::Value const& json) {
ccColor3B color;
// array
if (json.is_array()) {
if (json.as_array().size() == 3) {
color.r = json[0].as_int();
color.g = json[1].as_int();
color.b = json[2].as_int();
}
else {
throw matjson::JsonException("Expected color array to have 3 items");
}
}
// object
else if (json.is_object()) {
color.r = json["r"].as_int();
color.g = json["g"].as_int();
color.b = json["b"].as_int();
}
// hex string
else if (json.is_string()) {
auto c = cc3bFromHexString(json.as_string());
if (!c) {
throw matjson::JsonException("Invalid color hex string");
}
color = c.unwrap();
}
// bad
else {
throw matjson::JsonException("Expected color to be array, object or hex string");
}
return color;
}
bool matjson::Serialize<ccColor4B>::is_json(matjson::Value const& json) {
if (json.is_array()) {
return json.as_array().size() == 4;
}
if (json.is_object()) {
return json.contains("r") && json.contains("g") && json.contains("b") && json.contains("a");
}
if (json.is_string()) {
return !cc4bFromHexString(json.as_string()).isErr();
}
return false;
}
matjson::Value matjson::Serialize<ccColor4B>::to_json(ccColor4B const& color) {
return matjson::Object {
{ "r", color.r },
{ "g", color.g },
{ "b", color.b },
{ "a", color.a }
};
}
ccColor4B matjson::Serialize<ccColor4B>::from_json(matjson::Value const& json) {
ccColor4B color;
// array
if (json.is_array()) {
if (json.as_array().size() == 4) {
color.r = json[0].as_int();
color.g = json[1].as_int();
color.b = json[2].as_int();
color.a = json[3].as_int();
}
else {
throw matjson::JsonException("Expected color array to have 4 items");
}
}
// object
else if (json.is_object()) {
color.r = json["r"].as_int();
color.g = json["g"].as_int();
color.b = json["b"].as_int();
color.a = json["a"].as_int();
}
// hex string
else if (json.is_string()) {
auto c = cc4bFromHexString(json.as_string());
if (!c) {
throw matjson::JsonException("Invalid color hex string: " + c.unwrapErr());
}
color = c.unwrap();
}
// bad
else {
throw matjson::JsonException("Expected color to be array, object or hex string");
}
return color;
}
Result<ccColor3B> geode::cocos::cc3bFromHexString(std::string const& rawHexValue, bool permissive) {

View file

@ -3,7 +3,7 @@
#include <Geode/utils/file.hpp>
#include <Geode/utils/map.hpp>
#include <Geode/utils/string.hpp>
#include <matjson3.hpp>
#include <matjson.hpp>
#include <fstream>
#include <mz.h>
#include <mz_os.h>

View file

@ -3,7 +3,7 @@
#include <filesystem>
#include <fmt/core.h>
#include <fstream>
#include <matjson3.hpp>
#include <matjson.hpp>
#include <system_error>
#define CURL_STATICLIB
#include <curl/curl.h>

View file

@ -54,7 +54,7 @@ struct $modify(MenuLayer) {
log::popNest();
log::info("Mod has launch arg 'mod-arg': {}", Mod::get()->hasLaunchArgument("mod-arg"));
log::info("Loader flag 'bool-arg': {}", Loader::get()->getLaunchFlag("bool-arg"));
log::info("Loader int 'int-arg': {}", Loader::get()->parseLaunchArgument<int>("int-arg").unwrapOr(0));
log::info("Loader int 'int-arg': {}", Loader::get()->parseLaunchArgument<int>("int-arg"));
log::popNest();
return true;