Skip to content

Commit 485cf82

Browse files
committed
feat: Game::preventDefault
1 parent 9fee6fb commit 485cf82

File tree

8 files changed

+208
-67
lines changed

8 files changed

+208
-67
lines changed

src/mod/PrimordialCore.cpp

Lines changed: 0 additions & 66 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#pragma once
2+
13
#include <algorithm>
24
#include <any>
35
#include <functional>
@@ -86,7 +88,19 @@ class CallbackManager {
8688
register_impl<Args...>(name, std::move(f), p);
8789
}
8890

91+
CallbackManager() = default;
92+
~CallbackManager() = default;
93+
CallbackManager(const CallbackManager&) = delete;
94+
CallbackManager& operator=(const CallbackManager&) = delete;
95+
CallbackManager(CallbackManager&&) = delete;
96+
CallbackManager& operator=(CallbackManager&&) = delete;
97+
8998
public:
99+
static CallbackManager& getInstance() {
100+
static CallbackManager instance;
101+
return instance;
102+
}
103+
90104
template <typename Callable>
91105
void addCallback(const std::string& name, Callable&& cb, int priority = 0) {
92106
using traits = function_traits<std::decay_t<Callable>>;

src/pc/mod/PrimordialCore.cpp

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#include "pc/mod/PrimordialCore.h"
2+
#include "pc/callback/CallbackManager.hpp"
3+
#include "pc/world/Game.h"
4+
5+
#include "ll/api/mod/RegisterHelper.h"
6+
7+
namespace primordial_core {
8+
9+
void Hooked_OriginalFunction(CallbackManager& mgr, int damage) {
10+
Game::EventScope scope;
11+
12+
mgr.invokeCallback("OnTakeDamage", damage);
13+
14+
if (scope.isPrevented()) {
15+
std::cout << "Original default functionality was prevented by a callback!" << std::endl;
16+
return; // 直接返回,从而阻止原函数的默认行为
17+
}
18+
19+
std::cout << "Executing default original functionality. Damage: " << damage << std::endl;
20+
}
21+
22+
PrimordialCore& PrimordialCore::getInstance() {
23+
static PrimordialCore instance;
24+
return instance;
25+
}
26+
27+
bool PrimordialCore::load() {
28+
getSelf().getLogger().debug("Loading...");
29+
// Code for loading the mod goes here.
30+
31+
CallbackManager& mgr = CallbackManager::getInstance();
32+
33+
// 添加不同签名的事件
34+
mgr.addCallback(
35+
"OnLogin",
36+
[](std::string user, int age) { std::cout << "[User] " << user << " logged in. Age: " << age << "\n"; },
37+
10
38+
);
39+
40+
mgr.addCallback("OnSystem", [](int code) { std::cout << "Code: " << code << "\n"; });
41+
42+
// 高优先级测试
43+
mgr.addCallback(
44+
"OnLogin",
45+
[](std::string user, int) { std::cout << "[Admin] Priority check for " << user << "\n"; },
46+
100
47+
);
48+
49+
// 调用
50+
std::cout << "--- Triggering Login ---\n";
51+
// 注意:必须显式构造std::string,否则推导为const char*导致类型不匹配
52+
mgr.invokeCallback("OnLogin", std::string("Alice"), 25);
53+
54+
std::cout << "\n--- Triggering System ---\n";
55+
mgr.invokeCallback("OnSystem", 404);
56+
57+
// 回调 A:不阻止默认行为
58+
mgr.addCallback("OnTakeDamage", [](int damage) { std::cout << "Callback A saw damage: " << damage << "\n"; }, 10);
59+
60+
// 回调 B:满足特定条件时阻止默认行为
61+
mgr.addCallback(
62+
"OnTakeDamage",
63+
[](int damage) {
64+
if (damage > 100) {
65+
std::cout << "Callback B: Damage too high! Preventing default.\n";
66+
Game::getInstance().preventDefault(); // 直接调用,无需返回特定类型
67+
}
68+
},
69+
20
70+
);
71+
72+
std::cout << "=== 测试1:不会被阻止(damage=50) ===\n";
73+
Hooked_OriginalFunction(mgr, 50);
74+
75+
std::cout << "\n=== 测试2:会被回调 B 阻止(damage=150) ===\n";
76+
Hooked_OriginalFunction(mgr, 150);
77+
78+
// 测试嵌套调用
79+
std::cout << "\n=== 测试3:嵌套调用测试 ===\n";
80+
mgr.addCallback(
81+
"OnTakeDamage",
82+
[&mgr](int damage) {
83+
std::cout << "Callback C: Triggering nested event\n";
84+
Game::EventScope scope;
85+
mgr.invokeCallback("OnNestedEvent", damage);
86+
},
87+
30
88+
);
89+
90+
mgr.addCallback("OnNestedEvent", [](int damage) {
91+
std::cout << "Nested callback: Damage = " << damage << "\n";
92+
// 这里调用 preventDefault 不会影响外层 OnTakeDamage 的状态
93+
Game::getInstance().preventDefault();
94+
});
95+
96+
{
97+
Game::EventScope scope;
98+
mgr.invokeCallback("OnTakeDamage", 200);
99+
std::cout << "Outer scope prevented: " << (scope.isPrevented() ? "Yes" : "No") << std::endl;
100+
}
101+
102+
{
103+
Game::EventScope scope;
104+
mgr.invokeCallback("OnTakeDamage", 20);
105+
std::cout << "Outer scope prevented: " << (scope.isPrevented() ? "Yes" : "No") << std::endl;
106+
}
107+
108+
return true;
109+
}
110+
111+
bool PrimordialCore::enable() {
112+
getSelf().getLogger().debug("Enabling...");
113+
// Code for enabling the mod goes here.
114+
return true;
115+
}
116+
117+
bool PrimordialCore::disable() {
118+
getSelf().getLogger().debug("Disabling...");
119+
// Code for disabling the mod goes here.
120+
return true;
121+
}
122+
123+
bool PrimordialCore::unload() {
124+
getSelf().getLogger().debug("Unloading...");
125+
// Code for unloading the mod goes here.
126+
return true;
127+
}
128+
129+
} // namespace primordial_core
130+
131+
LL_REGISTER_MOD(primordial_core::PrimordialCore, primordial_core::PrimordialCore::getInstance());

src/pc/world/Game.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "pc/world/Game.h"
2+
3+
namespace primordial_core {
4+
5+
thread_local std::vector<bool> Game::prevent_stack;
6+
7+
Game& Game::getInstance() {
8+
static Game instance;
9+
return instance;
10+
}
11+
12+
void Game::preventDefault() {
13+
if (!prevent_stack.empty()) {
14+
prevent_stack.back() = true;
15+
}
16+
}
17+
18+
bool Game::_isDefaultPrevented() const {
19+
if (prevent_stack.empty()) return false;
20+
return prevent_stack.back();
21+
}
22+
23+
Game::EventScope::EventScope() { Game::prevent_stack.push_back(false); }
24+
25+
Game::EventScope::~EventScope() { Game::prevent_stack.pop_back(); }
26+
27+
bool Game::EventScope::isPrevented() const { return Game::getInstance()._isDefaultPrevented(); }
28+
29+
} // namespace primordial_core

src/pc/world/Game.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
3+
#include <vector>
4+
5+
namespace primordial_core {
6+
7+
class Game {
8+
private:
9+
Game() = default;
10+
~Game() = default;
11+
Game(const Game&) = delete;
12+
Game& operator=(const Game&) = delete;
13+
Game(Game&&) = delete;
14+
Game& operator=(Game&&) = delete;
15+
16+
static thread_local std::vector<bool> prevent_stack;
17+
18+
public:
19+
static Game& getInstance();
20+
21+
void preventDefault();
22+
bool _isDefaultPrevented() const;
23+
24+
class EventScope {
25+
public:
26+
EventScope();
27+
~EventScope();
28+
29+
bool isPrevented() const;
30+
};
31+
};
32+
33+
} // namespace primordial_core

xmake.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ target("primordial-core") -- Change this to your mod name.
2929
set_kind("shared")
3030
set_languages("c++20")
3131
set_symbols("debug")
32-
add_headerfiles("src/**.h")
32+
add_headerfiles("src/**.h", "src/**.hpp")
3333
add_files("src/**.cpp")
3434
add_includedirs("src")
3535
if is_config("target_type", "server") then

0 commit comments

Comments
 (0)