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

[feature] Issue with Loading Custom Plugins in Endstone due to Plugin Loading Mechanism #98

Closed
engsr6982 opened this issue Dec 1, 2024 · 6 comments · Fixed by #110
Closed
Assignees
Labels
enhancement New feature or request

Comments

@engsr6982
Copy link
Contributor

engsr6982 commented Dec 1, 2024

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

I'm trying to write other language engines for Endstone (although the Python functionality provided by Endstone is stronger). However, the plugin loading mechanism of Endstone prevents me from loading plugins of custom types, such as.lua ones.
Because I need to wait for Endstone to load my engine DLL before I can register the loader with Endstone. But by this time, Endstone has already completed the loading and will no longer call the newly added loader.
I've tried to manually call the "loadPlugins" function, but Endstone doesn't check whether the plugins have been loaded, which will lead to an infinite loop. Besides, the members of Endstone_plugin_manager are private, and I can't register them manually either.
Describe the solution you'd like
A clear and concise description of what you want to happen.

Could you add a couple of overloads to EndStonePluginManager::loadPlugins(const std::string &directory), for example:

EndStonePluginManager::loadPlugins(const std::string &directory, string const& loader_type)

or

EndStonePluginManager::loadPlugins(const std::string &directory, PluginLoader& loader)

@engsr6982 engsr6982 added the enhancement New feature or request label Dec 1, 2024
@wu-vincent
Copy link
Member

wu-vincent commented Dec 2, 2024

Thanks for the issue! This is indeed something in the current design that needs improvement.

I’m currently refactoring the plugin loading mechanism to address this. I’ve added a new function, PluginManager::loadPlugin(std::string file), which allows loading a plugin directly from a single file instead of a directory. I’ve also introduced an overload for PluginManager::loadPlugins(std::vector<std::string>) that accepts a list of file paths instead of just a directory.

These changes should enable you to load your custom plugins without encountering infinite loops. Most of the refactoring work mentioned above is completed in this commit, but I still need to perform more testing.

@wu-vincent wu-vincent self-assigned this Dec 2, 2024
@wu-vincent
Copy link
Member

Close as it's completed now. The new API will be available in the upcoming release v0.5.6.

@engsr6982
Copy link
Contributor Author

engsr6982 commented Dec 7, 2024

Thanks for the issue! This is indeed something in the current design that needs improvement.

I’m currently refactoring the plugin loading mechanism to address this. I’ve added a new function, PluginManager::loadPlugin(std::string file), which allows loading a plugin directly from a single file instead of a directory. I’ve also introduced an overload for PluginManager::loadPlugins(std::vector<std::string>) that accepts a list of file paths instead of just a directory.

These changes should enable you to load your custom plugins without encountering infinite loops. Most of the refactoring work mentioned above is completed in this commit, but I still need to perform more testing.

I tested these two new overloaded functions and found that custom plugins still cannot be properly registered with Endstone.

Here's my registration process:
When Endstone loads my DLL, I register a custom Loader in the onLoad function. Then I search for the file paths I expect to load in the plugins directory and pass them to the PluginManager::loadPlugins(std::vector<std::string> files) function.

However, PluginManager::loadPlugins calls PluginManager::loadPlugin(file), which iterates through each Loader trying to find one that can load this file. The problem occurs here - this function doesn't perform any checks and doesn't call getPluginFileFilters() for filtering. Instead, it directly passes the file path to both Cpp and Py Loaders, causing exceptions and crashes.

@wu-vincent wu-vincent reopened this Dec 7, 2024
@engsr6982
Copy link
Contributor Author

engsr6982 commented Dec 17, 2024

Thanks for the issue! This is indeed something in the current design that needs improvement.
I’m currently refactoring the plugin loading mechanism to address this. I’ve added a new function, PluginManager::loadPlugin(std::string file), which allows loading a plugin directly from a single file instead of a directory. I’ve also introduced an overload for PluginManager::loadPlugins(std::vector<std::string>) that accepts a list of file paths instead of just a directory.
These changes should enable you to load your custom plugins without encountering infinite loops. Most of the refactoring work mentioned above is completed in this commit, but I still need to perform more testing.

I tested these two new overloaded functions and found that custom plugins still cannot be properly registered with Endstone.

Here's my registration process: When Endstone loads my DLL, I register a custom Loader in the onLoad function. Then I search for the file paths I expect to load in the plugins directory and pass them to the PluginManager::loadPlugins(std::vector<std::string> files) function.

