Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: 1.0.0-rc.3 #1615

Merged
merged 22 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
23 changes: 23 additions & 0 deletions .github/ISSUE_TEMPLATE/mcclass_member_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: MC class member request
description: Requests for completion of certain minecraft class member variables
title: "[Request]: "
labels: ["enhancement"]
body:
- type: textarea
attributes:
label: Please list all requested class names.
description: Names of all requested classes.
validations:
required: true

- type: textarea
attributes:
label: Do you have a good reason for us to complement these member variables of these mc class? Please write it out.
description: Sufficient reason to convince us to complement the member variables of these mc classes.
validations:
required: true

- type: textarea
attributes:
label: Additional context
description: Add any other context or screenshots about the mc class member request here.
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.0.0-rc.3] - 2025-01-11

### Added

- Added more nbt operator @OEOTYAN
- Added some api to logger @OEOTYAN
- Added itemstack ctor default param @Dofes
- Added some mc class members [#1611]
- Added an issue template for requesting complementary mc class member variables @Lovelylavender4

### Fixed

- Fixed [#1610] @Dofes
- Fixed command @OEOTYAN
- Fixed version prelease parse @OEOTYAN

## [1.0.0-rc.2] - 2025-01-06

### Added
Expand Down Expand Up @@ -733,8 +749,11 @@ For lip and tooth-hub test only.
[#1559]: https://github.com/LiteLDev/LeviLamina/issues/1559
[#1574]: https://github.com/LiteLDev/LeviLamina/issues/1574
[#1582]: https://github.com/LiteLDev/LeviLamina/issues/1582
[#1610]: https://github.com/LiteLDev/LeviLamina/issues/1610
[#1611]: https://github.com/LiteLDev/LeviLamina/issues/1611

[Unreleased]: https://github.com/LiteLDev/LeviLamina/compare/v1.0.0-rc.2...HEAD
[Unreleased]: https://github.com/LiteLDev/LeviLamina/compare/v1.0.0-rc.3...HEAD
[1.0.0-rc.3]: https://github.com/LiteLDev/LeviLamina/compare/v1.0.0-rc.2...v1.0.0-rc.3
[1.0.0-rc.2]: https://github.com/LiteLDev/LeviLamina/compare/v1.0.0-rc.1...v1.0.0-rc.2
[1.0.0-rc.1]: https://github.com/LiteLDev/LeviLamina/compare/v0.13.5...v1.0.0-rc.1
[0.13.5]: https://github.com/LiteLDev/LeviLamina/compare/v0.13.4...v0.13.5
Expand Down
43 changes: 20 additions & 23 deletions docs/main/developer_guides/how_to_guides/hook_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ In [`ll/api/memory/Hook.h`](https://github.com/LiteLDev/LeviLamina/blob/develop/
#define LL_AUTO_INSTANCE_HOOK(DEF_TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...)
```

The AUTO-marked Hooks automatically register, i.e., call the hook() function to register at runtime.
The TYPED-marked Hooks inherit your DEF_TYPE to the specified type.
The `AUTO`-marked Hooks automatically register, i.e., call the `hook()` function to register at runtime.
The `TYPED`-marked Hooks inherit your `DEF_TYPE` to the specified type.

### STATIC_HOOK

Expand All @@ -50,59 +50,56 @@ For hooking member functions.
!!! note
Generally, unless there's a special need, we do not recommend a very high priority; Normal is sufficient.

`TYPE`: The type to which your defined DEF_TYPE is inherited.
`TYPE`: The type to which your defined `DEF_TYPE` is inherited.

`IDENTIFIER`: The identifier used for the Hook lookup function, which can be: [function's decorated name](https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170), function bytecode, function definition.
`IDENTIFIER`: The identifier used for the Hook lookup function, which can be: [function's decorated name](https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170), function bytecode, or function definition.

`RET_TYPE`: The return type of the Hook function.

`...`: The parameter list of the Hook function.

## Using Hooks

You can refer to static program analysis tools, such as IDA Pro, to obtain the symbols or signatures of the functions you want to Hook.

Or refer to the [`Fake Header`](https://github.com/LiteLDev/LeviLamina/tree/develop/src/mc) provided by LeviLamina to obtain the symbols or definitions of the functions you want to Hook.
You can refer to the [`Fake Header`](https://github.com/LiteLDev/LeviLamina/tree/develop/src/mc) provided by LeviLamina to obtain the definitions of the functions you want to Hook.

### A Simple Hook Example

```cpp
#include "ll/api/Logger.h"
#include "mc/server/common/DedicatedServer.h"
#include "ll/api/memory/Hook.h"
#include "ll/api/io/LoggerRegistry.h"
#include "mc/server/DedicatedServer.h"

ll::Logger dedicatedServerLogger("DedicatedServer");
auto dedicatedServerLogger = ll::io::LoggerRegistry::getInstance().getOrCreate("DedicatedServer");

LL_AUTO_TYPE_INSTANCE_HOOK(
DedicatedServerHook,
DedicatedServerCtorHook,
ll::memory::HookPriority::Normal,
DedicatedServer,
"??0DedicatedServer@@QEAA@XZ",
void
&DedicatedServer::$ctor,
void*
) {
origin();
dedicatedServerLogger.info("DedicatedServer::DedicatedServer");
dedicatedServerLogger->info("DedicatedServer::DedicatedServer");
return origin();
}
```

This code hooks the constructor of DedicatedServer and prints a log message when the constructor is called.
This code hooks the constructor of `DedicatedServer` and prints a log message when the constructor is called.

Analysis:
#### Analysis:

Referring to the [`DedicatedServer.h`](https://github.com/LiteLDev/LeviLamina/blob/cccef6a0307cdcd89342d25f4826271ac298b6a8/src/mc/server/common/DedicatedServer.h#L59C31-L59C32) provided by LeviLamina, we know that the symbol for DedicatedServer's constructor is `??0DedicatedServer@@QEAA@XZ`.
Referring to the [`DedicatedServer.h`](https://github.com/LiteLDev/LeviLamina/blob/594d6897525f902c457428bbbc5bc9fe20305fb8/src/mc/server/DedicatedServer.h#L134) provided by LeviLamina, we know that the constructor of `DedicatedServer` has a thunk function.

Since the constructor is a member function of the class, we used the `INSTANCE_HOOK` type of Hook, which means we don't need to fill in the first [`this pointer`](https://en.cppreference.com/w/cpp/language/this) parameter generated by the compiler.

We used the `AUTO`-marked Hook because we want it to automatically register when the mod is loaded.

Finally, for convenience, we used the `TYPE`-marked Hook, so we can directly call functions under the DedicatedServer type in the function body. Although we did not use it in this code, it is a good habit.
Finally, for convenience, we used the `TYPE`-marked Hook, so we can directly call functions under the `DedicatedServer` type in the function body. Although we did not use it in this code, it is a good habit.

### Registering and Unloading Hooks

#### Registration

For non-automatically registered Hooks, you need

to call the `hook()` function to register at the moment your mod needs to register the Hook.
For non-automatically registered Hooks, you need to call the `hook()` function to register at the moment your mod needs to register the Hook.

#### Unloading

Expand All @@ -112,4 +109,4 @@ All Hooks will automatically unload when BDS unloads. You can also call the `unh

Hook is a very powerful technique but also a double-edged sword. If used improperly, it can cause crashes of the BDS core or mods, and in severe cases, affect the game saves.

Therefore, please be cautious when using Hooks, check your code carefully to avoid unnecessary errors.
Therefore, please be cautious when using Hooks, and check your code carefully to avoid unnecessary errors.
54 changes: 26 additions & 28 deletions docs/main/developer_guides/how_to_guides/hook_guide.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ Hook 是一种在运行时修改函数行为的技术。通常用于在不修改

wikipedia 关于 Hook 的解释:[Hooking](https://en.wikipedia.org/wiki/Hooking)

在 LeviLamina 中,我们提供了封装好的Hook API,使得你可以快速便捷地对 Minecraft 基岩专用服务器(下文称为```BDS```)中的游戏函数进行行为修改。
在 LeviLamina 中,我们提供了封装好的Hook API,使得你可以快速便捷地对 Minecraft 基岩专用服务器(下文称为`BDS`)中的游戏函数进行行为修改。

## Hook的类型

[```ll/api/memory/Hook.h```](https://github.com/LiteLDev/LeviLamina/blob/develop/src/ll/api/memory/Hook.h#L180C1-L180C1) 中,我们定义了以下几种Hook 宏:
[`ll/api/memory/Hook.h`](https://github.com/LiteLDev/LeviLamina/blob/develop/src/ll/api/memory/Hook.h#L180C1-L180C1) 中,我们定义了以下几种Hook 宏:

```cpp
#define LL_TYPE_STATIC_HOOK(DEF_TYPE, PRIORITY, TYPE, IDENTIFIER, RET_TYPE, ...)
Expand All @@ -30,8 +30,7 @@ wikipedia 关于 Hook 的解释:[Hooking](https://en.wikipedia.org/wiki/Hookin
#define LL_AUTO_INSTANCE_HOOK(DEF_TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...)
```

其中,AUTO 标注的 Hook 会自动注册,即运行时自动调用hook()函数进行注册。
TYPED 标注的 Hook 会给你的 DEF_TYPE 继承到你指定的类型。
其中,AUTO 标注的 Hook 会自动注册,即运行时自动调用hook()函数进行注册。 TYPE 标注的 Hook 会给你的 DEF_TYPE 继承到你指定的类型。

### STATIC_HOOK

Expand All @@ -43,68 +42,67 @@ TYPED 标注的 Hook 会给你的 DEF_TYPE 继承到你指定的类型。

## Hook的参数解释

```DEF_TYPE```:你给你这个 Hook 的起的类型名。
`DEF_TYPE`:你给你这个 Hook 的起的类型名。

```PRIORITY```:[Hook的优先级](https://github.com/LiteLDev/LeviLamina/blob/develop/src/ll/api/memory/Hook.h#L73),例如```ll::memory::HookPriority::Normal```
`PRIORITY`:[Hook的优先级](https://github.com/LiteLDev/LeviLamina/blob/develop/src/ll/api/memory/Hook.h#L73),例如`ll::memory::HookPriority::Normal`

!!! note
一般不是特殊需求,我们不推荐过高的优先级,Normal 即可。

```TYPE```:你的定义的 DEF_TYPE 继承到的类型。
`TYPE`:你的定义的 `DEF_TYPE` 继承到的类型。

```IDENTIFIER```:Hook 的查询函数使用的标识符,可以为:[函数修饰后名称](https://learn.microsoft.com/zh-cn/cpp/build/reference/decorated-names?view=msvc-170),函数的字节码,函数定义。
`IDENTIFIER`:Hook 的查询函数使用的标识符,可以为:[函数修饰后名称](https://learn.microsoft.com/zh-cn/cpp/build/reference/decorated-names?view=msvc-170),函数的字节码,函数定义。

```RET_TYPE```:Hook 的函数的返回值类型。
`RET_TYPE`:Hook 的函数的返回值类型。

```...```:Hook 的函数的参数列表。
`...`:Hook 的函数的参数列表。

## Hook的使用

你可以查阅静态程序分析工具,例如 IDA Pro,来获取你想要Hook的函数的符号或特征码。

或者查阅 LeviLamina 提供的[```Fake Header```](https://github.com/LiteLDev/LeviLamina/tree/develop/src/mc)来获取你想要 Hook 的函数的符号或者定义。
你可以查阅 LeviLamina 提供的[`Fake Header`](https://github.com/LiteLDev/LeviLamina/tree/develop/src/mc)来获取你想要 Hook 的函数的定义。

### 简单的Hook示例

```cpp
#include "ll/api/Logger.h"
#include "mc/server/common/DedicatedServer.h"
#include "ll/api/memory/Hook.h"
#include "ll/api/io/LoggerRegistry.h"
#include "mc/server/DedicatedServer.h"

ll::Logger dedicatedServerLogger("DedicatedServer");
auto dedicatedServerLogger = ll::io::LoggerRegistry::getInstance().getOrCreate("DedicatedServer");

LL_AUTO_TYPE_INSTANCE_HOOK(
DedicatedServerHook,
DedicatedServerCtorHook,
ll::memory::HookPriority::Normal,
DedicatedServer,
"??0DedicatedServer@@QEAA@XZ",
void
&DedicatedServer::$ctor,
void*
) {
origin();
dedicatedServerLogger.info("DedicatedServer::DedicatedServer");
dedicatedServerLogger->info("DedicatedServer::DedicatedServer");
return origin();
}
```

这段代码会 Hook DedicatedServer 的构造函数,并在构造函数被调用时打印一条日志。

解析:
#### 解析:

根据查阅 LeviLamina 提供的[```DedicatedServer.h```](https://github.com/LiteLDev/LeviLamina/blob/cccef6a0307cdcd89342d25f4826271ac298b6a8/src/mc/server/common/DedicatedServer.h#L59C31-L59C32) ,我们可以知道 DedicatedServer 的构造函数的符号为 ```??0DedicatedServer@@QEAA@XZ```
根据查阅 LeviLamina 提供的[`DedicatedServer.h`](https://github.com/LiteLDev/LeviLamina/blob/594d6897525f902c457428bbbc5bc9fe20305fb8/src/mc/server/DedicatedServer.h#L134),我们可以得到 DedicatedServer 的构造函数的thunk函数

又由于构造函数是类的成员函数,所以我们使用了 ```INSTANCE_HOOK```类型的 Hook,这使我们不需要填写由编译器产生的第一个[```this指针```](https://zh.cppreference.com/w/cpp/language/this)参数。
又由于构造函数是类的成员函数,所以我们使用了`INSTANCE_HOOK`类型的Hook,这使我们不需要填写由编译器产生的第一个[`this指针`](https://zh.cppreference.com/w/cpp/language/this)参数。

又由于我们希望在模组被加载的时候自动注册,所以我们使用了 ```AUTO```标注的 Hook。
又由于我们希望在模组被加载的时候自动注册,所以我们使用了 `AUTO`标注的 Hook。

最后由于方便,我们使用了 ```TYPE```标注的 Hook,使得我们可以直接在函数体内调用 DedicatedServer 类型下的函数,虽然在这段代码中我们并没有使用到,但是这是一个好习惯。
最后由于方便,我们使用了 `TYPE`标注的 Hook,使得我们可以直接在函数体内调用 DedicatedServer 类型下的函数,虽然在这段代码中我们并没有使用到,但是这是一个好习惯。

### Hook的注册和卸载

#### 注册

针对非自动注册的 Hook,你需要在你模组需要注册 Hook 的时机调用```hook()```函数进行注册。
针对非自动注册的 Hook,你需要在你模组需要注册 Hook 的时机调用`hook()`函数进行注册。

#### 卸载

所有的 Hook 都会在 BDS 卸载时自动卸载,你也可以在你模组需要卸载 Hook 的时机调用```unhook()```函数进行卸载。
所有的 Hook 都会在 BDS 卸载时自动卸载,你也可以在你模组需要卸载 Hook 的时机调用`unhook()`函数进行卸载。

## 写在最后

Expand Down
3 changes: 0 additions & 3 deletions src-client/ll/core/main_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,6 @@ LL_AUTO_TYPE_INSTANCE_HOOK(

BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ulReasonForCall, LPVOID /*lpReserved*/) {
using namespace ll;
if (ulReasonForCall == DLL_PROCESS_DETACH) {
mod::ModRegistrar::getInstance().releaseAllMods();
}
if (ulReasonForCall != DLL_PROCESS_ATTACH) return TRUE;

setGamingStatus(GamingStatus::Default);
Expand Down
3 changes: 2 additions & 1 deletion src-server/ll/core/form/FormHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,9 @@ bool handleFormPacket(
if (it == formHandlers.end()) {
return false;
}
it->second->handle(player, std::move(data), cancelReason);
auto handler = std::move(it->second);
formHandlers.erase(it);
handler->handle(player, std::move(data), cancelReason);
return true;
}

Expand Down
2 changes: 0 additions & 2 deletions src-server/ll/core/main_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,6 @@ LL_AUTO_TYPE_INSTANCE_HOOK(

command::CommandRegistrar::getInstance().clear();

mod::ModRegistrar::getInstance().releaseAllMods();

origin();
}

Expand Down
2 changes: 1 addition & 1 deletion src-test/server/TestNbt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ LL_AUTO_TYPE_INSTANCE_HOOK(NbtTest, HookPriority::Normal, ServerInstance, &Serve

nbt3["hello"]["world"] = ListTag{1.0, 2.0, 3.0};

nbt3["hello"]["world"][1] = 7.0_d;
nbt3["hello"]["world"][1] = 7.0;

nbt3["hello"][", "] = "world";

Expand Down
8 changes: 4 additions & 4 deletions src/ll/api/base/Containers.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ template <
class Key,
class Hash = ::phmap::priv::hash_default_hash<Key>,
class Eq = ::phmap::priv::hash_default_eq<Key>,
class Alloc = ::phmap::priv::Allocator<Key>,
class Alloc = ::std::allocator<Key>,
size_t N = 4,
class Mutex = std::shared_mutex>
using ConcurrentDenseSet = ::phmap::parallel_flat_hash_set<Key, Hash, Eq, Alloc, N, Mutex>;
Expand All @@ -78,7 +78,7 @@ template <
class Value,
class Hash = ::phmap::priv::hash_default_hash<Key>,
class Eq = ::phmap::priv::hash_default_eq<Key>,
class Alloc = ::phmap::priv::Allocator<::phmap::priv::Pair<Key const, Value>>,
class Alloc = ::std::allocator<::std::pair<Key const, Value>>,
size_t N = 4,
class Mutex = std::shared_mutex>
using ConcurrentDenseMap = ::phmap::parallel_flat_hash_map<Key, Value, Hash, Eq, Alloc, N, Mutex>;
Expand All @@ -87,7 +87,7 @@ template <
class Key,
class Hash = ::phmap::priv::hash_default_hash<Key>,
class Eq = ::phmap::priv::hash_default_eq<Key>,
class Alloc = ::phmap::priv::Allocator<Key>,
class Alloc = ::std::allocator<Key>,
size_t N = 4,
class Mutex = std::shared_mutex>
using ConcurrentDenseNodeSet = ::phmap::parallel_node_hash_set<Key, Hash, Eq, Alloc, N, Mutex>;
Expand All @@ -96,7 +96,7 @@ template <
class Value,
class Hash = ::phmap::priv::hash_default_hash<Key>,
class Eq = ::phmap::priv::hash_default_eq<Key>,
class Alloc = ::phmap::priv::Allocator<::phmap::priv::Pair<Key const, Value>>,
class Alloc = ::std::allocator<::std::pair<Key const, Value>>,
size_t N = 4,
class Mutex = std::shared_mutex>
using ConcurrentDenseNodeMap = ::phmap::parallel_node_hash_map<Key, Value, Hash, Eq, Alloc, N, Mutex>;
Expand Down
2 changes: 1 addition & 1 deletion src/ll/api/data/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ struct PreRelease {
auto tokens = ll::string_utils::splitByPattern(s, ".");
for (auto const& token : tokens) {
std::uint16_t value;
if (detail::from_chars(token.data(), token.data() + token.length(), value); value) {
if (auto result = detail::from_chars(token.data(), token.data() + token.length(), value); result) {
values.emplace_back(value);
} else {
values.emplace_back(std::string{token});
Expand Down
14 changes: 5 additions & 9 deletions src/ll/api/io/Logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,13 @@ Logger::Logger(PrivateTag, std::string_view title) : impl(std::make_unique<Impl>
impl->sinks.push_back(std::make_shared<DefaultSink>());
}

void Logger::printView(LogLevel level, std::string_view msg) const noexcept {
if (level > impl->level) {
return;
}
printStr(level, std::string{msg});
}
std::string const& Logger::getTitle() const noexcept { return impl->title; }

LogLevel Logger::getLevel() const noexcept { return impl->level; }

bool Logger::shouldLog(LogLevel level) const noexcept { return level <= impl->level; }

void Logger::printStr(LogLevel level, std::string&& msg) const noexcept try {
if (level > impl->level) {
return;
}
impl->pool.execute([logger = shared_from_this(),
msg = LogMessage{std::move(msg), impl->title, level, sys_utils::getLocalTime()}] {
try {
Expand Down
Loading
Loading