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/InternalMacros.hpp"
|
||||
#include "loader/GeodeLoader.hpp"
|
||||
#include "loader/API.hpp"
|
||||
#include "loader/Dispatcher.hpp"
|
||||
|
||||
using namespace geode::modifier;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "../codegen-base/Macros.hpp"
|
||||
#include "../utils/include.hpp"
|
||||
#include "Mod.hpp"
|
||||
|
@ -6,65 +8,86 @@
|
|||
#include <vector>
|
||||
|
||||
namespace geode {
|
||||
class Dispatcher;
|
||||
|
||||
struct GEODE_DLL dispatch_handle {
|
||||
void* handle;
|
||||
class Dispatcher;
|
||||
|
||||
struct GEODE_DLL dispatch_handle {
|
||||
void* handle;
|
||||
|
||||
dispatch_handle() = delete;
|
||||
dispatch_handle(dispatch_handle&& d) : handle(d.handle) {}
|
||||
dispatch_handle(dispatch_handle const& d) : handle(d.handle) {}
|
||||
dispatch_handle() = delete;
|
||||
dispatch_handle(dispatch_handle const& d) : handle(d.handle) {}
|
||||
|
||||
template <typename T>
|
||||
std::function<T> get() {
|
||||
*reinterpret_cast<std::function<T>*>(this->handle);
|
||||
}
|
||||
template <typename T>
|
||||
std::function<T> into() {
|
||||
*reinterpret_cast<std::function<T>*>(this->handle);
|
||||
}
|
||||
|
||||
template <typename R, typename ...Args>
|
||||
R call(Args... args) {
|
||||
return this->get<std::function<R(Args...)>>()(args...);
|
||||
}
|
||||
|
||||
private:
|
||||
dispatch_handle(void* h) : handle(h) {}
|
||||
friend class Dispatcher;
|
||||
};
|
||||
template <typename R, typename ...Args>
|
||||
R call(Args... args) {
|
||||
return this->into<std::function<R(Args...)>>()(args...);
|
||||
}
|
||||
|
||||
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
|
||||
bool operator<(dispatch_handle const& b) const {
|
||||
return handle < b.handle;
|
||||
}
|
||||
|
||||
std::vector<dispatch_handle> _getHandles(std::string const& a);
|
||||
std::pair<string, Mod*> _getInfo(dispatch_handle u);
|
||||
bool operator==(dispatch_handle const& b) const {
|
||||
return handle == b.handle;
|
||||
}
|
||||
|
||||
private:
|
||||
dispatch_handle(void* h) : handle(h) {}
|
||||
|
||||
void _removeFunction(dispatch_handle u);
|
||||
dispatch_handle _addFunction(Mod* m, std::string const& a);
|
||||
template <typename T>
|
||||
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>
|
||||
std::function<T> _fromOpaque(void* f) {
|
||||
*reinterpret_cast<std::function<T>*>(f);
|
||||
}
|
||||
Dispatcher() {}
|
||||
|
||||
template <typename T>
|
||||
void* _toOpaque(std::function<T> f) {
|
||||
return reinterpret_cast<void*>(new std::function<T>(f));
|
||||
}
|
||||
public:
|
||||
static Dispatcher* get();
|
||||
public:
|
||||
static Dispatcher* get();
|
||||
|
||||
template <typename T>
|
||||
std::vector<std::function<T>> getSelectors(std::string_view const& a) {
|
||||
return geode::vector_utils::map(_getSelectors(a), [this](std::pair<dispatch_handle, void*> selector) {
|
||||
return _fromOpaque<T>(selector.second);
|
||||
});
|
||||
}
|
||||
template <typename T>
|
||||
std::vector<std::function<T>> getFunctions(std::string const& a) {
|
||||
return geode::vector_utils::map(getFunctions_(a), [this](dispatch_handle fn) {
|
||||
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*);
|
||||
|
||||
struct ScheduledExport {
|
||||
std::string m_selector;
|
||||
std::variant<unknownmemfn_t, unknownfn_t> m_func;
|
||||
};
|
||||
|
||||
Mod* m_mod = nullptr;
|
||||
std::vector<ScheduledHook> m_scheduledHooks;
|
||||
std::vector<ScheduledLog> m_scheduledLogs;
|
||||
std::vector<ScheduledExport> m_scheduledExports;
|
||||
std::vector<loadfn_t> m_scheduledFunctions;
|
||||
|
||||
public:
|
||||
|
@ -160,17 +154,6 @@ namespace geode {
|
|||
inline Log Log::get() {
|
||||
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) {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <Macros.hpp>
|
||||
#include "Types.hpp"
|
||||
#include "Hook.hpp"
|
||||
#include "Event.hpp"
|
||||
#include "../utils/types.hpp"
|
||||
#include "../utils/Result.hpp"
|
||||
#include "../utils/VersionInfo.hpp"
|
||||
|
@ -335,37 +334,6 @@ namespace geode {
|
|||
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
|
||||
* @returns Vector of hooks
|
||||
|
|
Loading…
Reference in a new issue