However, PluginManager::loadPlugins calls PluginManager::loadPlugin(file), which iterates through each Loader trying to find one that can load this file. The problem occurs here - this function doesn't perform any checks and doesn't call getPluginFileFilters() for filtering. Instead, it directly passes the file path to both Cpp and Py Loaders, causing exceptions and crashes.

I forked the project and fixed the problem. But I found a more serious problem, if any plugin registers (modifies) the Vector that holds the Loader during onLoad, it will cause the iterator to fail and trigger a crash.

fork: https://github.com/engsr6982/endstone/commit/dd2d97f9f3cd8ee98c5760eca098edb76df322bb
Iterator failure location:

std::vector<Plugin *> EndstonePluginManager::loadPlugins(std::string directory)
{
std::vector<Plugin *> loaded_plugins;
// TODO(plugin): handling logic for depend, soft_depend, load_before and provides
for (const auto &loader : plugin_loaders_) {
auto plugins = loader->loadPlugins(directory);
for (const auto &plugin : plugins) {
if (!plugin) {
continue;
}
if (initPlugin(*plugin, *loader, fs::path(directory))) {
loaded_plugins.push_back(plugin);
}
}
}
return loaded_plugins;
}

wu-vincent added a commit that referenced this issue Dec 18, 2024
…ile (#110)

* fix: fix EndstonePluginManager::loadPlugin #98

* refactor: improve plugin loading logic in EndstonePluginManager

* refactor: revert back to range-based loop for plugin loading

---------

Co-authored-by: Vincent <magicdroidx@gmail.com>
wu-vincent added a commit that referenced this issue Dec 18, 2024
* Update server_list_ping_event.h and make fields public

* use proper setters

* add set guid method for ServerListPingEvent

* docs: update README.md

* chore: update symbols.toml for BDS v1.21.50 Windows (not supported yet)

* fix: add missing virtual functions in IResourcePackRepository

* fix: ScriptingGameplayEvent variants

* fix: Dimension class members

* fix: PlayerGameplayEvent variants

* fix: update enums

* fix: Block and BlockLegacy

* fix: Item and ItemRegistry

* fix: Actor class

* fix: BlockSource and BinaryStream

* fix: correct size assertion for Block class

* fix: prevent server crash when comments are present in `world_resource_packs.json`

Fix #100

* feat: improve error logging to include exception details when JSON loading fails

* chore: update symbols.toml for BDS v1.21.50 Linux

* fix: make Level::_cerealContext() a pure virtual function.

* docs: update CHANGELOG.md

* deps: switch to FetchContent for funchook

* fix(event): ensure ScriptMessageEvent is invoked correctly

* fix: remove funchook in conanfile.py

* fix: add missing dependencies in CMakeLists.txt

* fix: compilation error in ScriptingEventCoordinator

* fix: remove funchook from conanfile.py

* feat: add `Block::canContainLiquid` (#107)

* refactor(devtools): remove deprecated material (#109)

* fix: fix material.h and material_type.h

* refactor: rename canDropWithAnyTool to requiresCorrectToolForDrops

* refactor: remove material related things since these things are unused

* docs: add a FIXME notice to biome.h

* fix: update Biome class members

* ci: fix static_assert macros for class size checks

* fix: player inventory not being updated after calling `clear`

close #108

* refactor: correct headers

* feat: add an overload for `/ban` command for player name auto-completion

* refactor: update members in CommandRegistry

* chore(deps): bump scikit-build-core-conan version in pyproject.toml

* fix: ensure the correct plugin loader is selected when loading from file (#110)

* fix: fix EndstonePluginManager::loadPlugin #98

* refactor: improve plugin loading logic in EndstonePluginManager

* refactor: revert back to range-based loop for plugin loading

---------

Co-authored-by: Vincent <magicdroidx@gmail.com>

* Update server_list_ping_event.h and make fields public

* use proper setters

* add set guid method for ServerListPingEvent

* docs: fix documentation for the setters

* feat: add python bindings for the setters in `ServerListPingEvent`

* docs: update documentation to improve consistency

---------

Co-authored-by: Vincent <magicdroidx@gmail.com>
Co-authored-by: daoge <3523206925@qq.com>
Co-authored-by: engsr6982 <109733049+engsr6982@users.noreply.github.com>
@wu-vincent
Copy link
Member

To address cases where the vector may be modified during iteration, I’ve made an additional commit to fix the issue. You can check it here: 6ed7faf

Can you verify if this resolves the problem?

@engsr6982
Copy link
Contributor Author

To address cases where the vector may be modified during iteration, I’ve made an additional commit to fix the issue. You can check it here: 6ed7faf

Can you verify if this resolves the problem?

Thanks, it's been verified and the code is running fine so far!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants