cleanup old field remnants without abi break

This commit is contained in:
altalk23 2024-06-20 11:48:15 +03:00
parent fdb473ac7c
commit 34e51ff868
2 changed files with 24 additions and 66 deletions
loader
include/Geode/modify
src/hooks

View file

@ -53,11 +53,6 @@ namespace geode::modifier {
GEODE_DLL size_t getFieldIndexForClass(char const* name);
template <class Parent>
concept HasFields = requires {
typename Parent::Fields;
};
template <class Parent, class Base>
class FieldIntermediate {
using Intermediate = Modify<Parent, Base>;
@ -69,74 +64,39 @@ namespace geode::modifier {
// the constructor that constructs the fields.
// we construct the Parent first,
static void fieldConstructor(void* offsetField) {
if constexpr (HasFields<Parent>) {
(void) new (offsetField) typename Parent::Fields();
}
else {
std::array<std::byte, sizeof(Parent)> parentContainer;
auto parent = new (parentContainer.data()) Parent();
parent->Intermediate::~Intermediate();
std::memcpy(
offsetField,
std::launder(&parentContainer[sizeof(Intermediate)]),
sizeof(Parent) - sizeof(Intermediate)
);
}
(void) new (offsetField) typename Parent::Fields();
}
static void fieldDestructor(void* offsetField) {
if constexpr (HasFields<Parent>) {
static_cast<typename Parent::Fields*>(offsetField)->~Fields();
}
else {
std::array<std::byte, sizeof(Parent)> parentContainer;
auto parent = new (parentContainer.data()) Intermediate();
std::memcpy(
std::launder(&parentContainer[sizeof(Intermediate)]),
offsetField,
sizeof(Parent) - sizeof(Intermediate)
);
static_cast<Parent*>(parent)->Parent::~Parent();
}
static_cast<typename Parent::Fields*>(offsetField)->~Fields();
}
auto self() {
if constexpr (HasFields<Parent>) {
// get the this pointer of the base
// field intermediate is the first member of Modify
// meaning we canget the base from ourself
auto node = reinterpret_cast<Parent*>(reinterpret_cast<std::byte*>(this) - sizeof(Base));
static_assert(sizeof(Base) == offsetof(Parent, m_fields), "offsetof not correct");
// get the this pointer of the base
// field intermediate is the first member of Modify
// meaning we can get the base from ourself
auto node = reinterpret_cast<Parent*>(reinterpret_cast<std::byte*>(this) - sizeof(Base));
static_assert(sizeof(Base) == offsetof(Parent, m_fields), "offsetof not correct");
// generating the container if it doesn't exist
auto container = FieldContainer::from(node, typeid(Base).name());
// generating the container if it doesn't exist
auto container = FieldContainer::from(node, typeid(Base).name());
// the index is global across all mods, so the
// function is defined in the loader source
static size_t index = getFieldIndexForClass(typeid(Base).name());
// the index is global across all mods, so the
// function is defined in the loader source
static size_t index = getFieldIndexForClass(typeid(Base).name());
// the fields are actually offset from their original
// offset, this is done to save on allocation and space
auto offsetField = container->getField(index);
if (!offsetField) {
offsetField = container->setField(
index, sizeof(typename Parent::Fields), &FieldIntermediate::fieldDestructor
);
// the fields are actually offset from their original
// offset, this is done to save on allocation and space
auto offsetField = container->getField(index);
if (!offsetField) {
offsetField = container->setField(
index, sizeof(typename Parent::Fields), &FieldIntermediate::fieldDestructor
);
FieldIntermediate::fieldConstructor(offsetField);
}
return reinterpret_cast<typename Parent::Fields*>(offsetField);
}
else {
static_assert(!HasFields<Parent>, "Parent must have a Fields struct");
FieldIntermediate::fieldConstructor(offsetField);
}
return reinterpret_cast<typename Parent::Fields*>(offsetField);
}
auto operator->() {

View file

@ -17,7 +17,6 @@ struct ProxyCCNode;
class GeodeNodeMetadata final : public cocos2d::CCObject {
private:
FieldContainer* m_fieldContainer;
std::unordered_map<std::string, FieldContainer*> m_classFieldContainers;
std::string m_id = "";
Ref<Layout> m_layout = nullptr;
@ -29,10 +28,9 @@ private:
friend class ProxyCCNode;
friend class cocos2d::CCNode;
GeodeNodeMetadata() : m_fieldContainer(new FieldContainer()) {}
GeodeNodeMetadata() {}
virtual ~GeodeNodeMetadata() {
delete m_fieldContainer;
for (auto& [_, container] : m_classFieldContainers) {
delete container;
}
@ -65,7 +63,7 @@ public:
}
FieldContainer* getFieldContainer() {
return m_fieldContainer;
return nullptr;
}
FieldContainer* getFieldContainer(char const* forClass) {