mirror of
https://github.com/geode-sdk/geode.git
synced 2024-12-02 12:17:10 -05:00
156 lines
4.5 KiB
C++
156 lines
4.5 KiB
C++
#pragma once
|
|
|
|
#include <ghc/fs_fwd.hpp>
|
|
#include "../utils/Result.hpp"
|
|
#include "../utils/MiniFunction.hpp"
|
|
#include "Log.hpp"
|
|
#include "ModEvent.hpp"
|
|
#include "ModMetadata.hpp"
|
|
#include "Types.hpp"
|
|
|
|
#include <atomic>
|
|
#include <matjson.hpp>
|
|
#include <mutex>
|
|
#include <optional>
|
|
#include <string_view>
|
|
|
|
namespace geode {
|
|
using ScheduledFunction = utils::MiniFunction<void()>;
|
|
|
|
struct InvalidGeodeFile {
|
|
ghc::filesystem::path path;
|
|
std::string reason;
|
|
};
|
|
|
|
struct LoadProblem {
|
|
enum class Type : uint8_t {
|
|
Unknown,
|
|
Suggestion,
|
|
Recommendation,
|
|
Conflict,
|
|
OutdatedConflict,
|
|
InvalidFile,
|
|
Duplicate,
|
|
SetupFailed,
|
|
LoadFailed,
|
|
EnableFailed,
|
|
MissingDependency,
|
|
PresentIncompatibility,
|
|
UnzipFailed,
|
|
UnsupportedVersion,
|
|
UnsupportedGeodeVersion,
|
|
NeedsNewerGeodeVersion,
|
|
DisabledDependency,
|
|
OutdatedDependency,
|
|
OutdatedIncompatibility,
|
|
};
|
|
Type type;
|
|
std::variant<ghc::filesystem::path, ModMetadata, Mod*> cause;
|
|
std::string message;
|
|
};
|
|
|
|
class LoaderImpl;
|
|
|
|
class GEODE_DLL Loader {
|
|
private:
|
|
class Impl;
|
|
std::unique_ptr<Impl> m_impl;
|
|
Loader();
|
|
~Loader();
|
|
|
|
protected:
|
|
Mod* takeNextMod();
|
|
|
|
public:
|
|
static Loader* get();
|
|
|
|
enum class LoadingState : uint8_t {
|
|
None,
|
|
Queue,
|
|
List,
|
|
Graph,
|
|
EarlyMods,
|
|
Mods,
|
|
Problems,
|
|
Done
|
|
};
|
|
|
|
bool isForwardCompatMode();
|
|
|
|
void saveData();
|
|
void loadData();
|
|
|
|
VersionInfo getVersion();
|
|
VersionInfo minModVersion();
|
|
VersionInfo maxModVersion();
|
|
bool isModVersionSupported(VersionInfo const& version);
|
|
|
|
LoadingState getLoadingState();
|
|
bool isModInstalled(std::string const& id) const;
|
|
Mod* getInstalledMod(std::string const& id) const;
|
|
bool isModLoaded(std::string const& id) const;
|
|
Mod* getLoadedMod(std::string const& id) const;
|
|
std::vector<Mod*> getAllMods();
|
|
std::vector<LoadProblem> getProblems() const;
|
|
|
|
/**
|
|
* Returns the available launch argument names.
|
|
*/
|
|
std::vector<std::string> getLaunchArgumentNames() const;
|
|
/**
|
|
* Returns whether the specified launch argument was passed in via the command line.
|
|
* @param name The argument name
|
|
*/
|
|
bool hasLaunchArgument(std::string_view const name) const;
|
|
/**
|
|
* Get a launch argument. These are passed into the game as command-line arguments
|
|
* with the format `--geode:arg-name=value`.
|
|
* @param name The argument name
|
|
* @return The value, if present
|
|
*/
|
|
std::optional<std::string> getLaunchArgument(std::string_view const name) const;
|
|
/**
|
|
* Get a launch argument flag. Returns whether the argument is present and its
|
|
* value is exactly `true`.
|
|
* @param name The argument name
|
|
*/
|
|
bool getLaunchFlag(std::string_view const name) const;
|
|
/**
|
|
* Get and parse a launch argument value using the setting value system.
|
|
* @param name The argument name
|
|
*/
|
|
template <class T>
|
|
std::optional<T> parseLaunchArgument(std::string_view const name) const {
|
|
auto str = this->getLaunchArgument(name);
|
|
if (!str.has_value()) {
|
|
return std::nullopt;
|
|
}
|
|
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.value();
|
|
if (!value.is<T>()) {
|
|
return std::nullopt;
|
|
}
|
|
return value.as<T>();
|
|
}
|
|
|
|
void queueInMainThread(ScheduledFunction func);
|
|
|
|
friend class LoaderImpl;
|
|
|
|
friend Mod* takeNextLoaderMod();
|
|
};
|
|
|
|
/**
|
|
* @brief Take the next mod to load
|
|
*
|
|
* @return Mod* The next mod to load
|
|
*/
|
|
inline GEODE_HIDDEN Mod* takeNextLoaderMod() {
|
|
return Loader::get()->takeNextMod();
|
|
}
|
|
}
|