geode/loader/include/Geode/modify/Modify.hpp

92 lines
3.4 KiB
C++
Raw Normal View History

2022-07-30 12:24:03 -04:00
#pragma once
#include "../meta/meta.hpp"
2022-10-30 14:59:20 -04:00
#include "Addresses.hpp"
2022-11-09 12:11:50 -05:00
#include "Field.hpp"
2022-12-12 10:42:56 -05:00
#include "IDManager.hpp"
2022-10-30 14:59:20 -04:00
#include "Types.hpp"
#include "Wrapper.hpp"
2022-10-08 09:55:40 -04:00
#include <Geode/loader/Loader.hpp>
#include <Geode/loader/Mod.hpp>
2022-07-30 12:24:03 -04:00
#include <iostream>
2022-12-12 10:42:56 -05:00
#include <tulip/TulipHook.hpp>
2022-07-30 12:24:03 -04:00
2022-12-12 10:42:56 -05:00
#define GEODE_APPLY_MODIFY_FOR_FUNCTION(addr_index, pure_index, convention, className, functionName) \
{ \
using DerivedWrap = wrap::functionName<Derived, types::pure##pure_index>; \
using BaseWrap = wrap::functionName<Base, types::pure##pure_index>; \
if constexpr (DerivedWrap::uuid != nullptr && (void*)BaseWrap::uuid != (void*)DerivedWrap::uuid) { \
auto hook = Hook::create<convention>( \
Mod::get(), \
reinterpret_cast<void*>(addresses::address##addr_index()), \
DerivedWrap::value, \
#className "::" #functionName \
); \
BaseModify::m_hooks[FunctionUUID<DerivedWrap::value>::value] = hook; \
} \
2022-10-30 14:59:20 -04:00
}
2022-07-30 12:24:03 -04:00
namespace geode::modifier {
2022-10-30 14:59:20 -04:00
template <class Derived, class Base>
2022-11-09 12:11:50 -05:00
class ModifyDerive;
2022-07-30 12:24:03 -04:00
2022-12-12 10:42:56 -05:00
template <class ModifyDerived>
2022-10-30 14:59:20 -04:00
class ModifyBase {
public:
2022-12-12 10:42:56 -05:00
std::map<void (*)(), Hook*> m_hooks;
template <auto Function>
Result<Hook*> getHook() {
auto uuid = FunctionUUID<Function>::value;
if (m_hooks.find(uuid) == m_hooks.end()) {
return Err("Hook not in this modify");
}
return m_hooks[uuid];
}
2022-10-30 14:59:20 -04:00
// unordered_map<handles> idea
ModifyBase() {
2022-12-12 10:42:56 -05:00
Loader::get()->scheduleOnModLoad(getMod(), [this]() {
this->apply();
ModifyDerived::Derived::onModify(*this);
for (auto& [uuid, hook] : m_hooks) {
auto res = Mod::get()->addHook(hook);
if (!res) {
log::error("Failed to add hook: {}", res.error());
}
}
2022-10-30 14:59:20 -04:00
});
}
2022-12-12 10:42:56 -05:00
virtual void apply() {}
2022-10-30 14:59:20 -04:00
template <class, class>
2022-11-09 12:11:50 -05:00
friend class ModifyDerive;
2022-10-30 14:59:20 -04:00
// explicit Modify(Property property) idea
};
2022-07-30 12:24:03 -04:00
2022-10-30 14:59:20 -04:00
template <class Derived, class Base>
2022-11-09 12:11:50 -05:00
class ModifyDerive {
2022-10-30 14:59:20 -04:00
public:
2022-11-09 12:11:50 -05:00
ModifyDerive() {
2022-10-30 14:59:20 -04:00
static_assert(core::meta::always_false<Derived>, "Custom Modify not implemented.");
}
};
2022-07-30 12:24:03 -04:00
}
2022-11-09 12:11:50 -05:00
namespace geode {
template <class Derived, class Base>
class Modify : public Base {
private:
static inline modifier::ModifyDerive<Derived, Base> s_apply;
// because for some reason we need it
static inline auto s_applyRef = &Modify::s_apply;
public:
modifier::FieldIntermediate<Derived, Base> m_fields;
2022-12-12 10:42:56 -05:00
static void onModify(auto& self) {}
2022-11-09 12:11:50 -05:00
};
}