mirror of
https://github.com/geode-sdk/geode.git
synced 2025-03-24 03:39:56 -04:00
remove old Result + move everything over to new Result
This commit is contained in:
parent
5b3fb508e3
commit
63749320a3
30 changed files with 504 additions and 684 deletions
loader
include/Geode
src
hooks
index
internal
load
ui
internal
dev
info
list
settings
nodes
utils
|
@ -47,7 +47,7 @@ namespace geode::core {
|
|||
|
||||
inline Result<> remove(HookHandle const& handle) {
|
||||
impl::removeHook(handle);
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -81,7 +81,7 @@ namespace geode {
|
|||
#define GEODE_INT_PARSE_SETTING_IMPL(obj, func, ...) \
|
||||
if constexpr (std::is_base_of_v<__VA_ARGS__, Class>) { \
|
||||
auto r = std::static_pointer_cast<Class>(res)->func(obj); \
|
||||
if (!r) return Err(r.error()); \
|
||||
if (!r) return Err(r.unwrapErr()); \
|
||||
}
|
||||
|
||||
#define GEODE_INT_CONSTRAIN_SETTING_CAN_IMPL(func, ...) \
|
||||
|
|
|
@ -1,277 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "../DefaultInclude.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
|
||||
namespace geode {
|
||||
namespace {
|
||||
struct AnyType {
|
||||
explicit AnyType() = delete;
|
||||
};
|
||||
|
||||
template <class V, class RV>
|
||||
concept ConvertibleToResult =
|
||||
std::is_convertible_v<std::remove_reference_t<V>, std::remove_reference_t<RV>> ||
|
||||
std::is_same_v<std::remove_reference_t<V>, std::remove_reference_t<RV>>;
|
||||
|
||||
using DefaultValue = std::monostate;
|
||||
using DefaultError = std::string;
|
||||
}
|
||||
|
||||
template <class T = DefaultValue, class E = DefaultError>
|
||||
class [[nodiscard]] NewResult {
|
||||
public:
|
||||
using value_type = std::remove_reference_t<T>;
|
||||
using error_type = std::remove_reference_t<E>;
|
||||
|
||||
// for some reason doing requires causes errors with pch...
|
||||
static_assert(
|
||||
std::is_copy_constructible_v<value_type> || std::is_move_constructible_v<value_type>,
|
||||
"T must be copiable or movable!"
|
||||
);
|
||||
static_assert(
|
||||
std::is_copy_constructible_v<error_type> || std::is_move_constructible_v<error_type>,
|
||||
"E must be copiable or movable!"
|
||||
);
|
||||
|
||||
protected:
|
||||
std::variant<value_type, error_type> m_value;
|
||||
|
||||
public:
|
||||
bool isOk() const {
|
||||
return std::holds_alternative<value_type>(m_value);
|
||||
}
|
||||
|
||||
bool isErr() const {
|
||||
return std::holds_alternative<error_type>(m_value);
|
||||
}
|
||||
|
||||
explicit NewResult(value_type const& value
|
||||
) requires std::is_copy_constructible_v<value_type> : m_value(value) {}
|
||||
|
||||
explicit NewResult(value_type&& value) requires std::is_move_constructible_v<value_type> :
|
||||
m_value(std::forward<value_type>(value)) {}
|
||||
|
||||
explicit NewResult(error_type const& value
|
||||
) requires std::is_copy_constructible_v<error_type> : m_value(value) {}
|
||||
|
||||
explicit NewResult(error_type&& value) requires std::is_move_constructible_v<error_type> :
|
||||
m_value(std::forward<error_type>(value)) {}
|
||||
|
||||
NewResult(NewResult<T, E> const& other) requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type>
|
||||
= default;
|
||||
|
||||
NewResult(NewResult<T, E>&& other
|
||||
) requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) =
|
||||
default;
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, E> NewResult(
|
||||
NewResult<T2, E2> const& other
|
||||
)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type> :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()) {}
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, E> NewResult(
|
||||
NewResult<T2, E2>&& other
|
||||
)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> NewResult(NewResult<T2, AnyType> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type> : NewResult(value_type(other.unwrap())) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, E> NewResult(NewResult<AnyType, E2> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type> :
|
||||
m_value(std::forward<E2>(other.unwrapErr())) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> NewResult(NewResult<T2, AnyType>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) :
|
||||
m_value(other.unwrap()) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, E> NewResult(NewResult<AnyType, E2>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) :
|
||||
NewResult(std::forward<error_type>(other.unwrapErr())) {}
|
||||
|
||||
value_type unwrap() const requires std::is_copy_constructible_v<value_type> {
|
||||
return std::get<value_type>(m_value);
|
||||
}
|
||||
|
||||
value_type&& unwrap() requires(!std::is_copy_constructible_v<value_type>) {
|
||||
return std::move(std::get<value_type>(m_value));
|
||||
}
|
||||
|
||||
error_type unwrapErr() const requires std::is_copy_constructible_v<error_type> {
|
||||
return std::get<error_type>(m_value);
|
||||
}
|
||||
|
||||
error_type&& unwrapErr() requires(!std::is_copy_constructible_v<error_type>) {
|
||||
return std::move(std::get<error_type>(m_value));
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
requires(!std::is_same_v<T, bool> && !std::is_same_v<E, bool>) {
|
||||
return this->isOk();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class [[nodiscard]] NewResult<T, T> {
|
||||
public:
|
||||
using value_type = std::remove_reference_t<T>;
|
||||
using error_type = std::remove_reference_t<T>;
|
||||
|
||||
// for some reason doing requires causes errors with pch...
|
||||
static_assert(
|
||||
std::is_copy_constructible_v<value_type> || std::is_move_constructible_v<value_type>,
|
||||
"T must be copiable or movable!"
|
||||
);
|
||||
|
||||
protected:
|
||||
bool m_success;
|
||||
value_type m_value;
|
||||
|
||||
public:
|
||||
bool isOk() const {
|
||||
return m_success;
|
||||
}
|
||||
|
||||
bool isErr() const {
|
||||
return !m_success;
|
||||
}
|
||||
|
||||
explicit NewResult(value_type const& value, bool success) requires
|
||||
std::is_copy_constructible_v<value_type> :
|
||||
m_value(value),
|
||||
m_success(success) {}
|
||||
|
||||
explicit NewResult(value_type&& value, bool success) requires
|
||||
std::is_move_constructible_v<value_type> :
|
||||
m_value(std::forward<value_type>(value)),
|
||||
m_success(success) {}
|
||||
|
||||
NewResult(NewResult<T, T> const& other) requires std::is_copy_constructible_v<value_type>
|
||||
= default;
|
||||
|
||||
NewResult(NewResult<T, T>&& other
|
||||
) requires(!std::is_copy_constructible_v<value_type>) = default;
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, T> NewResult(
|
||||
NewResult<T2, E2> const& other
|
||||
)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()),
|
||||
m_success(other.isOk()) {}
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, T> NewResult(
|
||||
NewResult<T2, E2>&& other
|
||||
)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type>) :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()), m_success(other.isOk()) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> NewResult(NewResult<T2, AnyType> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> :
|
||||
NewResult(value_type(other.unwrap()), true) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> NewResult(NewResult<T2, AnyType>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type>) :
|
||||
NewResult(std::forward<value_type>(other.unwrap()), true) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, T> NewResult(NewResult<AnyType, E2> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> :
|
||||
NewResult(error_type(other.unwrapErr()), false) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, T> NewResult(NewResult<AnyType, E2>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type>) :
|
||||
NewResult(std::forward<error_type>(other.unwrapErr()), false) {}
|
||||
|
||||
value_type unwrap() const requires std::is_copy_constructible_v<value_type> {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
value_type&& unwrap() requires(!std::is_copy_constructible_v<value_type>) {
|
||||
return std::move(m_value);
|
||||
}
|
||||
|
||||
error_type unwrapErr() const requires std::is_copy_constructible_v<error_type> {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
error_type&& unwrapErr() requires(!std::is_copy_constructible_v<error_type>) {
|
||||
return std::move(m_value);
|
||||
}
|
||||
|
||||
explicit operator bool() const requires(!std::is_same_v<T, bool>) {
|
||||
return this->isOk();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T = DefaultValue, class E = AnyType>
|
||||
|
||||
requires std::is_copy_constructible_v<T> NewResult<T, E> NewOk(T value = T()) {
|
||||
return NewResult<T, E>(value);
|
||||
}
|
||||
|
||||
template <class T = DefaultValue, class E = AnyType>
|
||||
|
||||
requires(!std::is_copy_constructible_v<T>) NewResult<T, E> NewOk(T&& value) {
|
||||
return NewResult<T, E>(std::forward<T>(value));
|
||||
}
|
||||
|
||||
template <class E = DefaultError, class T = AnyType>
|
||||
|
||||
requires std::is_copy_constructible_v<E> NewResult<T, E> NewErr(E error = E()) {
|
||||
return NewResult<T, E>(error);
|
||||
}
|
||||
|
||||
template <class E = DefaultError, class T = AnyType>
|
||||
|
||||
requires(!std::is_copy_constructible_v<E>) NewResult<T, E> NewErr(E&& error) {
|
||||
return NewResult<T, E>(std::forward<E>(error));
|
||||
}
|
||||
|
||||
#define GEODE_UNWRAP_INTO(into, ...) \
|
||||
auto GEODE_CONCAT(res_, __LINE__) = (__VA_ARGS__); \
|
||||
if (GEODE_CONCAT(res_, __LINE__).isErr()) { \
|
||||
return Err(std::move(GEODE_CONCAT(res_, __LINE__).unwrapErr())); \
|
||||
} \
|
||||
into = std::move(GEODE_CONCAT(res_, __LINE__).unwrap())
|
||||
|
||||
#define GEODE_UNWRAP(...) \
|
||||
{ \
|
||||
auto GEODE_CONCAT(res_, __LINE__) = (__VA_ARGS__); \
|
||||
if (GEODE_CONCAT(res_, __LINE__).isErr()) { \
|
||||
return Err(std::move(GEODE_CONCAT(res_, __LINE__).unwrapErr())); \
|
||||
} \
|
||||
}
|
||||
}
|
|
@ -1,176 +1,303 @@
|
|||
#pragma once
|
||||
|
||||
#include "NewResult.hpp"
|
||||
#include "types.hpp"
|
||||
#include "../DefaultInclude.hpp"
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace geode {
|
||||
/**
|
||||
* @struct no_result
|
||||
* The default value of a Result.
|
||||
* Represents a Result that has no
|
||||
* data to carry on Success, but
|
||||
* may still return extended
|
||||
* error information on failure.
|
||||
*/
|
||||
struct no_result {};
|
||||
|
||||
/**
|
||||
* @class Result
|
||||
* Represents an optional value with an
|
||||
* associated error state and -information.
|
||||
* Use the Ok<T> and Err<T> classes to
|
||||
* create Result(s).
|
||||
* @param T Success result value type
|
||||
* @param E Error message type
|
||||
* @authors Matcool, HJfod
|
||||
*/
|
||||
template <class T = no_result, class E = std::string>
|
||||
class [[nodiscard]] Result {
|
||||
protected:
|
||||
bool success;
|
||||
|
||||
union {
|
||||
T my_value;
|
||||
E error_msg;
|
||||
namespace {
|
||||
struct AnyType {
|
||||
explicit AnyType() = delete;
|
||||
};
|
||||
|
||||
Result(const T value) : success(true), my_value(value) {}
|
||||
template <class V, class RV>
|
||||
concept ConvertibleToResult =
|
||||
std::is_convertible_v<std::remove_reference_t<V>, std::remove_reference_t<RV>> ||
|
||||
std::is_same_v<std::remove_reference_t<V>, std::remove_reference_t<RV>>;
|
||||
|
||||
Result(const E error, int dummy) : success(false), error_msg(error) {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Result() {
|
||||
if (success) {
|
||||
if (std::is_destructible<T>::value) {
|
||||
my_value.~T();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (std::is_destructible<E>::value) {
|
||||
error_msg.~E();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy another Result of the same type
|
||||
*/
|
||||
Result(Result<T, E> const& other) {
|
||||
if (other.success) {
|
||||
this->success = true;
|
||||
new (&this->my_value) T(other.value());
|
||||
}
|
||||
else {
|
||||
this->success = false;
|
||||
new (&this->error_msg) E(other.error());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy another Result of a convertible type
|
||||
*/
|
||||
template <class T2, class E2>
|
||||
Result(Result<T2, E2> const& other) {
|
||||
if (other.is_value()) {
|
||||
this->success = true;
|
||||
if constexpr (!std::is_same<T, no_result>::value) {
|
||||
new (&this->my_value) T(other.value());
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->success = false;
|
||||
new (&this->error_msg) E(other.error());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Result was errorful
|
||||
* @returns True if errorful
|
||||
*/
|
||||
bool is_error() const {
|
||||
return !success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Result was succesful
|
||||
* @returns True if succesful
|
||||
*/
|
||||
bool is_value() const {
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the success value of a Result
|
||||
* @returns Value
|
||||
*/
|
||||
auto value() const {
|
||||
return my_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error message of a Result
|
||||
* @returns Error
|
||||
*/
|
||||
auto error() const {
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to bool
|
||||
* @example if (result) { <handle success> } else { <handle failure> }
|
||||
*/
|
||||
explicit operator bool() const {
|
||||
return this->success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a success result
|
||||
* @param value Value
|
||||
*/
|
||||
static auto ok(const T value) {
|
||||
return Result<T>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error result
|
||||
* @param error Error information
|
||||
*/
|
||||
static auto err(E error) {
|
||||
return Result<T>(error, 0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a succesful Result with a value
|
||||
* @param value The value. If none is provided, the type will be no_result
|
||||
* @returns Successful Result
|
||||
*/
|
||||
template <class T = no_result>
|
||||
[[nodiscard]] Result<T> Ok(T value = T()) {
|
||||
return Result<T>::ok(value);
|
||||
using DefaultValue = std::monostate;
|
||||
using DefaultError = std::string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Err
|
||||
* Create an errorful Result with an error message
|
||||
* @param value Error message
|
||||
* @returns Errorful Result
|
||||
*/
|
||||
template <class E = std::string>
|
||||
struct [[nodiscard]] Err {
|
||||
const E _value;
|
||||
template <class T = DefaultValue, class E = DefaultError>
|
||||
class [[nodiscard]] Result {
|
||||
public:
|
||||
using value_type = std::remove_reference_t<T>;
|
||||
using error_type = std::remove_reference_t<E>;
|
||||
|
||||
Err(TypeIdentityType<E> const value) : _value(value) {}
|
||||
// for some reason doing requires causes errors with pch...
|
||||
static_assert(
|
||||
std::is_copy_constructible_v<value_type> || std::is_move_constructible_v<value_type>,
|
||||
"T must be copiable or movable!"
|
||||
);
|
||||
static_assert(
|
||||
std::is_copy_constructible_v<error_type> || std::is_move_constructible_v<error_type>,
|
||||
"E must be copiable or movable!"
|
||||
);
|
||||
|
||||
template <class T>
|
||||
operator Result<T, E>() const {
|
||||
return Result<T, E>::err(_value);
|
||||
protected:
|
||||
std::variant<value_type, error_type> m_value;
|
||||
|
||||
public:
|
||||
bool isOk() const {
|
||||
return std::holds_alternative<value_type>(m_value);
|
||||
}
|
||||
|
||||
bool isErr() const {
|
||||
return std::holds_alternative<error_type>(m_value);
|
||||
}
|
||||
|
||||
template<class ... Args>
|
||||
Result<T, std::string> expect(const char* str, Args&&... args) {
|
||||
if (isErr()) {
|
||||
return Result(fmt::format(str, std::forward<Args>(args)...));
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
explicit Result(value_type const& value
|
||||
) requires std::is_copy_constructible_v<value_type> : m_value(value) {}
|
||||
|
||||
explicit Result(value_type&& value) requires std::is_move_constructible_v<value_type> :
|
||||
m_value(std::forward<value_type>(value)) {}
|
||||
|
||||
explicit Result(error_type const& value
|
||||
) requires std::is_copy_constructible_v<error_type> : m_value(value) {}
|
||||
|
||||
explicit Result(error_type&& value) requires std::is_move_constructible_v<error_type> :
|
||||
m_value(std::forward<error_type>(value)) {}
|
||||
|
||||
Result(Result<T, E> const& other) requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type>
|
||||
= default;
|
||||
|
||||
Result(Result<T, E>&& other
|
||||
) requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) =
|
||||
default;
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, E> Result(
|
||||
Result<T2, E2> const& other
|
||||
)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type>
|
||||
{
|
||||
if (other.isOk()) {
|
||||
m_value = other.unwrap();
|
||||
} else {
|
||||
m_value = other.unwrapErr();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, E> Result(
|
||||
Result<T2, E2>&& other
|
||||
)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> Result(Result<T2, AnyType> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type> : Result(value_type(other.unwrap())) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, E> Result(Result<AnyType, E2> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type> :
|
||||
m_value(std::forward<E2>(other.unwrapErr())) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> Result(Result<T2, AnyType>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) :
|
||||
m_value(other.unwrap()) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, E> Result(Result<AnyType, E2>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) :
|
||||
Result(std::forward<error_type>(other.unwrapErr())) {}
|
||||
|
||||
value_type unwrap() const requires std::is_copy_constructible_v<value_type> {
|
||||
return std::get<value_type>(m_value);
|
||||
}
|
||||
|
||||
value_type&& unwrap() requires(!std::is_copy_constructible_v<value_type>) {
|
||||
return std::move(std::get<value_type>(m_value));
|
||||
}
|
||||
|
||||
error_type unwrapErr() const requires std::is_copy_constructible_v<error_type> {
|
||||
return std::get<error_type>(m_value);
|
||||
}
|
||||
|
||||
error_type&& unwrapErr() requires(!std::is_copy_constructible_v<error_type>) {
|
||||
return std::move(std::get<error_type>(m_value));
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
requires(!std::is_same_v<T, bool> && !std::is_same_v<E, bool>) {
|
||||
return this->isOk();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class [[nodiscard]] Result<T, T> {
|
||||
public:
|
||||
using value_type = std::remove_reference_t<T>;
|
||||
using error_type = std::remove_reference_t<T>;
|
||||
|
||||
// for some reason doing requires causes errors with pch...
|
||||
static_assert(
|
||||
std::is_copy_constructible_v<value_type> ||
|
||||
std::is_move_constructible_v<value_type>,
|
||||
"T must be copiable or movable!"
|
||||
);
|
||||
|
||||
protected:
|
||||
bool m_success;
|
||||
value_type m_value;
|
||||
|
||||
public:
|
||||
bool isOk() const {
|
||||
return m_success;
|
||||
}
|
||||
|
||||
bool isErr() const {
|
||||
return !m_success;
|
||||
}
|
||||
|
||||
template<class ... Args>
|
||||
Result<T, std::string> expect(const char* str, Args&&... args) {
|
||||
if (isErr()) {
|
||||
return Result(fmt::format(str, std::forward<Args>(args)...), false);
|
||||
} else {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
explicit Result(value_type const& value, bool success) requires
|
||||
std::is_copy_constructible_v<value_type> :
|
||||
m_value(value),
|
||||
m_success(success) {}
|
||||
|
||||
explicit Result(value_type&& value, bool success) requires
|
||||
std::is_move_constructible_v<value_type> :
|
||||
m_value(std::forward<value_type>(value)),
|
||||
m_success(success) {}
|
||||
|
||||
Result(Result<T, T> const& other) requires std::is_copy_constructible_v<value_type>
|
||||
= default;
|
||||
|
||||
Result(Result<T, T>&& other
|
||||
) requires(!std::is_copy_constructible_v<value_type>) = default;
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, T> Result(
|
||||
Result<T2, E2> const& other
|
||||
)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()),
|
||||
m_success(other.isOk()) {}
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, T> Result(
|
||||
Result<T2, E2>&& other
|
||||
)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type>) :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()), m_success(other.isOk()) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> Result(Result<T2, AnyType> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> :
|
||||
Result(value_type(other.unwrap()), true) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> Result(Result<T2, AnyType>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type>) :
|
||||
Result(std::forward<value_type>(other.unwrap()), true) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, T> Result(Result<AnyType, E2> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> :
|
||||
Result(error_type(other.unwrapErr()), false) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, T> Result(Result<AnyType, E2>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type>) :
|
||||
Result(std::forward<error_type>(other.unwrapErr()), false) {}
|
||||
|
||||
value_type unwrap() const requires std::is_copy_constructible_v<value_type> {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
value_type&& unwrap() requires(!std::is_copy_constructible_v<value_type>) {
|
||||
return std::move(m_value);
|
||||
}
|
||||
|
||||
error_type unwrapErr() const requires std::is_copy_constructible_v<error_type> {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
error_type&& unwrapErr() requires(!std::is_copy_constructible_v<error_type>) {
|
||||
return std::move(m_value);
|
||||
}
|
||||
|
||||
explicit operator bool() const requires(!std::is_same_v<T, bool>) {
|
||||
return this->isOk();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T = DefaultValue, class E = AnyType>
|
||||
|
||||
requires std::is_copy_constructible_v<T> Result<T, E> Ok(T value = T()) {
|
||||
return Result<T, E>(value);
|
||||
}
|
||||
|
||||
template <class T = DefaultValue, class E = AnyType>
|
||||
|
||||
requires(!std::is_copy_constructible_v<T>) Result<T, E> Ok(T&& value) {
|
||||
return Result<T, E>(std::forward<T>(value));
|
||||
}
|
||||
|
||||
template <class E = DefaultError, class T = AnyType>
|
||||
|
||||
requires std::is_copy_constructible_v<E> Result<T, E> Err(E error = E()) {
|
||||
return Result<T, E>(error);
|
||||
}
|
||||
|
||||
template <class E = DefaultError, class T = AnyType>
|
||||
|
||||
requires(!std::is_copy_constructible_v<E>) Result<T, E> Err(E&& error) {
|
||||
return Result<T, E>(std::forward<E>(error));
|
||||
}
|
||||
|
||||
#define GEODE_UNWRAP_INTO(into, ...) \
|
||||
auto GEODE_CONCAT(unwrap_res_, __LINE__) = (__VA_ARGS__); \
|
||||
if (GEODE_CONCAT(unwrap_res_, __LINE__).isErr()) { \
|
||||
return Err(std::move(GEODE_CONCAT(unwrap_res_, __LINE__).unwrapErr())); \
|
||||
} \
|
||||
into = std::move(GEODE_CONCAT(unwrap_res_, __LINE__).unwrap())
|
||||
|
||||
#define GEODE_UNWRAP(...) \
|
||||
{ \
|
||||
auto GEODE_CONCAT(unwrap_res_, __LINE__) = (__VA_ARGS__); \
|
||||
if (GEODE_CONCAT(unwrap_res_, __LINE__).isErr()) { \
|
||||
return Err(std::move(GEODE_CONCAT(unwrap_res_, __LINE__).unwrapErr())); \
|
||||
} \
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../DefaultInclude.hpp"
|
||||
#include "Result.hpp"
|
||||
#include "json.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include <fs/filesystem.hpp>
|
||||
#include <mutex>
|
||||
|
@ -46,10 +47,10 @@ namespace geode::utils::web {
|
|||
*/
|
||||
template <class Json = nlohmann::json>
|
||||
Result<Json> fetchJSON(std::string const& url) {
|
||||
auto res = fetch(url);
|
||||
if (!res) return Err(res.error());
|
||||
std::string res;
|
||||
GEODE_UNWRAP_INTO(res, fetch(url));
|
||||
try {
|
||||
return Ok(Json::parse(res.value()));
|
||||
return Ok(Json::parse(res));
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
return Err(e.what());
|
||||
|
@ -309,10 +310,10 @@ namespace geode::utils::web {
|
|||
handle](SentAsyncWebRequest& req, byte_array const& arr) {
|
||||
auto conv = converter(arr);
|
||||
if (conv) {
|
||||
handle(conv.value());
|
||||
handle(conv.unwrap());
|
||||
}
|
||||
else {
|
||||
req.error("Unable to convert value: " + conv.error());
|
||||
req.error("Unable to convert value: " + conv.unwrapErr());
|
||||
}
|
||||
};
|
||||
return m_request;
|
||||
|
|
|
@ -10,7 +10,7 @@ struct SaveLoader : Modify<SaveLoader, AppDelegate> {
|
|||
|
||||
auto r = Loader::get()->saveData();
|
||||
if (!r) {
|
||||
log::log(Severity::Error, Loader::getInternalMod(), "{}", r.error());
|
||||
log::log(Severity::Error, Loader::getInternalMod(), "{}", r.unwrapErr());
|
||||
}
|
||||
|
||||
log::log(Severity::Info, Loader::getInternalMod(), "Saved");
|
||||
|
|
|
@ -20,12 +20,12 @@
|
|||
|
||||
template <class Json = nlohmann::json>
|
||||
static Result<Json> readJSON(ghc::filesystem::path const& path) {
|
||||
auto indexJsonData = utils::file::readString(path);
|
||||
if (!indexJsonData) {
|
||||
return Err("Unable to read " + path.string());
|
||||
}
|
||||
GEODE_UNWRAP_INTO(
|
||||
std::string indexJsonData,
|
||||
utils::file::readString(path).expect("Unable to read {}", path.string())
|
||||
);
|
||||
try {
|
||||
return Ok(Json::parse(indexJsonData.value()));
|
||||
return Ok(Json::parse(indexJsonData));
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
return Err("Error parsing JSON: " + std::string(e.what()));
|
||||
|
@ -110,7 +110,7 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) {
|
|||
if (ghc::filesystem::exists(indexDir / "current")) {
|
||||
auto data = utils::file::readString(indexDir / "current");
|
||||
if (data) {
|
||||
currentCommitSHA = data.value();
|
||||
currentCommitSHA = data.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) {
|
|||
if (upcomingCommitSHA == "") {
|
||||
auto err = this->updateIndexFromLocalCache();
|
||||
if (!err) {
|
||||
RETURN_ERROR(err.error());
|
||||
RETURN_ERROR(err.unwrapErr());
|
||||
}
|
||||
|
||||
m_upToDate = true;
|
||||
|
@ -162,13 +162,13 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) {
|
|||
// unzip new index
|
||||
auto unzip = file::unzipTo(indexDir / "index.zip", indexDir);
|
||||
if (!unzip) {
|
||||
RETURN_ERROR(unzip.error());
|
||||
RETURN_ERROR(unzip.unwrapErr());
|
||||
}
|
||||
|
||||
// update index
|
||||
auto err = this->updateIndexFromLocalCache();
|
||||
if (!err) {
|
||||
RETURN_ERROR(err.error());
|
||||
RETURN_ERROR(err.unwrapErr());
|
||||
}
|
||||
|
||||
m_upToDate = true;
|
||||
|
@ -190,7 +190,7 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) {
|
|||
else {
|
||||
auto err = this->updateIndexFromLocalCache();
|
||||
if (!err) {
|
||||
RETURN_ERROR(err.error());
|
||||
RETURN_ERROR(err.unwrapErr());
|
||||
}
|
||||
|
||||
m_upToDate = true;
|
||||
|
@ -214,10 +214,10 @@ void Index::addIndexItemFromFolder(ghc::filesystem::path const& dir) {
|
|||
if (ghc::filesystem::exists(dir / "index.json")) {
|
||||
auto readJson = readJSON(dir / "index.json");
|
||||
if (!readJson) {
|
||||
log::warn("Error reading index.json: {}, skipping", readJson.error());
|
||||
log::warn("Error reading index.json: {}, skipping", readJson.unwrapErr());
|
||||
return;
|
||||
}
|
||||
auto json = readJson.value();
|
||||
auto json = readJson.unwrap();
|
||||
if (!json.is_object()) {
|
||||
log::warn("[index.json] is not an object, skipping");
|
||||
return;
|
||||
|
@ -225,10 +225,10 @@ void Index::addIndexItemFromFolder(ghc::filesystem::path const& dir) {
|
|||
|
||||
auto infoRes = ModInfo::createFromFile(dir / "mod.json");
|
||||
if (!infoRes) {
|
||||
log::warn("{}: {}, skipping", dir, infoRes.error());
|
||||
log::warn("{}: {}, skipping", dir, infoRes.unwrapErr());
|
||||
return;
|
||||
}
|
||||
auto info = infoRes.value();
|
||||
auto info = infoRes.unwrap();
|
||||
|
||||
// make sure only latest version is present in index
|
||||
auto old = std::find_if(m_items.begin(), m_items.end(), [info](IndexItem const& item) {
|
||||
|
@ -283,7 +283,7 @@ void Index::addIndexItemFromFolder(ghc::filesystem::path const& dir) {
|
|||
log::warn("[index.json].categories is not an array, skipping");
|
||||
return;
|
||||
}
|
||||
item.m_categories = json["categories"].get<std::unordered_set<std::string>>();
|
||||
item.m_categories = json["categories"].template get<std::unordered_set<std::string>>();
|
||||
m_categories.insert(item.m_categories.begin(), item.m_categories.end());
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ Result<> Index::updateIndexFromLocalCache() {
|
|||
|
||||
// load geode.json (index settings)
|
||||
if (auto baseIndexJson = readJSON(baseIndexDir / "geode.json")) {
|
||||
auto json = baseIndexJson.value();
|
||||
auto json = baseIndexJson.unwrap();
|
||||
auto checker = JsonChecker(json);
|
||||
checker.root("[index/geode.json]").obj().has("featured").into(m_featured);
|
||||
}
|
||||
|
@ -440,11 +440,8 @@ Result<InstallHandle> Index::installItems(std::vector<IndexItem> const& items) {
|
|||
"the Geode developers - this should not happen, ever."
|
||||
);
|
||||
}
|
||||
auto list = checkDependenciesForItem(item);
|
||||
if (!list) {
|
||||
return Err(list.error());
|
||||
}
|
||||
ranges::push(ids, list.value());
|
||||
GEODE_UNWRAP_INTO(auto list, checkDependenciesForItem(item));
|
||||
ranges::push(ids, list);
|
||||
}
|
||||
auto ret = std::make_shared<InstallItems>(std::unordered_set(ids.begin(), ids.end()));
|
||||
m_installations.insert(ret);
|
||||
|
@ -636,7 +633,7 @@ InstallItems::CallbackID InstallItems::start(ItemInstallCallback callback, bool
|
|||
.then([this, replaceFiles, item, inst, indexDir, tempFile](auto) {
|
||||
// check for 404
|
||||
auto notFound = utils::file::readString(tempFile);
|
||||
if (notFound && notFound.value() == "Not Found") {
|
||||
if (notFound && notFound.unwrap() == "Not Found") {
|
||||
try {
|
||||
ghc::filesystem::remove(tempFile);
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ void InternalLoader::downloadLoaderResources(IndexUpdateCallback callback) {
|
|||
if (!unzip) {
|
||||
if (callback)
|
||||
callback(
|
||||
UpdateStatus::Failed, "Unable to unzip new resources: " + unzip.error(), 0
|
||||
UpdateStatus::Failed, "Unable to unzip new resources: " + unzip.unwrapErr(), 0
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -12,17 +12,17 @@ static ModInfo getInternalModInfo() {
|
|||
try {
|
||||
auto json = ModJson::parse(LOADER_MOD_JSON);
|
||||
auto infoRes = ModInfo::create(json);
|
||||
if (infoRes.is_error()) {
|
||||
if (infoRes.isErr()) {
|
||||
InternalLoader::platformMessageBox(
|
||||
"Fatal Internal Error",
|
||||
"Unable to parse loader mod.json: \"" + infoRes.error() +
|
||||
"Unable to parse loader mod.json: \"" + infoRes.unwrapErr() +
|
||||
"\"\n"
|
||||
"This is a fatal internal error in the loader, please "
|
||||
"contact Geode developers immediately!"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
auto info = infoRes.value();
|
||||
auto info = infoRes.unwrap();
|
||||
info.m_details = LOADER_ABOUT_MD;
|
||||
info.m_supportInfo = SUPPORT_INFO;
|
||||
info.m_supportsDisabling = false;
|
||||
|
@ -50,7 +50,7 @@ InternalMod::InternalMod() : Mod(getInternalModInfo()) {
|
|||
|
||||
auto sett = this->loadSettings();
|
||||
if (!sett) {
|
||||
log::log(Severity::Error, this, "{}", sett.error());
|
||||
log::log(Severity::Error, this, "{}", sett.unwrapErr());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,18 +33,18 @@ Result<> Mod::enableHook(Hook* hook) {
|
|||
log::debug("Enabling hook at function {}", hook->m_displayName);
|
||||
this->m_hooks.push_back(hook);
|
||||
hook->m_enabled = true;
|
||||
hook->m_handle = res.value();
|
||||
return Ok<>();
|
||||
hook->m_handle = res.unwrap();
|
||||
return Ok();
|
||||
}
|
||||
else {
|
||||
return Err<>(
|
||||
return Err(
|
||||
"Unable to create hook at " +
|
||||
std::to_string(reinterpret_cast<uintptr_t>(hook->m_address))
|
||||
);
|
||||
}
|
||||
return Err<>("Hook already has a handle");
|
||||
return Err("Hook already has a handle");
|
||||
}
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> Mod::disableHook(Hook* hook) {
|
||||
|
@ -52,11 +52,11 @@ Result<> Mod::disableHook(Hook* hook) {
|
|||
if (geode::core::hook::remove(hook->m_handle)) {
|
||||
log::debug("Disabling hook at function {}", hook->m_displayName);
|
||||
hook->m_enabled = false;
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
return Err<>("Unable to remove hook");
|
||||
return Err("Unable to remove hook");
|
||||
}
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> Mod::removeHook(Hook* hook) {
|
||||
|
@ -73,7 +73,7 @@ Result<Hook*> Mod::addHook(Hook* hook) {
|
|||
auto res = this->enableHook(hook);
|
||||
if (!res) {
|
||||
delete hook;
|
||||
return Err<>("Can't create hook");
|
||||
return Err("Can't create hook");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -88,7 +88,7 @@ bool InternalLoader::loadHooks() {
|
|||
for (auto const& hook : internalHooks()) {
|
||||
auto res = hook.mod->addHook(hook.hook);
|
||||
if (!res) {
|
||||
log::log(Severity::Error, hook.mod, "{}", res.error());
|
||||
log::log(Severity::Error, hook.mod, "{}", res.unwrapErr());
|
||||
thereWereErrors = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -184,17 +184,17 @@ size_t Loader::loadModsFromDirectory(
|
|||
loadedCount++;
|
||||
|
||||
// check for dependencies
|
||||
if (!res.value()->hasUnresolvedDependencies()) {
|
||||
log::debug("Successfully loaded {}", res.value());
|
||||
if (!res.unwrap()->hasUnresolvedDependencies()) {
|
||||
log::debug("Successfully loaded {}", res.unwrap());
|
||||
}
|
||||
else {
|
||||
log::error("{} has unresolved dependencies", res.value());
|
||||
log::error("{} has unresolved dependencies", res.unwrap());
|
||||
}
|
||||
}
|
||||
else {
|
||||
// something went wrong
|
||||
log::error("{}", res.error());
|
||||
m_erroredMods.push_back({ entry.path().string(), res.error() });
|
||||
log::error("{}", res.unwrapErr());
|
||||
m_erroredMods.push_back({ entry.path().string(), res.unwrapErr() });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,8 +213,8 @@ size_t Loader::refreshMods() {
|
|||
auto res = this->loadModFromFile(path.string());
|
||||
if (!res) {
|
||||
// something went wrong
|
||||
log::error("{}", res.error());
|
||||
m_erroredMods.push_back({ path.string(), res.error() });
|
||||
log::error("{}", res.unwrapErr());
|
||||
m_erroredMods.push_back({ path.string(), res.unwrapErr() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ Result<> Loader::saveData() {
|
|||
for (auto& [_, mod] : m_mods) {
|
||||
auto r = mod->saveData();
|
||||
if (!r) {
|
||||
log::warn("Unable to save data for mod \"{}\": {}", mod->getID(), r.error());
|
||||
log::warn("Unable to save data for mod \"{}\": {}", mod->getID(), r.unwrapErr());
|
||||
}
|
||||
}
|
||||
return Ok();
|
||||
|
@ -257,7 +257,7 @@ Result<> Loader::loadData() {
|
|||
for (auto& [_, mod] : m_mods) {
|
||||
auto r = mod->loadData();
|
||||
if (!r) {
|
||||
log::warn("Unable to load data for mod \"{}\": {}", mod->getID(), r.error());
|
||||
log::warn("Unable to load data for mod \"{}\": {}", mod->getID(), r.unwrapErr());
|
||||
}
|
||||
}
|
||||
return Ok();
|
||||
|
@ -277,10 +277,7 @@ Result<> Loader::saveSettings() {
|
|||
json["early-load"] = m_loadedSettings.m_earlyLoadMods;
|
||||
|
||||
// save loader settings
|
||||
auto saveIS = InternalMod::get()->saveSettings();
|
||||
if (!saveIS) {
|
||||
return Err(saveIS.error());
|
||||
}
|
||||
GEODE_UNWRAP(InternalMod::get()->saveSettings());
|
||||
|
||||
// save info alerts
|
||||
InternalLoader::get()->saveInfoAlerts(json);
|
||||
|
@ -298,12 +295,9 @@ Result<> Loader::loadSettings() {
|
|||
}
|
||||
|
||||
// read mods.json
|
||||
auto read = utils::file::readString(path);
|
||||
if (!read) {
|
||||
return read;
|
||||
}
|
||||
GEODE_UNWRAP_INTO(auto read, utils::file::readString(path));
|
||||
try {
|
||||
auto json = nlohmann::json::parse(read.value());
|
||||
auto json = nlohmann::json::parse(read);
|
||||
auto checker = JsonChecker(json);
|
||||
auto root = checker.root("[loader settings]").obj();
|
||||
root.has("early-load").into(m_loadedSettings.m_earlyLoadMods);
|
||||
|
@ -400,7 +394,7 @@ bool Loader::setup() {
|
|||
this->createDirectories();
|
||||
auto sett = this->loadData();
|
||||
if (!sett) {
|
||||
log::warn("Unable to load loader settings: {}", sett.error());
|
||||
log::warn("Unable to load loader settings: {}", sett.unwrapErr());
|
||||
}
|
||||
this->refreshMods();
|
||||
|
||||
|
|
|
@ -57,11 +57,10 @@ Result<> Mod::loadSettings() {
|
|||
// Check if settings exist
|
||||
auto settPath = m_saveDirPath / "settings.json";
|
||||
if (ghc::filesystem::exists(settPath)) {
|
||||
auto settData = utils::file::readString(settPath);
|
||||
if (!settData) return settData;
|
||||
GEODE_UNWRAP_INTO(auto settData, utils::file::readString(settPath));
|
||||
try {
|
||||
// parse settings.json
|
||||
auto data = nlohmann::json::parse(settData.value());
|
||||
auto data = nlohmann::json::parse(settData);
|
||||
JsonChecker checker(data);
|
||||
auto root = checker.root("[settings.json]");
|
||||
|
||||
|
@ -91,10 +90,9 @@ Result<> Mod::loadSettings() {
|
|||
// Saved values
|
||||
auto savedPath = m_saveDirPath / "saved.json";
|
||||
if (ghc::filesystem::exists(savedPath)) {
|
||||
auto data = utils::file::readString(savedPath);
|
||||
if (!data) return data;
|
||||
GEODE_UNWRAP_INTO(auto data, utils::file::readString(savedPath));
|
||||
try {
|
||||
m_saved = nlohmann::json::parse(data.value());
|
||||
m_saved = nlohmann::json::parse(data);
|
||||
} catch(std::exception& e) {
|
||||
return Err(std::string("Unable to parse saved values: ") + e.what());
|
||||
}
|
||||
|
@ -106,10 +104,9 @@ Result<> Mod::loadSettings() {
|
|||
m_dataStore = m_info.m_defaultDataStore;
|
||||
}
|
||||
else {
|
||||
auto dsData = utils::file::readString(dsPath);
|
||||
if (!dsData) return dsData;
|
||||
GEODE_UNWRAP_INTO(auto dsData, utils::file::readString(dsPath));
|
||||
try {
|
||||
m_dataStore = nlohmann::json::parse(dsData.value());
|
||||
m_dataStore = nlohmann::json::parse(dsData);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
return Err(std::string("Unable to parse datastore: ") + e.what());
|
||||
|
@ -190,11 +187,11 @@ Result<> Mod::createTempDir() {
|
|||
ZipFile unzip(m_info.m_path.string());
|
||||
|
||||
if (!unzip.isLoaded()) {
|
||||
return Err<>("Unable to unzip " + m_info.m_path.string());
|
||||
return Err("Unable to unzip " + m_info.m_path.string());
|
||||
}
|
||||
|
||||
if (!unzip.fileExists(m_info.m_binaryName)) {
|
||||
return Err<>(
|
||||
return Err(
|
||||
"Unable to find platform binary under the name \"" + m_info.m_binaryName + "\""
|
||||
);
|
||||
}
|
||||
|
@ -202,13 +199,13 @@ Result<> Mod::createTempDir() {
|
|||
auto tempDir = Loader::get()->getGeodeDirectory() / GEODE_TEMP_DIRECTORY;
|
||||
if (!ghc::filesystem::exists(tempDir)) {
|
||||
if (!ghc::filesystem::create_directory(tempDir)) {
|
||||
return Err<>("Unable to create temp directory for mods!");
|
||||
return Err("Unable to create temp directory for mods!");
|
||||
}
|
||||
}
|
||||
|
||||
auto tempPath = ghc::filesystem::path(tempDir) / m_info.m_id;
|
||||
if (!ghc::filesystem::exists(tempPath) && !ghc::filesystem::create_directories(tempPath)) {
|
||||
return Err<>("Unable to create temp directory");
|
||||
return Err("Unable to create temp directory");
|
||||
}
|
||||
m_tempDirName = tempPath;
|
||||
|
||||
|
@ -217,7 +214,7 @@ Result<> Mod::createTempDir() {
|
|||
if (path.has_parent_path()) {
|
||||
if (!ghc::filesystem::exists(tempPath / path.parent_path()) &&
|
||||
!ghc::filesystem::create_directories(tempPath / path.parent_path())) {
|
||||
return Err<>(
|
||||
return Err(
|
||||
"Unable to create directories \"" + path.parent_path().string() + "\""
|
||||
);
|
||||
}
|
||||
|
@ -225,37 +222,37 @@ Result<> Mod::createTempDir() {
|
|||
unsigned long size;
|
||||
auto data = unzip.getFileData(file, &size);
|
||||
if (!data || !size) {
|
||||
return Err<>("Unable to read \"" + std::string(file) + "\"");
|
||||
return Err("Unable to read \"" + std::string(file) + "\"");
|
||||
}
|
||||
auto wrt = utils::file::writeBinary(tempPath / file, byte_array(data, data + size));
|
||||
if (!wrt) return Err<>("Unable to write \"" + file + "\": " + wrt.error());
|
||||
if (!wrt) return Err("Unable to write \"" + file + "\": " + wrt.unwrapErr());
|
||||
}
|
||||
|
||||
m_addResourcesToSearchPath = true;
|
||||
|
||||
return Ok<>(tempPath);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> Mod::load() {
|
||||
if (m_loaded) {
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
#define RETURN_LOAD_ERR(str) \
|
||||
{ \
|
||||
m_loadErrorInfo = str; \
|
||||
return Err<>(m_loadErrorInfo); \
|
||||
return Err(m_loadErrorInfo); \
|
||||
}
|
||||
|
||||
if (!m_tempDirName.string().size()) {
|
||||
auto err = this->createTempDir();
|
||||
if (!err) RETURN_LOAD_ERR("Unable to create temp directory: " + err.error());
|
||||
if (!err) RETURN_LOAD_ERR("Unable to create temp directory: " + err.unwrapErr());
|
||||
}
|
||||
|
||||
if (this->hasUnresolvedDependencies()) {
|
||||
RETURN_LOAD_ERR("Mod has unresolved dependencies");
|
||||
}
|
||||
auto err = this->loadPlatformBinary();
|
||||
if (!err) RETURN_LOAD_ERR(err.error());
|
||||
if (!err) RETURN_LOAD_ERR(err.unwrapErr());
|
||||
if (m_implicitLoadFunc) {
|
||||
auto r = m_implicitLoadFunc(this);
|
||||
if (!r) {
|
||||
|
@ -279,20 +276,20 @@ Result<> Mod::load() {
|
|||
ModStateEvent(this, ModEventType::Loaded).post();
|
||||
auto loadRes = this->loadData();
|
||||
if (!loadRes) {
|
||||
log::warn("Unable to load data for \"{}\": {}", m_info.m_id, loadRes.error());
|
||||
log::warn("Unable to load data for \"{}\": {}", m_info.m_id, loadRes.unwrapErr());
|
||||
}
|
||||
m_loadErrorInfo = "";
|
||||
Loader::get()->updateAllDependencies();
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> Mod::unload() {
|
||||
if (!m_loaded) {
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
if (!m_info.m_supportsUnloading) {
|
||||
return Err<>("Mod does not support unloading");
|
||||
return Err("Mod does not support unloading");
|
||||
}
|
||||
|
||||
auto saveRes = this->saveData();
|
||||
|
@ -314,7 +311,7 @@ Result<> Mod::unload() {
|
|||
|
||||
for (auto const& patch : m_patches) {
|
||||
if (!patch->restore()) {
|
||||
return Err<>("Unable to restore patch at " + std::to_string(patch->getAddress()));
|
||||
return Err("Unable to restore patch at " + std::to_string(patch->getAddress()));
|
||||
}
|
||||
delete patch;
|
||||
}
|
||||
|
@ -326,17 +323,17 @@ Result<> Mod::unload() {
|
|||
}
|
||||
m_loaded = false;
|
||||
Loader::get()->updateAllDependencies();
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> Mod::enable() {
|
||||
if (!m_loaded) {
|
||||
return Err<>("Mod is not loaded");
|
||||
return Err("Mod is not loaded");
|
||||
}
|
||||
|
||||
if (m_enableFunc) {
|
||||
if (!m_enableFunc()) {
|
||||
return Err<>("Mod enable function returned false");
|
||||
return Err("Mod enable function returned false");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,23 +346,23 @@ Result<> Mod::enable() {
|
|||
|
||||
for (auto const& patch : m_patches) {
|
||||
if (!patch->apply()) {
|
||||
return Err<>("Unable to apply patch at " + std::to_string(patch->getAddress()));
|
||||
return Err("Unable to apply patch at " + std::to_string(patch->getAddress()));
|
||||
}
|
||||
}
|
||||
|
||||
m_enabled = true;
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> Mod::disable() {
|
||||
if (!m_info.m_supportsDisabling) {
|
||||
return Err<>("Mod does not support disabling");
|
||||
return Err("Mod does not support disabling");
|
||||
}
|
||||
|
||||
if (m_disableFunc) {
|
||||
if (!m_disableFunc()) {
|
||||
return Err<>("Mod disable function returned false");
|
||||
return Err("Mod disable function returned false");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,13 +375,13 @@ Result<> Mod::disable() {
|
|||
|
||||
for (auto const& patch : m_patches) {
|
||||
if (!patch->restore()) {
|
||||
return Err<>("Unable to restore patch at " + std::to_string(patch->getAddress()));
|
||||
return Err("Unable to restore patch at " + std::to_string(patch->getAddress()));
|
||||
}
|
||||
}
|
||||
|
||||
m_enabled = false;
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> Mod::uninstall() {
|
||||
|
@ -397,13 +394,13 @@ Result<> Mod::uninstall() {
|
|||
}
|
||||
}
|
||||
if (!ghc::filesystem::remove(m_info.m_path)) {
|
||||
return Err<>(
|
||||
return Err(
|
||||
"Unable to delete mod's .geode file! "
|
||||
"This might be due to insufficient permissions - "
|
||||
"try running GD as administrator."
|
||||
);
|
||||
}
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool Mod::isUninstalled() const {
|
||||
|
@ -435,13 +432,13 @@ bool Mod::updateDependencyStates() {
|
|||
auto r = dep.m_mod->load();
|
||||
if (!r) {
|
||||
dep.m_state = ModResolveState::Unloaded;
|
||||
log::log(Severity::Error, dep.m_mod, "{}", r.error());
|
||||
log::log(Severity::Error, dep.m_mod, "{}", r.unwrapErr());
|
||||
}
|
||||
else {
|
||||
auto r = dep.m_mod->enable();
|
||||
if (!r) {
|
||||
dep.m_state = ModResolveState::Disabled;
|
||||
log::log(Severity::Error, dep.m_mod, "{}", r.error());
|
||||
log::log(Severity::Error, dep.m_mod, "{}", r.unwrapErr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -471,12 +468,12 @@ bool Mod::updateDependencyStates() {
|
|||
log::debug("Resolved & loading {}", m_info.m_id);
|
||||
auto r = this->load();
|
||||
if (!r) {
|
||||
log::error("{} Error loading: {}", this, r.error());
|
||||
log::error("{} Error loading: {}", this, r.unwrapErr());
|
||||
}
|
||||
else {
|
||||
auto r = this->enable();
|
||||
if (!r) {
|
||||
log::error("{} Error enabling: {}", this, r.error());
|
||||
log::error("{} Error enabling: {}", this, r.unwrapErr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,6 @@ Result<ModInfo> ModInfo::createFromSchemaV010(ModJson const& rawJson) {
|
|||
auto json = rawJson;
|
||||
info.m_rawJSON = rawJson;
|
||||
|
||||
#define PROPAGATE(err) \
|
||||
{ \
|
||||
auto err__ = err; \
|
||||
if (!err__) return Err(err__.error()); \
|
||||
}
|
||||
|
||||
JsonChecker checker(json);
|
||||
auto root = checker.root("[mod.json]").obj();
|
||||
|
||||
|
@ -59,9 +53,7 @@ Result<ModInfo> ModInfo::createFromSchemaV010(ModJson const& rawJson) {
|
|||
}
|
||||
|
||||
for (auto& [key, value] : root.has("settings").items()) {
|
||||
auto settRes = Setting::parse(key, value.json());
|
||||
PROPAGATE(settRes);
|
||||
auto sett = settRes.value();
|
||||
GEODE_UNWRAP_INTO(auto sett, Setting::parse(key, value.json()));
|
||||
sett->m_modID = info.m_id;
|
||||
info.m_settings.push_back({ key, sett });
|
||||
}
|
||||
|
@ -180,18 +172,12 @@ Result<ModInfo> ModInfo::create(ModJson const& json) {
|
|||
|
||||
Result<ModInfo> ModInfo::createFromFile(ghc::filesystem::path const& path) {
|
||||
try {
|
||||
auto read = utils::file::readString(path);
|
||||
if (!read) return Err(read.error());
|
||||
GEODE_UNWRAP_INTO(auto read, utils::file::readString(path));
|
||||
try {
|
||||
auto res = ModInfo::create(ModJson::parse(read.value()));
|
||||
if (!res) return res;
|
||||
auto info = res.value();
|
||||
GEODE_UNWRAP_INTO(auto info, ModInfo::create(ModJson::parse(read)));
|
||||
info.m_path = path;
|
||||
if (path.has_parent_path()) {
|
||||
auto err = info.addSpecialFiles(path.parent_path());
|
||||
if (!err) {
|
||||
return Err(err.error());
|
||||
}
|
||||
GEODE_UNWRAP(info.addSpecialFiles(path.parent_path()));
|
||||
}
|
||||
return Ok(info);
|
||||
}
|
||||
|
@ -207,11 +193,11 @@ Result<ModInfo> ModInfo::createFromFile(ghc::filesystem::path const& path) {
|
|||
Result<ModInfo> ModInfo::createFromGeodeFile(ghc::filesystem::path const& path) {
|
||||
ZipFile unzip(path.string());
|
||||
if (!unzip.isLoaded()) {
|
||||
return Err<>("\"" + path.string() + "\": Unable to unzip");
|
||||
return Err("\"" + path.string() + "\": Unable to unzip");
|
||||
}
|
||||
// Check if mod.json exists in zip
|
||||
if (!unzip.fileExists("mod.json")) {
|
||||
return Err<>("\"" + path.string() + "\" is missing mod.json");
|
||||
return Err("\"" + path.string() + "\" is missing mod.json");
|
||||
}
|
||||
// Read mod.json & parse if possible
|
||||
unsigned long readSize = 0;
|
||||
|
@ -225,7 +211,7 @@ Result<ModInfo> ModInfo::createFromGeodeFile(ghc::filesystem::path const& path)
|
|||
}
|
||||
catch (std::exception const& e) {
|
||||
delete[] read;
|
||||
return Err<>(e.what());
|
||||
return Err(e.what());
|
||||
}
|
||||
|
||||
delete[] read;
|
||||
|
@ -240,15 +226,12 @@ Result<ModInfo> ModInfo::createFromGeodeFile(ghc::filesystem::path const& path)
|
|||
|
||||
auto res = ModInfo::create(json);
|
||||
if (!res) {
|
||||
return Err("\"" + path.string() + "\" - " + res.error());
|
||||
return Err("\"" + path.string() + "\" - " + res.unwrapErr());
|
||||
}
|
||||
auto info = res.value();
|
||||
auto info = res.unwrap();
|
||||
info.m_path = path;
|
||||
|
||||
auto err = info.addSpecialFiles(unzip);
|
||||
if (!err) {
|
||||
return Err(err.error());
|
||||
}
|
||||
GEODE_UNWRAP(info.addSpecialFiles(unzip));
|
||||
|
||||
return Ok(info);
|
||||
}
|
||||
|
@ -276,9 +259,9 @@ Result<> ModInfo::addSpecialFiles(ghc::filesystem::path const& dir) {
|
|||
if (ghc::filesystem::exists(dir / file)) {
|
||||
auto data = file::readString(dir / file);
|
||||
if (!data) {
|
||||
return Err("Unable to read \"" + file + "\": " + data.error());
|
||||
return Err("Unable to read \"" + file + "\": " + data.unwrapErr());
|
||||
}
|
||||
*target = sanitizeDetailsData(data.value());
|
||||
*target = sanitizeDetailsData(data.unwrap());
|
||||
}
|
||||
}
|
||||
return Ok();
|
||||
|
|
|
@ -26,7 +26,7 @@ Result<Patch*> Mod::patch(void* address, byte_array data) {
|
|||
p->m_patch = data;
|
||||
if (!p->apply()) {
|
||||
delete p;
|
||||
return Err<>("Unable to enable patch at " + std::to_string(p->getAddress()));
|
||||
return Err("Unable to enable patch at " + std::to_string(p->getAddress()));
|
||||
}
|
||||
m_patches.push_back(p);
|
||||
return Ok<Patch*>(p);
|
||||
|
@ -36,9 +36,9 @@ Result<> Mod::unpatch(Patch* patch) {
|
|||
if (patch->restore()) {
|
||||
ranges::remove(m_patches, patch);
|
||||
delete patch;
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
return Err<>("Unable to restore patch!");
|
||||
return Err("Unable to restore patch!");
|
||||
}
|
||||
|
||||
bool Patch::apply() {
|
||||
|
|
|
@ -38,7 +38,7 @@ Result<> Mod::loadPlatformBinary() {
|
|||
);
|
||||
|
||||
if (!this->m_implicitLoadFunc && !this->m_loadFunc) {
|
||||
return Err<>(
|
||||
return Err(
|
||||
"Unable to find mod entry point (lacking both implicit & explicit definition)"
|
||||
);
|
||||
}
|
||||
|
@ -48,10 +48,10 @@ Result<> Mod::loadPlatformBinary() {
|
|||
}
|
||||
this->m_platformInfo = new PlatformInfo { dylib };
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
std::string err = (char const*)dlerror();
|
||||
return Err<>("Unable to load the DYLIB: dlerror returned (" + err + ")");
|
||||
return Err("Unable to load the DYLIB: dlerror returned (" + err + ")");
|
||||
}
|
||||
|
||||
Result<> Mod::unloadPlatformBinary() {
|
||||
|
@ -67,10 +67,10 @@ Result<> Mod::unloadPlatformBinary() {
|
|||
this->m_saveDataFunc = nullptr;
|
||||
this->m_loadDataFunc = nullptr;
|
||||
this->m_settingUpdatedFunc = nullptr;
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
else {
|
||||
return Err<>("Unable to free library");
|
||||
return Err("Unable to free library");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,30 +19,27 @@ bool Mod::validateID(std::string const& id) {
|
|||
|
||||
Result<Mod*> Loader::loadModFromFile(std::string const& path) {
|
||||
// load mod.json
|
||||
auto res = ModInfo::createFromGeodeFile(path);
|
||||
if (!res) {
|
||||
return Err(res.error());
|
||||
}
|
||||
GEODE_UNWRAP_INTO(auto json, ModInfo::createFromGeodeFile(path));
|
||||
|
||||
// check that a duplicate has not been loaded
|
||||
if (m_mods.count(res.value().m_id)) {
|
||||
return Err("Mod with ID \"" + res.value().m_id + "\" has already been loaded!");
|
||||
if (m_mods.count(json.m_id)) {
|
||||
return Err("Mod with ID \"" + json.m_id + "\" has already been loaded!");
|
||||
}
|
||||
|
||||
// create and set up Mod instance
|
||||
auto mod = new Mod(res.value());
|
||||
auto mod = new Mod(json);
|
||||
mod->m_saveDirPath =
|
||||
Loader::get()->getGeodeSaveDirectory() / GEODE_MOD_DIRECTORY / res.value().m_id;
|
||||
Loader::get()->getGeodeSaveDirectory() / GEODE_MOD_DIRECTORY / json.m_id;
|
||||
ghc::filesystem::create_directories(mod->m_saveDirPath);
|
||||
|
||||
auto sett = mod->loadSettings();
|
||||
if (!sett) {
|
||||
log::log(Severity::Error, mod, "{}", sett.error());
|
||||
log::log(Severity::Error, mod, "{}", sett.unwrapErr());
|
||||
}
|
||||
|
||||
// enable mod if needed
|
||||
mod->m_enabled = Loader::get()->shouldLoadMod(mod->m_info.m_id);
|
||||
m_mods.insert({ res.value().m_id, mod });
|
||||
m_mods.insert({ json.m_id, mod });
|
||||
mod->updateDependencyStates();
|
||||
|
||||
// add mod resources
|
||||
|
|
|
@ -38,7 +38,7 @@ Result<> Mod::loadPlatformBinary() {
|
|||
);
|
||||
|
||||
if (!this->m_implicitLoadFunc && !this->m_loadFunc) {
|
||||
return Err<>(
|
||||
return Err(
|
||||
"Unable to find mod entry point (lacking both implicit & explicit definition)"
|
||||
);
|
||||
}
|
||||
|
@ -48,10 +48,10 @@ Result<> Mod::loadPlatformBinary() {
|
|||
}
|
||||
this->m_platformInfo = new PlatformInfo { dylib };
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
std::string err = (char const*)dlerror();
|
||||
return Err<>("Unable to load the DYLIB: dlerror returned (" + err + ")");
|
||||
return Err("Unable to load the DYLIB: dlerror returned (" + err + ")");
|
||||
}
|
||||
|
||||
Result<> Mod::unloadPlatformBinary() {
|
||||
|
@ -67,10 +67,10 @@ Result<> Mod::unloadPlatformBinary() {
|
|||
this->m_saveDataFunc = nullptr;
|
||||
this->m_loadDataFunc = nullptr;
|
||||
this->m_settingUpdatedFunc = nullptr;
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
else {
|
||||
return Err<>("Unable to free library");
|
||||
return Err("Unable to free library");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ Result<> Mod::loadPlatformBinary() {
|
|||
);
|
||||
|
||||
if (!this->m_implicitLoadFunc && !this->m_loadFunc) {
|
||||
return Err<>(
|
||||
return Err(
|
||||
"Unable to find mod entry point (lacking both implicit & explicit definition)"
|
||||
);
|
||||
}
|
||||
|
@ -101,9 +101,9 @@ Result<> Mod::loadPlatformBinary() {
|
|||
}
|
||||
this->m_platformInfo = new PlatformInfo { load };
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
return Err<>("Unable to load the DLL: " + getLastWinError());
|
||||
return Err("Unable to load the DLL: " + getLastWinError());
|
||||
}
|
||||
|
||||
Result<> Mod::unloadPlatformBinary() {
|
||||
|
@ -113,10 +113,10 @@ Result<> Mod::unloadPlatformBinary() {
|
|||
this->m_implicitLoadFunc = nullptr;
|
||||
this->m_unloadFunc = nullptr;
|
||||
this->m_loadFunc = nullptr;
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
else {
|
||||
return Err<>("Unable to free the DLL: " + getLastWinError());
|
||||
return Err("Unable to free the DLL: " + getLastWinError());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
#include <Geode/binding/StatsCell.hpp>
|
||||
#include <Geode/binding/TableView.hpp>
|
||||
#include <Geode/binding/FLAlertLayer.hpp>
|
||||
#include <Geode/binding/CCMenuItemToggler.hpp>
|
||||
#include <Geode/utils/casts.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
|
||||
HookCell::HookCell(char const* name, CCSize size) : TableViewCell(name, size.width, size.height) {}
|
||||
|
||||
|
@ -19,36 +22,36 @@ void HookCell::updateBGColor(int index) {
|
|||
void HookCell::onEnable(CCObject* pSender) {
|
||||
auto toggle = as<CCMenuItemToggler*>(pSender);
|
||||
if (!toggle->isToggled()) {
|
||||
auto res = this->m_mod->enableHook(this->m_hook);
|
||||
auto res = m_mod->enableHook(m_hook);
|
||||
if (!res) {
|
||||
FLAlertLayer::create(
|
||||
nullptr, "Error Enabling Hook", std::string(res.error()), "OK", nullptr, 280.f
|
||||
nullptr, "Error Enabling Hook", std::string(res.unwrapErr()), "OK", nullptr, 280.f
|
||||
)
|
||||
->show();
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto res = this->m_mod->disableHook(this->m_hook);
|
||||
auto res = m_mod->disableHook(m_hook);
|
||||
if (!res) {
|
||||
FLAlertLayer::create(
|
||||
nullptr, "Error Disabling Hook", std::string(res.error()), "OK", nullptr, 280.f
|
||||
nullptr, "Error Disabling Hook", std::string(res.unwrapErr()), "OK", nullptr, 280.f
|
||||
)
|
||||
->show();
|
||||
}
|
||||
}
|
||||
toggle->toggle(!this->m_hook->isEnabled());
|
||||
toggle->toggle(!m_hook->isEnabled());
|
||||
}
|
||||
|
||||
void HookCell::loadFromHook(Hook* hook, Mod* Mod) {
|
||||
this->m_hook = hook;
|
||||
this->m_mod = Mod;
|
||||
m_hook = hook;
|
||||
m_mod = Mod;
|
||||
|
||||
this->m_mainLayer->setVisible(true);
|
||||
this->m_backgroundLayer->setOpacity(255);
|
||||
m_mainLayer->setVisible(true);
|
||||
m_backgroundLayer->setOpacity(255);
|
||||
|
||||
auto menu = CCMenu::create();
|
||||
menu->setPosition(this->m_width - this->m_height, this->m_height / 2);
|
||||
this->m_mainLayer->addChild(menu);
|
||||
menu->setPosition(m_width - m_height, m_height / 2);
|
||||
m_mainLayer->addChild(menu);
|
||||
|
||||
auto enableBtn =
|
||||
CCMenuItemToggler::createWithStandardSprites(this, menu_selector(HookCell::onEnable), .6f);
|
||||
|
@ -79,10 +82,10 @@ void HookCell::loadFromHook(Hook* hook, Mod* Mod) {
|
|||
if (hook->getDisplayName() != "") moduleName << hook->getDisplayName();
|
||||
else moduleName << "0x" << std::hex << hook->getAddress();
|
||||
auto label = CCLabelBMFont::create(moduleName.str().c_str(), "chatFont.fnt");
|
||||
label->setPosition(this->m_height / 2, this->m_height / 2);
|
||||
label->setPosition(m_height / 2, m_height / 2);
|
||||
label->setScale(.7f);
|
||||
label->setAnchorPoint({ .0f, .5f });
|
||||
this->m_mainLayer->addChild(label);
|
||||
m_mainLayer->addChild(label);
|
||||
}
|
||||
|
||||
HookCell* HookCell::create(char const* key, CCSize size) {
|
||||
|
@ -95,25 +98,25 @@ HookCell* HookCell::create(char const* key, CCSize size) {
|
|||
}
|
||||
|
||||
void HookListView::setupList() {
|
||||
this->m_itemSeparation = 30.0f;
|
||||
m_itemSeparation = 30.0f;
|
||||
|
||||
if (!this->m_entries->count()) return;
|
||||
if (!m_entries->count()) return;
|
||||
|
||||
this->m_tableView->reloadData();
|
||||
m_tableView->reloadData();
|
||||
|
||||
if (this->m_entries->count() == 1)
|
||||
this->m_tableView->moveToTopWithOffset(this->m_itemSeparation);
|
||||
if (m_entries->count() == 1)
|
||||
m_tableView->moveToTopWithOffset(m_itemSeparation);
|
||||
|
||||
this->m_tableView->moveToTop();
|
||||
m_tableView->moveToTop();
|
||||
}
|
||||
|
||||
TableViewCell* HookListView::getListCell(char const* key) {
|
||||
return HookCell::create(key, CCSize { this->m_width, this->m_itemSeparation });
|
||||
return HookCell::create(key, CCSize { m_width, m_itemSeparation });
|
||||
}
|
||||
|
||||
void HookListView::loadCell(TableViewCell* cell, unsigned int index) {
|
||||
as<HookCell*>(cell)->loadFromHook(
|
||||
as<HookItem*>(this->m_entries->objectAtIndex(index))->m_hook, this->m_mod
|
||||
as<HookItem*>(m_entries->objectAtIndex(index))->m_hook, m_mod
|
||||
);
|
||||
as<HookCell*>(cell)->updateBGColor(index);
|
||||
}
|
||||
|
|
|
@ -448,12 +448,12 @@ void ModInfoLayer::onEnableMod(CCObject* pSender) {
|
|||
if (as<CCMenuItemToggler*>(pSender)->isToggled()) {
|
||||
auto res = m_mod->load();
|
||||
if (!res) {
|
||||
FLAlertLayer::create(nullptr, "Error Loading Mod", res.error(), "OK", nullptr)->show();
|
||||
FLAlertLayer::create(nullptr, "Error Loading Mod", res.unwrapErr(), "OK", nullptr)->show();
|
||||
}
|
||||
else {
|
||||
auto res = m_mod->enable();
|
||||
if (!res) {
|
||||
FLAlertLayer::create(nullptr, "Error Enabling Mod", res.error(), "OK", nullptr)
|
||||
FLAlertLayer::create(nullptr, "Error Enabling Mod", res.unwrapErr(), "OK", nullptr)
|
||||
->show();
|
||||
}
|
||||
}
|
||||
|
@ -461,7 +461,7 @@ void ModInfoLayer::onEnableMod(CCObject* pSender) {
|
|||
else {
|
||||
auto res = m_mod->disable();
|
||||
if (!res) {
|
||||
FLAlertLayer::create(nullptr, "Error Disabling Mod", res.error(), "OK", nullptr)
|
||||
FLAlertLayer::create(nullptr, "Error Disabling Mod", res.unwrapErr(), "OK", nullptr)
|
||||
->show();
|
||||
}
|
||||
}
|
||||
|
@ -476,9 +476,11 @@ void ModInfoLayer::onRepository(CCObject*) {
|
|||
void ModInfoLayer::onInstallMod(CCObject*) {
|
||||
auto ticketRes = Index::get()->installItem(Index::get()->getKnownItem(m_info.m_id));
|
||||
if (!ticketRes) {
|
||||
return FLAlertLayer::create("Unable to install", ticketRes.error(), "OK")->show();
|
||||
return FLAlertLayer::create(
|
||||
"Unable to install", ticketRes.unwrapErr(), "OK"
|
||||
)->show();
|
||||
}
|
||||
m_installation = ticketRes.value();
|
||||
m_installation = ticketRes.unwrap();
|
||||
|
||||
createQuickPopup(
|
||||
"Install",
|
||||
|
@ -626,7 +628,9 @@ void ModInfoLayer::install() {
|
|||
void ModInfoLayer::uninstall() {
|
||||
auto res = m_mod->uninstall();
|
||||
if (!res) {
|
||||
return FLAlertLayer::create("Uninstall failed :(", res.error(), "OK")->show();
|
||||
return FLAlertLayer::create(
|
||||
"Uninstall failed :(", res.unwrapErr(), "OK"
|
||||
)->show();
|
||||
}
|
||||
auto layer = FLAlertLayer::create(
|
||||
this, "Uninstall complete",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <Geode/binding/CCMenuItemSpriteExtra.hpp>
|
||||
#include <Geode/binding/StatsCell.hpp>
|
||||
#include <Geode/binding/TableView.hpp>
|
||||
#include <Geode/binding/CCMenuItemToggler.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <Geode/utils/casts.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
|
@ -18,9 +19,9 @@
|
|||
template <class T>
|
||||
static bool tryOrAlert(Result<T> const& res, char const* title) {
|
||||
if (!res) {
|
||||
FLAlertLayer::create(title, res.error(), "OK")->show();
|
||||
FLAlertLayer::create(title, res.unwrapErr(), "OK")->show();
|
||||
}
|
||||
return res.is_value();
|
||||
return res.isOk();
|
||||
}
|
||||
|
||||
ModCell::ModCell(char const* name, CCSize size) : TableViewCell(name, size.width, size.height) {}
|
||||
|
|
|
@ -120,10 +120,12 @@ void FileSettingNode::onPickFile(CCObject*) {
|
|||
auto setting = std::static_pointer_cast<FileSetting>(m_setting);
|
||||
if (auto path = file::pickFile(
|
||||
file::PickMode::OpenFile,
|
||||
{ file::geodeRoot(),
|
||||
setting->getFileFilters().value_or(std::vector<file::FilePickOptions::Filter>()) }
|
||||
{
|
||||
file::geodeRoot(),
|
||||
setting->getFileFilters().value_or(std::vector<file::FilePickOptions::Filter>())
|
||||
}
|
||||
)) {
|
||||
m_uncommittedValue = path.value();
|
||||
m_uncommittedValue = path.unwrap();
|
||||
this->valueChanged(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ namespace {
|
|||
auto isValid = std::static_pointer_cast<T>(m_setting)->isValidValue(m_uncommittedValue);
|
||||
if (!isValid) {
|
||||
m_errorLabel->setVisible(true);
|
||||
m_errorLabel->setString(isValid.error().c_str());
|
||||
m_errorLabel->setString(isValid.unwrapErr().c_str());
|
||||
}
|
||||
else {
|
||||
m_errorLabel->setVisible(false);
|
||||
|
|
|
@ -209,9 +209,9 @@ void ColorPickPopup::textChanged(CCTextInputNode* input) {
|
|||
case TAG_HEX_INPUT:
|
||||
{
|
||||
if (auto color = cc3bFromHexString(input->getString())) {
|
||||
m_color.r = color.value().r;
|
||||
m_color.g = color.value().g;
|
||||
m_color.b = color.value().b;
|
||||
m_color.r = color.unwrap().r;
|
||||
m_color.g = color.unwrap().g;
|
||||
m_color.b = color.unwrap().b;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -303,10 +303,10 @@ struct MDParser {
|
|||
else {
|
||||
auto color = colorForIdentifier(tag);
|
||||
if (color) {
|
||||
renderer->pushColor(color.value());
|
||||
renderer->pushColor(color.unwrap());
|
||||
}
|
||||
else {
|
||||
log::warn("Error parsing color: {}", color.error());
|
||||
log::warn("Error parsing color: {}", color.unwrapErr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,10 +42,10 @@ void cocos2d::from_json(nlohmann::json const& json, ccColor3B& color) {
|
|||
auto c = cc3bFromHexString(str);
|
||||
if (!c) {
|
||||
throw nlohmann::json::type_error::create(
|
||||
0, "Invalid color hex string: " + c.error(), json
|
||||
0, "Invalid color hex string: " + c.unwrapErr(), json
|
||||
);
|
||||
}
|
||||
color = c.value();
|
||||
color = c.unwrap();
|
||||
}
|
||||
// bad
|
||||
else {
|
||||
|
@ -98,10 +98,10 @@ void cocos2d::from_json(nlohmann::json const& json, ccColor4B& color) {
|
|||
auto c = cc4bFromHexString(str);
|
||||
if (!c) {
|
||||
throw nlohmann::json::type_error::create(
|
||||
0, "Invalid color hex string: " + c.error(), json
|
||||
0, "Invalid color hex string: " + c.unwrapErr(), json
|
||||
);
|
||||
}
|
||||
color = c.value();
|
||||
color = c.unwrap();
|
||||
}
|
||||
// bad
|
||||
else {
|
||||
|
|
|
@ -367,26 +367,26 @@ AsyncWebRequest::~AsyncWebRequest() {
|
|||
|
||||
AsyncWebResult<std::monostate> AsyncWebResponse::into(std::ostream& stream) {
|
||||
m_request.m_target = &stream;
|
||||
return this->as(+[](byte_array const&) {
|
||||
return this->as(+[](byte_array const&) -> Result<std::monostate> {
|
||||
return Ok(std::monostate());
|
||||
});
|
||||
}
|
||||
|
||||
AsyncWebResult<std::monostate> AsyncWebResponse::into(ghc::filesystem::path const& path) {
|
||||
m_request.m_target = path;
|
||||
return this->as(+[](byte_array const&) {
|
||||
return this->as(+[](byte_array const&) -> Result<std::monostate> {
|
||||
return Ok(std::monostate());
|
||||
});
|
||||
}
|
||||
|
||||
AsyncWebResult<std::string> AsyncWebResponse::text() {
|
||||
return this->as(+[](byte_array const& bytes) {
|
||||
return this->as(+[](byte_array const& bytes) -> Result<std::string> {
|
||||
return Ok(std::string(bytes.begin(), bytes.end()));
|
||||
});
|
||||
}
|
||||
|
||||
AsyncWebResult<byte_array> AsyncWebResponse::bytes() {
|
||||
return this->as(+[](byte_array const& bytes) {
|
||||
return this->as(+[](byte_array const& bytes) -> Result<byte_array> {
|
||||
return Ok(bytes);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <Geode/utils/file.hpp>
|
||||
#include <Geode/utils/string.hpp>
|
||||
#include <fstream>
|
||||
#include <../support/zip_support/ZipUtils.h>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
|
@ -89,10 +90,10 @@ Result<> utils::file::writeString(std::string const& path, std::string const& da
|
|||
file << data;
|
||||
file.close();
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
file.close();
|
||||
return Err<>("Unable to open file");
|
||||
return Err("Unable to open file");
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
|
@ -103,10 +104,10 @@ Result<> utils::file::writeString(std::wstring const& path, std::string const& d
|
|||
file << data;
|
||||
file.close();
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
file.close();
|
||||
return Err<>("Unable to open file");
|
||||
return Err("Unable to open file");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -121,10 +122,10 @@ Result<> utils::file::writeString(ghc::filesystem::path const& path, std::string
|
|||
file << data;
|
||||
file.close();
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
file.close();
|
||||
return Err<>("Unable to open file");
|
||||
return Err("Unable to open file");
|
||||
}
|
||||
|
||||
Result<> utils::file::writeBinary(std::string const& path, byte_array const& data) {
|
||||
|
@ -134,10 +135,10 @@ Result<> utils::file::writeBinary(std::string const& path, byte_array const& dat
|
|||
file.write(reinterpret_cast<char const*>(data.data()), data.size());
|
||||
file.close();
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
file.close();
|
||||
return Err<>("Unable to open file");
|
||||
return Err("Unable to open file");
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
|
@ -148,10 +149,10 @@ Result<> utils::file::writeBinary(std::wstring const& path, byte_array const& da
|
|||
file.write(reinterpret_cast<char const*>(data.data()), data.size());
|
||||
file.close();
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
file.close();
|
||||
return Err<>("Unable to open file");
|
||||
return Err("Unable to open file");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -166,74 +167,74 @@ Result<> utils::file::writeBinary(ghc::filesystem::path const& path, byte_array
|
|||
file.write(reinterpret_cast<char const*>(data.data()), data.size());
|
||||
file.close();
|
||||
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
file.close();
|
||||
return Err<>("Unable to open file");
|
||||
return Err("Unable to open file");
|
||||
}
|
||||
|
||||
Result<> utils::file::createDirectory(std::string const& path) {
|
||||
try {
|
||||
if (ghc::filesystem::create_directory(path)) {
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return Err<>("Unable to create directory");
|
||||
return Err("Unable to create directory");
|
||||
}
|
||||
|
||||
Result<> utils::file::createDirectory(ghc::filesystem::path const& path) {
|
||||
try {
|
||||
if (ghc::filesystem::create_directory(path)) {
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return Err<>("Unable to create directory");
|
||||
return Err("Unable to create directory");
|
||||
}
|
||||
|
||||
Result<> utils::file::createDirectoryAll(std::string const& path) {
|
||||
try {
|
||||
if (ghc::filesystem::create_directories(path)) {
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return Err<>("Unable to create directories");
|
||||
return Err("Unable to create directories");
|
||||
}
|
||||
|
||||
Result<> utils::file::createDirectoryAll(ghc::filesystem::path const& path) {
|
||||
try {
|
||||
if (ghc::filesystem::create_directories(path)) {
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return Err<>("Unable to create directories");
|
||||
return Err("Unable to create directories");
|
||||
}
|
||||
|
||||
Result<std::vector<std::string>> utils::file::listFiles(std::string const& path) {
|
||||
if (!ghc::filesystem::exists(path)) return Err<>("Directory does not exist");
|
||||
if (!ghc::filesystem::exists(path)) return Err("Directory does not exist");
|
||||
|
||||
std::vector<std::string> res;
|
||||
for (auto const& file : ghc::filesystem::directory_iterator(path)) {
|
||||
res.push_back(file.path().string());
|
||||
}
|
||||
return Ok<>(res);
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
Result<std::vector<std::string>> utils::file::listFilesRecursively(std::string const& path) {
|
||||
if (!ghc::filesystem::exists(path)) return Err<>("Directory does not exist");
|
||||
if (!ghc::filesystem::exists(path)) return Err("Directory does not exist");
|
||||
|
||||
std::vector<std::string> res;
|
||||
for (auto const& file : ghc::filesystem::recursive_directory_iterator(path)) {
|
||||
res.push_back(file.path().string());
|
||||
}
|
||||
return Ok<>(res);
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
Result<> utils::file::unzipTo(ghc::filesystem::path const& from, ghc::filesystem::path const& to) {
|
||||
|
@ -274,7 +275,7 @@ Result<> utils::file::unzipTo(ghc::filesystem::path const& from, ghc::filesystem
|
|||
}
|
||||
auto wrt = utils::file::writeBinary(to / file, byte_array(data, data + size));
|
||||
if (!wrt) {
|
||||
return Err("Unable to write \"" + (to / file).string() + "\": " + wrt.error());
|
||||
return Err("Unable to write \"" + (to / file).string() + "\": " + wrt.unwrapErr());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -235,11 +235,7 @@ Result<> nfdPick(
|
|||
Holder _([&]() {
|
||||
shellItems->Release();
|
||||
});
|
||||
auto res = convShellItems(shellItems);
|
||||
if (!res) {
|
||||
return Err(res.error());
|
||||
}
|
||||
*reinterpret_cast<Paths*>(result) = res.value();
|
||||
GEODE_UNWRAP_INTO(*reinterpret_cast<Paths*>(result), convShellItems(shellItems));
|
||||
return Ok();
|
||||
} break;
|
||||
|
||||
|
|
|
@ -89,13 +89,10 @@ Result<ghc::filesystem::path> utils::file::pickFile(
|
|||
TURN_INTO_NFDMODE(OpenFile);
|
||||
TURN_INTO_NFDMODE(SaveFile);
|
||||
TURN_INTO_NFDMODE(OpenFolder);
|
||||
default: return Err("Unknown open mode");
|
||||
default: return Err<std::string>("Unknown open mode");
|
||||
}
|
||||
ghc::filesystem::path path;
|
||||
auto r = nfdPick(nfdMode, options, &path);
|
||||
if (!r) {
|
||||
return Err(r.error());
|
||||
}
|
||||
GEODE_UNWRAP(nfdPick(nfdMode, options, &path));
|
||||
return Ok(path);
|
||||
}
|
||||
|
||||
|
@ -103,10 +100,7 @@ Result<std::vector<ghc::filesystem::path>> utils::file::pickFiles(
|
|||
file::FilePickOptions const& options
|
||||
) {
|
||||
std::vector<ghc::filesystem::path> paths;
|
||||
auto r = nfdPick(NFDMode::OpenFolder, options, &paths);
|
||||
if (!r) {
|
||||
return Err(r.error());
|
||||
}
|
||||
GEODE_UNWRAP(nfdPick(NFDMode::OpenFolder, options, &paths));
|
||||
return Ok(paths);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue