Skip to content

Commit a3b2741

Browse files
committed
test
1 parent f140371 commit a3b2741

File tree

3 files changed

+140
-3
lines changed

3 files changed

+140
-3
lines changed

include/NodeModding.h

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,135 @@
1717

1818
namespace AlphaUtils {
1919

20+
static uint64_t fnv1aHash(char const* str) {
21+
uint64_t hash = 0xcbf29ce484222325;
22+
while (*str) {
23+
hash ^= *str++;
24+
hash *= 0x100000001b3;
25+
}
26+
return hash;
27+
}
28+
29+
template <typename T>
30+
class NoHashHasher;
31+
32+
template <>
33+
class NoHashHasher<uint64_t> {
34+
public:
35+
size_t operator()(uint64_t key) const {
36+
return key;
37+
}
38+
};
39+
40+
class ObjectFieldContainer {
41+
private:
42+
std::vector<void*> m_containedFields;
43+
std::vector<std::function<void(void*)>> m_destructorFunctions;
44+
45+
public:
46+
~ObjectFieldContainer() {
47+
for (auto i = 0u; i < m_containedFields.size(); i++) {
48+
if (m_destructorFunctions[i] && m_containedFields[i]) {
49+
m_destructorFunctions[i](m_containedFields[i]);
50+
operator delete(m_containedFields[i]);
51+
}
52+
}
53+
}
54+
55+
void* getField(size_t index) {
56+
while (m_containedFields.size() <= index) {
57+
m_containedFields.push_back(nullptr);
58+
m_destructorFunctions.push_back(nullptr);
59+
}
60+
return m_containedFields.at(index);
61+
}
62+
63+
void* setField(size_t index, size_t size, std::function<void(void*)> destructor) {
64+
m_containedFields.at(index) = operator new(size);
65+
m_destructorFunctions.at(index) = std::move(destructor);
66+
return m_containedFields.at(index);
67+
}
68+
69+
static ObjectFieldContainer* from(cocos2d::CCObject* node, char const* forClass) {
70+
//return node->getFieldContainer(forClass);
71+
}
72+
};
73+
74+
class ObjectMetadata final : public cocos2d::CCNode {
75+
private:
76+
std::unordered_map<uint64_t, ObjectFieldContainer*, NoHashHasher<uint64_t>> m_classFieldContainers;
77+
78+
friend class cocos2d::CCObject;
79+
80+
ObjectMetadata() {}
81+
82+
virtual ~ObjectMetadata() {
83+
for (auto& [_, container] : m_classFieldContainers) {
84+
delete container;
85+
}
86+
}
87+
88+
public:
89+
static ObjectMetadata* set(CCObject* target) {
90+
if (!target) return nullptr;
91+
92+
auto meta = new ObjectMetadata();
93+
meta->autorelease();
94+
95+
target->m_pUserObject = meta;
96+
meta->retain();
97+
98+
return meta;
99+
}
100+
101+
ObjectFieldContainer* getFieldContainer(char const* forClass) {
102+
auto hash = fnv1aHash(forClass);
103+
104+
auto& container = m_classFieldContainers[hash];
105+
if (!container) {
106+
container = new ObjectFieldContainer();
107+
}
108+
109+
return container;
110+
}
111+
};
112+
113+
GEODE_DLL size_t getFieldIndexForClass(char const* name);
114+
115+
template <class Parent, class Base>
116+
class ObjectFieldIntermediate {
117+
using Intermediate = Modify<Parent, Base>;
118+
std::aligned_storage_t<std::alignment_of_v<Base>, std::alignment_of_v<Base>> m_padding;
119+
120+
public:
121+
static void fieldConstructor(void* offsetField) {
122+
(void) new (offsetField) typename Parent::Fields();
123+
}
124+
125+
static void fieldDestructor(void* offsetField) {
126+
static_cast<typename Parent::Fields*>(offsetField)->~Fields();
127+
}
128+
129+
auto self() {
130+
131+
auto node = reinterpret_cast<Parent*>(reinterpret_cast<std::byte*>(this) - sizeof(Base));
132+
auto container = ObjectFieldContainer::from(node, typeid(Base).name());
133+
static size_t index = getFieldIndexForClass(typeid(Base).name());
134+
auto offsetField = container->getField(index);
135+
if (!offsetField) {
136+
offsetField = container->setField(
137+
index, sizeof(typename Parent::Fields), &ObjectFieldIntermediate::fieldDestructor
138+
);
139+
ObjectFieldIntermediate::fieldConstructor(offsetField);
140+
}
141+
142+
return reinterpret_cast<typename Parent::Fields*>(offsetField);
143+
}
144+
auto operator->() {
145+
return this->self();
146+
}
147+
};
148+
20149
struct ModifyInfo {
21150
int priority;
22151
std::function<void(cocos2d::CCNode*)> method;
@@ -39,6 +168,12 @@ namespace AlphaUtils {
39168
static int modifyPrio() { return 0; }
40169
};
41170

171+
template <class Derived>
172+
struct ObjectWrapper : public cocos2d::CCObject {
173+
ObjectFieldIntermediate<Derived, cocos2d::CCObject> m_fields;
174+
static int modifyPrio() { return 0; }
175+
};
176+
42177
template <class T>
43178
class ModifyLoad {
44179
public:
@@ -65,3 +200,5 @@ struct derived : AlphaUtils::NodeWrapper<derived>
65200

66201
#define $nodeModify(...) \
67202
GEODE_INVOKE(GEODE_CONCAT(MODIFY, GEODE_NUMBER_OF_ARGS(__VA_ARGS__)), __VA_ARGS__)
203+
204+
#define $objectModify(...) $nodeModify(__VA_ARGS__)

mod.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"geode": "4.2.0",
2+
"geode": "4.3.0",
33
"gd": {
44
"win": "2.2074",
55
"android": "2.2074",

src/hooks/CCObject.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ using namespace AlphaUtils;
88

99
class $modify(CCObject) {
1010
CCObject* autorelease() {
11-
if (CCNode* node = typeinfo_cast<CCNode*>(this)) {
11+
//if (CCNode* node = typeinfo_cast<CCNode*>(this)) {
1212
NodeModding::get()->handleNode(node);
13-
}
13+
//}
1414
return CCObject::autorelease();
1515
}
1616
};

0 commit comments

Comments
 (0)