Skip to content

Commit 2f817aa

Browse files
committed
feat: split tests into a separate plugin
1 parent 485cf82 commit 2f817aa

File tree

13 files changed

+274
-124
lines changed

13 files changed

+274
-124
lines changed

src-client/.gitkeep

Whitespace-only changes.

src-server/.gitkeep

Whitespace-only changes.

src-test-client/.gitkeep

Whitespace-only changes.

src-test-server/.gitkeep

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

src/pc/callback/CallbackManager.hpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#pragma once
1+
#pragma once
22

33
#include <algorithm>
44
#include <any>
@@ -12,6 +12,14 @@
1212
#include <type_traits>
1313
#include <vector>
1414

15+
#ifdef PC_EXPORT
16+
#define PCAPI __declspec(dllexport)
17+
#define PCAPI_TEMPLATE
18+
#else
19+
#define PCAPI __declspec(dllimport)
20+
#define PCAPI_TEMPLATE extern
21+
#endif
22+
1523
namespace primordial_core {
1624

1725
template <typename T>
@@ -88,15 +96,15 @@ class CallbackManager {
8896
register_impl<Args...>(name, std::move(f), p);
8997
}
9098

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;
99+
PCAPI CallbackManager() = default;
100+
PCAPI ~CallbackManager() = default;
101+
PCAPI CallbackManager(const CallbackManager&) = delete;
102+
PCAPI CallbackManager& operator=(const CallbackManager&) = delete;
103+
PCAPI CallbackManager(CallbackManager&&) = delete;
104+
PCAPI CallbackManager& operator=(CallbackManager&&) = delete;
97105

98106
public:
99-
static CallbackManager& getInstance() {
107+
PCAPI static CallbackManager& getInstance() {
100108
static CallbackManager instance;
101109
return instance;
102110
}

src/pc/callback/ItemCallbacks.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include "ll/api/memory/Hook.h"
2+
3+
#include "mc/world/gamemode/InteractionResult.h"
4+
#include "mc/world/item/Item.h"
5+
#include "mc/world/item/ItemUsedOnEventContext.h"
6+
7+
LL_AUTO_TYPE_INSTANCE_HOOK(
8+
ItemOnUseHook,
9+
HookPriority::Normal,
10+
Item,
11+
&Item::useOn,
12+
::InteractionResult,
13+
::ItemStack& item,
14+
::Actor& entity,
15+
int x,
16+
int y,
17+
int z,
18+
uchar face,
19+
::Vec3 const& clickPos,
20+
::ItemUsedOnEventContext itemUsedOnEventContext
21+
) {
22+
return origin(item, entity, x, y, z, face, clickPos, itemUsedOnEventContext);
23+
}

src/pc/mod/PrimordialCore.cpp

Lines changed: 5 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,36 @@
1-
#include "pc/mod/PrimordialCore.h"
1+
#include "pc/mod/PrimordialCore.h"
22
#include "pc/callback/CallbackManager.hpp"
33
#include "pc/world/Game.h"
44

55
#include "ll/api/mod/RegisterHelper.h"
66

77
namespace primordial_core {
88

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-
229
PrimordialCore& PrimordialCore::getInstance() {
2310
static PrimordialCore instance;
2411
return instance;
2512
}
2613

2714
bool PrimordialCore::load() {
28-
getSelf().getLogger().debug("Loading...");
15+
getLogger().debug("Loading...");
2916
// 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-
10817
return true;
10918
}
11019

11120
bool PrimordialCore::enable() {
112-
getSelf().getLogger().debug("Enabling...");
21+
getLogger().debug("Enabling...");
11322
// Code for enabling the mod goes here.
11423
return true;
11524
}
11625

11726
bool PrimordialCore::disable() {
118-
getSelf().getLogger().debug("Disabling...");
27+
getLogger().debug("Disabling...");
11928
// Code for disabling the mod goes here.
12029
return true;
12130
}
12231

12332
bool PrimordialCore::unload() {
124-
getSelf().getLogger().debug("Unloading...");
33+
getLogger().debug("Unloading...");
12534
// Code for unloading the mod goes here.
12635
return true;
12736
}

0 commit comments

Comments
 (0)