You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: tutorials/hookpriority.md
+94-40Lines changed: 94 additions & 40 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,79 +9,80 @@ The syntax, as previously mentioned in the [Hooking tutorial](/tutorials/modify.
9
9
```cpp
10
10
class $modify(cocos2d::CCLabelBMFont) {
11
11
static void onModify(auto& self) {
12
-
if (!self.setHookPriority("cocos2d::CCLabelBMFont::init", 1'000'000'000)) {
12
+
if (!self.setHookPriorityPost("cocos2d::CCLabelBMFont::init", Priority::First)) {
13
+
geode::log::warn("Failed to set hook priority.");
14
+
}
15
+
if (!self.setHookPriorityPre("cocos2d::CCLabelBMFont::setString", Priority::Late)) {
16
+
geode::log::warn("Failed to set hook priority.");
17
+
}
18
+
if (!self.setHookPriorityAfterPost("cocos2d::CCLabelBMFont::limitLabelWidth", "geode.node-ids")) {
13
19
geode::log::warn("Failed to set hook priority.");
14
20
}
15
21
}
16
22
};
17
23
```
18
24
19
-
A function with no explicit priority is given the priority of 0.
25
+
A function with no explicit priority is given the priority of `Priority::Normal`.
20
26
21
-
The initial call to the function starts with the hook with lowest priority (`INT_MIN`).
22
-
Each call to the original function increases the current priority, with the original function being at the highest priority of `INT_MAX`.
23
-
As each function in the chain returns, priority is decreased until the function with lowest priority returns.
24
-
At this point, the function call is finished and execution returns to the original caller.
27
+
There are 7 pre-assigned priority values recommended for use: `First, VeryEarly, Early, Normal, Late, VeryLate, Last`. Arithmetic on these values are also possible, although not recommended: `Priority::Early + 2`, meaning 2 internal units later than `Early`.
25
28
26
-
An example is shown by this diagram and its accompanying code:
29
+
There are also 2 prefixes related with priorities: `Pre, Post`. Pre priorities sort based on code called **before** the original call, and Post priorities sort based on code called **after** the original call.
27
30
28
-

31
+
Here's an example of the pre/post differentiation:
29
32
30
33
```cpp
31
-
// priority of -1'000'000
32
-
void fn_lowest() {
34
+
void functionEarlyPre() {
33
35
log::info("statement 1");
34
-
fn();
35
-
log::info("statement 6");
36
+
function();
36
37
}
37
-
38
-
// priority of -100
39
-
void fn_neg100() {
40
-
// code here happens prior to statement 2 and after statement 1
41
-
fn();
42
-
log::info("statement 5");
38
+
void functionLatePre() {
39
+
log::info("statement 3");
40
+
function();
43
41
}
44
-
45
-
// priority of 0
46
-
void fn_default() {
42
+
void functionNormal() {
47
43
log::info("statement 2");
48
-
fn();
44
+
function();
45
+
log::info("statement 5");
46
+
}
47
+
void functionEarlyPost() {
48
+
function();
49
49
log::info("statement 4");
50
50
}
51
-
52
-
// priority of 1'000'000
53
-
void fn_highest() {
54
-
log::info("statement 3");
55
-
fn();
56
-
// code here will happen prior to statement 4 and after the original function call
51
+
void functionLatePost() {
52
+
function();
53
+
log::info("statement 6");
57
54
}
58
55
```
59
56
60
-
The statements will be printed in numerical order, from "statement 1" to "statement 6".
57
+
## Guidelines
61
58
62
-
A developer may also choose to not call the original, which means hooks that are a higher priority than the developer's hooks (including the original function) will not be executed.
59
+
**Always use** the before/after functions instead of doing arithmetic on priorities! Unless circular priorities happen, it is guaranteed for them to work consistently even if the other mods change their priorities.
63
60
64
-
## Guidelines
61
+
- If you want to run your code after some other mod's code before calling original, use `setHookPriorityAfterPre`.
62
+
63
+
- If you want to run your code before some other mod's code and before calling original, use `setHookPriorityBeforePre`.
64
+
65
+
- If you want to run your code before some other mod's code after calling original, use `setHookPriorityBeforePost`.
66
+
67
+
- If you want to run your code after some other mod's ccodeand after calling original, use `setHookPriorityAfterPost`.
65
68
66
-
Using hook priorities of `INT_MIN` and `INT_MAX - 1` is **strongly discouraged** for mod compatibility.
67
-
There are four billion possible priorities! Please take advantage of them.
69
+
Using raw numbers as priorities is **strongly discouraged** for mod compatibility.
70
+
There are tools for mod compatibilities! Please take advantage of them.
68
71
69
-
- If you want your function to run _before_ all other code, including the original function, use a very low hook priority and call the original function _after_ your code.
72
+
- If you want your function to run _before_ all other code, including the original function, use `Priority::First` with `setHookPriorityPre` and call the original function _after_ your code.
70
73
71
-
- If you want your function to run _after_ all other code, use a very low hook priority and call the original function at the start of your hook.
74
+
- If you want your function to run _after_ all other code, use `Priority::Last` with `setHookPriorityPost` and call the original function at the start of your hook.
72
75
73
-
- If you want your function to run _after_ the original function, but _before_ other hooks, use a high hook priority and call the original function at the start.
76
+
- If you want your function to run _after_ the original function, but _before_ other hooks, use `Priority::First` with `setHookPriorityPost` and call the original function at the start.
74
77
75
-
- If you're _reimplementing_ the original function and do not call the original, use a very high hook priority.
78
+
- If you're _reimplementing_ the original function and do not call the original, use `Priority::Last` with `setHookPriorityPre`.
76
79
77
80
Obviously, these are not strict rules. Feel free to choose the hook priority that best fits your situation.
78
81
79
82
## Notes
80
83
81
84
This section details some additional tricks to the hook priority system.
82
85
83
-
- A hook priority of `INT_MAX` will not function as expected, as the original function also has a priority of `INT_MAX`.
84
-
85
86
- Be sure you have the function name correct in `setHookPriority`! The namespace must be included.
86
87
87
88
- While the current priority is preserved across function calls, it is not preserved in other situations. For example:
@@ -108,8 +109,61 @@ This section details some additional tricks to the hook priority system.
108
109
}
109
110
```
110
111
111
-
- Using a stub function with a very low hook priority is an effective way to disable a function. In this scenario, it becomes impossible for other mods to call the original (as their hooks wouldn't be called either), so this is not recommended.
112
+
- Using a stub function with `Priority::First` with `Pre` or `Priority::Last` with `Post` is an effective way to disable a function. In this scenario, it becomes impossible for other mods to call the original (as their hooks wouldn't be called either), so this is not recommended.
113
+
114
+
- Pre/Post values embedded into `Priority::` do exist, but they are not that recommended as arithmetic on them can be confusing. (Positive becomes negative for Post)
112
115
113
116
- Manual hooks can have their priorities set through the [Hook::setPriority](/classes/geode/Hook/#setPriority) method.
114
117
115
118
- It is not possible to set the priorities of multiple functions with overloaded parameters in the same modify class (as this would require specifying arguments). In this situation, either split the hooks into separate modify classes or manually hook.
119
+
120
+
## Internal Implementation
121
+
122
+
The initial call to the function starts with the hook with lowest priority (internally `INT_MIN`).
123
+
Each call to the original function increases the current priority, with the original function being at the highest priority (internally `INT_MAX`).
124
+
As each function in the chain returns, priority is decreased until the function with lowest priority returns.
125
+
At this point, the function call is finished and execution returns to the original caller.
126
+
127
+
The 7 pre-assigned priorities have the values of `-3000, -2000, -1000, 0, 1000, 2000, 3000` respectively.
128
+
129
+
An example is shown by this diagram and its accompanying code:
130
+
131
+

132
+
133
+
```cpp
134
+
// priority of -1'000'000
135
+
voidfn_lowest() {
136
+
log::info("statement 1");
137
+
fn();
138
+
log::info("statement 6");
139
+
}
140
+
141
+
// priority of -100
142
+
voidfn_neg100() {
143
+
// code here happens prior to statement 2 and after statement 1
144
+
fn();
145
+
log::info("statement 5");
146
+
}
147
+
148
+
// priority of 0
149
+
voidfn_default() {
150
+
log::info("statement 2");
151
+
fn();
152
+
log::info("statement 4");
153
+
}
154
+
155
+
// priority of 1'000'000
156
+
voidfn_highest() {
157
+
log::info("statement 3");
158
+
fn();
159
+
// code here will happen prior to statement 4 and after the original function call
160
+
}
161
+
```
162
+
163
+
The statements will be printed in numerical order, from "statement 1" to "statement 6".
164
+
165
+
A developer may also choose to not call the original, which means hooks that are a higher priority than the developer's hooks (including the original function) will not be executed.
166
+
167
+
### Internal notes
168
+
169
+
- A hook priority of `INT_MAX` will not function as expected, as the original function also has a priority of `INT_MAX`.
0 commit comments