mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
dispatcher
This commit is contained in:
parent
8fe349d259
commit
19d4f3bbae
5 changed files with 71 additions and 245 deletions
|
@ -5,6 +5,6 @@
|
||||||
#include "syntax/Field.hpp"
|
#include "syntax/Field.hpp"
|
||||||
#include "syntax/InternalMacros.hpp"
|
#include "syntax/InternalMacros.hpp"
|
||||||
#include "loader/GeodeLoader.hpp"
|
#include "loader/GeodeLoader.hpp"
|
||||||
#include "loader/API.hpp"
|
#include "loader/Dispatcher.hpp"
|
||||||
|
|
||||||
using namespace geode::modifier;
|
using namespace geode::modifier;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "../codegen-base/Macros.hpp"
|
#include "../codegen-base/Macros.hpp"
|
||||||
#include "../utils/include.hpp"
|
#include "../utils/include.hpp"
|
||||||
#include "Mod.hpp"
|
#include "Mod.hpp"
|
||||||
|
@ -6,65 +8,86 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace geode {
|
namespace geode {
|
||||||
class Dispatcher;
|
class Dispatcher;
|
||||||
|
|
||||||
struct GEODE_DLL dispatch_handle {
|
struct GEODE_DLL dispatch_handle {
|
||||||
void* handle;
|
void* handle;
|
||||||
|
|
||||||
dispatch_handle() = delete;
|
dispatch_handle() = delete;
|
||||||
dispatch_handle(dispatch_handle&& d) : handle(d.handle) {}
|
dispatch_handle(dispatch_handle const& d) : handle(d.handle) {}
|
||||||
dispatch_handle(dispatch_handle const& d) : handle(d.handle) {}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::function<T> get() {
|
std::function<T> into() {
|
||||||
*reinterpret_cast<std::function<T>*>(this->handle);
|
*reinterpret_cast<std::function<T>*>(this->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename R, typename ...Args>
|
template <typename R, typename ...Args>
|
||||||
R call(Args... args) {
|
R call(Args... args) {
|
||||||
return this->get<std::function<R(Args...)>>()(args...);
|
return this->into<std::function<R(Args...)>>()(args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
dispatch_handle(void* h) : handle(h) {}
|
|
||||||
friend class Dispatcher;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GEODE_DLL Dispatcher {
|
bool operator<(dispatch_handle const& b) const {
|
||||||
protected:
|
return handle < b.handle;
|
||||||
std::map<dispatch_handle, std::pair<std::string, Mod*>> m_dispatchMap;
|
}
|
||||||
std::map<std::string, std::vector<dispatch_handle>> m_selectorMap;
|
|
||||||
// 2 maps for lookup speed
|
|
||||||
|
|
||||||
std::vector<dispatch_handle> _getHandles(std::string const& a);
|
bool operator==(dispatch_handle const& b) const {
|
||||||
std::pair<string, Mod*> _getInfo(dispatch_handle u);
|
return handle == b.handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
dispatch_handle(void* h) : handle(h) {}
|
||||||
|
|
||||||
void _removeFunction(dispatch_handle u);
|
template <typename T>
|
||||||
dispatch_handle _addFunction(Mod* m, std::string const& a);
|
static dispatch_handle from(std::function<T> f) {
|
||||||
|
return dispatch_handle(reinterpret_cast<void*>(new std::function<T>(f)));
|
||||||
|
}
|
||||||
|
friend class Dispatcher;
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<dispatch_handle> _allHandles();
|
class GEODE_DLL Dispatcher {
|
||||||
|
protected:
|
||||||
|
std::map<dispatch_handle, std::pair<std::string, Mod*>> m_dispatchMap;
|
||||||
|
std::map<std::string, std::vector<dispatch_handle>> m_selectorMap;
|
||||||
|
// 2 maps for lookup speed
|
||||||
|
|
||||||
|
std::vector<dispatch_handle> getFunctions_(std::string const& a);
|
||||||
|
|
||||||
|
void addFunction_(Mod* m, std::string const& a, dispatch_handle u);
|
||||||
|
|
||||||
|
std::vector<dispatch_handle> allFunctions_();
|
||||||
|
|
||||||
template <typename T>
|
Dispatcher() {}
|
||||||
std::function<T> _fromOpaque(void* f) {
|
|
||||||
*reinterpret_cast<std::function<T>*>(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
public:
|
||||||
void* _toOpaque(std::function<T> f) {
|
static Dispatcher* get();
|
||||||
return reinterpret_cast<void*>(new std::function<T>(f));
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
static Dispatcher* get();
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<std::function<T>> getSelectors(std::string_view const& a) {
|
std::vector<std::function<T>> getFunctions(std::string const& a) {
|
||||||
return geode::vector_utils::map(_getSelectors(a), [this](std::pair<dispatch_handle, void*> selector) {
|
return geode::vector_utils::map(getFunctions_(a), [this](dispatch_handle fn) {
|
||||||
return _fromOpaque<T>(selector.second);
|
return fn.into<T>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
template <typename T>
|
||||||
|
std::function<T> getFunction(std::string const& a) {
|
||||||
|
return getFunctions_(a).back().into<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
dispatch_handle addFunction(std::string const& a, std::function<T> f) {
|
||||||
|
dispatch_handle hdl = dispatch_handle::from(f);
|
||||||
|
addFunction_(Mod::get(), a, hdl);
|
||||||
|
return hdl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::vector<dispatch_handle> allFunctions() {
|
||||||
|
return geode::vector_utils::map(allFunctions_(), [this](dispatch_handle fn) {
|
||||||
|
return fn.into<T>();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFunction(dispatch_handle u);
|
||||||
|
std::pair<std::string, Mod*> getFunctionInfo(dispatch_handle u);
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -1,148 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <memory>
|
|
||||||
#include <exception>
|
|
||||||
#include <map>
|
|
||||||
#include <Macros.hpp>
|
|
||||||
#include <any>
|
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
#ifndef GEODE_DLL
|
|
||||||
#define GEODE_DLL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace geode {
|
|
||||||
class EventCenter;
|
|
||||||
class Mod;
|
|
||||||
|
|
||||||
template <typename T = std::monostate>
|
|
||||||
struct EventInfo {
|
|
||||||
std::string selector;
|
|
||||||
inline EventInfo(std::string sel) : selector(sel) {}
|
|
||||||
inline EventInfo() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T = std::monostate>
|
|
||||||
struct ConstEventInfo {
|
|
||||||
char const* selector;
|
|
||||||
inline constexpr ConstEventInfo(char const* sel) : selector(sel) {}
|
|
||||||
inline constexpr ConstEventInfo() {}
|
|
||||||
|
|
||||||
inline operator EventInfo<T>() {
|
|
||||||
return EventInfo<T>(selector);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T = std::monostate>
|
|
||||||
class Event {
|
|
||||||
protected:
|
|
||||||
EventInfo<T> m_info;
|
|
||||||
T m_object;
|
|
||||||
Mod* m_sender;
|
|
||||||
public:
|
|
||||||
inline T const& object() const {
|
|
||||||
return m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string const& selector() const { return m_info.selector; }
|
|
||||||
inline Mod* sender() const { return m_sender; }
|
|
||||||
|
|
||||||
inline Event(EventInfo<T> inf, T obj, Mod* sender) :
|
|
||||||
m_info(inf),
|
|
||||||
m_object(obj),
|
|
||||||
m_sender(sender) {}
|
|
||||||
|
|
||||||
inline Event(std::string sel, T obj, Mod* sender) : Event(EventInfo<T>(sel), obj, sender) {}
|
|
||||||
|
|
||||||
inline Event(std::string sel, Mod* sender) : Event(sel, T(), sender) {}
|
|
||||||
inline Event(EventInfo<T> inf, Mod* sender) : Event(inf, T(), sender) {}
|
|
||||||
// Event(std::string sel) : Event(sel, Interface::get()->mod()) {}
|
|
||||||
|
|
||||||
inline Event(Event&& a) : m_info(a.m_info), m_sender(a.m_sender), m_object(std::move(a.m_object)) {}
|
|
||||||
|
|
||||||
inline operator T() { return m_object; }
|
|
||||||
|
|
||||||
friend class EventCenter;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T = std::monostate>
|
|
||||||
struct Observer {
|
|
||||||
EventInfo<T> m_info;
|
|
||||||
Mod* m_mod;
|
|
||||||
std::function<void(Event<T> const&)> m_callback;
|
|
||||||
|
|
||||||
template <typename U = std::monostate>
|
|
||||||
inline Observer<U>* into() {
|
|
||||||
return reinterpret_cast<Observer<U>*>(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GEODE_DLL EventCenter {
|
|
||||||
public:
|
|
||||||
std::map<Mod*, std::map<std::string, std::vector<Observer<std::monostate>*>>> m_observers;
|
|
||||||
static EventCenter* shared;
|
|
||||||
public:
|
|
||||||
|
|
||||||
EventCenter();
|
|
||||||
static EventCenter* get();
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void send(Event<T> n, Mod* m) {
|
|
||||||
for (auto& obs : m_observers[m][n.selector()]) {
|
|
||||||
obs->template into<T>()->m_callback(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void broadcast(Event<T> n) {
|
|
||||||
for (auto& [k, v] : m_observers) {
|
|
||||||
for (auto& obs : v[n.selector()]) {
|
|
||||||
obs->template into<T>()->m_callback(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = std::monostate>
|
|
||||||
Observer<std::monostate>* registerObserver(Mod* m, EventInfo<T> info, std::function<void(Event<T> const&)> cb) {
|
|
||||||
Observer<T>* ob = new Observer<T>;
|
|
||||||
ob->m_info = info;
|
|
||||||
ob->m_callback = cb;
|
|
||||||
ob->m_mod = m;
|
|
||||||
|
|
||||||
m_observers[m][info.selector].push_back(ob->into());
|
|
||||||
|
|
||||||
return ob->into();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = std::monostate>
|
|
||||||
Observer<std::monostate>* registerObserver(Mod* m, std::string sel, std::function<void(Event<T> const&)> cb) {
|
|
||||||
return registerObserver(m, EventInfo<T>(sel), cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = std::monostate>
|
|
||||||
inline Observer<std::monostate>* registerObserver(std::string sel, std::function<void(Event<T> const&)> cb);
|
|
||||||
|
|
||||||
template <typename T = std::monostate>
|
|
||||||
inline Observer<std::monostate>* registerObserver(EventInfo<T> info, std::function<void(Event<T> const&)> cb);
|
|
||||||
|
|
||||||
void unregisterObserver(Observer<std::monostate>* ob);
|
|
||||||
std::vector<Observer<std::monostate>*> getObservers(std::string selector, Mod* m);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#define _$observe3(sel, T, data, ctr) \
|
|
||||||
void $_observer##ctr(geode::Event<T> const&); \
|
|
||||||
static auto $_throw##ctr = (([](){ \
|
|
||||||
geode::Interface::get()->scheduleOnLoad(+[](Mod* m) { \
|
|
||||||
geode::EventCenter::get()->registerObserver<T>( \
|
|
||||||
m, sel, $_observer##ctr \
|
|
||||||
); \
|
|
||||||
}); \
|
|
||||||
})(), 0); \
|
|
||||||
void $_observer##ctr(geode::Event<T> const& data)
|
|
||||||
|
|
||||||
#define _$observe1(sel, ctr) _$observe3(sel, std::monostate, , ctr)
|
|
||||||
|
|
||||||
#define $observe(...) GEODE_INVOKE(GEODE_CONCAT(_$observe, GEODE_NUMBER_OF_ARGS(__VA_ARGS__)), __VA_ARGS__, __COUNTER__)
|
|
||||||
|
|
|
@ -59,15 +59,9 @@ namespace geode {
|
||||||
|
|
||||||
using loadfn_t = void(*)(Mod*);
|
using loadfn_t = void(*)(Mod*);
|
||||||
|
|
||||||
struct ScheduledExport {
|
|
||||||
std::string m_selector;
|
|
||||||
std::variant<unknownmemfn_t, unknownfn_t> m_func;
|
|
||||||
};
|
|
||||||
|
|
||||||
Mod* m_mod = nullptr;
|
Mod* m_mod = nullptr;
|
||||||
std::vector<ScheduledHook> m_scheduledHooks;
|
std::vector<ScheduledHook> m_scheduledHooks;
|
||||||
std::vector<ScheduledLog> m_scheduledLogs;
|
std::vector<ScheduledLog> m_scheduledLogs;
|
||||||
std::vector<ScheduledExport> m_scheduledExports;
|
|
||||||
std::vector<loadfn_t> m_scheduledFunctions;
|
std::vector<loadfn_t> m_scheduledFunctions;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -160,17 +154,6 @@ namespace geode {
|
||||||
inline Log Log::get() {
|
inline Log Log::get() {
|
||||||
return Mod::get()->log();
|
return Mod::get()->log();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline Observer<std::monostate>* EventCenter::registerObserver(std::string sel, std::function<void(Event<T> const&)> cb) {
|
|
||||||
return registerObserver(Mod::get(), EventInfo<T>(sel), cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline Observer<std::monostate>* EventCenter::registerObserver(EventInfo<T> info, std::function<void(Event<T> const&)> cb) {
|
|
||||||
return registerObserver(Mod::get(), info, cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char* operator"" _spr(const char* str, size_t) {
|
inline const char* operator"" _spr(const char* str, size_t) {
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <Macros.hpp>
|
#include <Macros.hpp>
|
||||||
#include "Types.hpp"
|
#include "Types.hpp"
|
||||||
#include "Hook.hpp"
|
#include "Hook.hpp"
|
||||||
#include "Event.hpp"
|
|
||||||
#include "../utils/types.hpp"
|
#include "../utils/types.hpp"
|
||||||
#include "../utils/Result.hpp"
|
#include "../utils/Result.hpp"
|
||||||
#include "../utils/VersionInfo.hpp"
|
#include "../utils/VersionInfo.hpp"
|
||||||
|
@ -335,37 +334,6 @@ namespace geode {
|
||||||
Severity severity
|
Severity severity
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Exports an internal function. You can use this
|
|
||||||
* for mod interoperability.
|
|
||||||
* @param selector mod-specific string identifier
|
|
||||||
* for your function
|
|
||||||
* @param ptr pointer to your exported function
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
void exportAPIFunction(std::string const& selector, T ptr) {
|
|
||||||
EventCenter::get()->registerObserver<T*>(this, selector, [ptr](Event<T*> const& n) {
|
|
||||||
//*reinterpret_cast<T*>(n.object<void*>()) = ptr;
|
|
||||||
*n.object() = ptr;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imports an internal function. You can use this
|
|
||||||
* for mod interoperability.
|
|
||||||
* @param selector Mod-specific string identifier
|
|
||||||
* for your function
|
|
||||||
* @param source Mod that the API function originates
|
|
||||||
* from
|
|
||||||
* @returns Pointer to the external function
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
T importAPIFunction(std::string const& selector, Mod* source) {
|
|
||||||
T out;
|
|
||||||
EventCenter::get()->send(Event(selector, &out, nullptr), source);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all hooks owned by this Mod
|
* Get all hooks owned by this Mod
|
||||||
* @returns Vector of hooks
|
* @returns Vector of hooks
|
||||||
|
|
Loading…
Reference in a new issue