Table of Contents
About
Unlock a new era in plugin development with Plugify, a revolutionary library designed to streamline and enhance the way plugins are created and utilized. Plugify goes beyond traditional plugin management by introducing innovative language modules, redefining the boundaries of cross-language communication.
Key Features
-
Dynamic Language Diversity:
Plugify’s power is in its flexibility. It allows you to use multiple programming languages. Choose the languages you need for the project, and go. This will make your development environment more diverse and flexible. -
Language Modules:
Plugify allows you to install language modules for various programming languages, so you can use the language of your choice and develop plugins with the core without any doubt about language incompatibilities. -
Inter-Language Communication:
Make plugins communicate to each other in any existing language. Export methods, and share data between plugins, without regard for the programming language used.
Motivation
The plan was to build a new plugin system for CS in C#, but some of the decisions that were made in the early version led to a decision to ‘remove the training wheels’, unshackle the system from any game or embeddable language and create a system which allows the developers of plugins to build them in whatever language they like. For as long as that language module is installed, the system is able to support it. So by no longer trying to force it to be deemed a ‘good’ solution to be embedded in a variety of games, Plugify now goes far beyond the logical limitations a C#-specific solution has. What this means is that Plugify not only has the potential to have a larger community of developers, but is now flexible from the beginning to last a long time. Longevity was always a selling point, since if it was to work, it always had to be a ‘forever’ feature. It’s not just games development that stands to benefit. The flexibility of Plugify should mean it has uses in many projects, not just in games.
Integration
Requirements
- CMake version 3.14 or later.
- Doxygen version 1.8 or later.
- Requires C++20 or later.
- Designed for x86 and Arm.
- Tested on 64bit little-endian systems.
Supported platforms:
- Windows (7+)
- Linux
- macOS (13.0+)
- PlayStation 4/5
- Nintendo Switch
- Android (14+)
- iOS/iPadOS/tvOS (16.0+)
- UWP (Universal Windows, Xbox One)
Supported compilers:
- Clang 15 and above
- GCC 11 and above
- MSVC 2022 and above
- Apple Clang 15 and above
Actions build created for windows, linux and apple.
CMake
You can also use the plugify::plugify interface target in CMake.
External
To use this library from a CMake project, you can locate it directly with find_package() and use the namespaced imported target from the generated package configuration:
# CMakeLists.txt find_package(plugify REQUIRED) ... add_library(foo ...) ... target_link_libraries(foo PRIVATE plugify::plugify)
Embedded
To embed the library directly into an existing CMake project, place the entire source tree in a subdirectory and call add_subdirectory() in your CMakeLists.txt file:
# Typically you don't care so much for a third party library's tests to be # run from your own project's code. set(PLUGIFY_BUILD_TESTS OFF CACHE INTERNAL "") # Don't use include(plugify/CMakeLists.txt) since that carries with it # unintended consequences that will break the build. It's generally # discouraged (although not necessarily well documented as such) to use # include(...) for pulling in other CMake projects anyways. add_subdirectory(plugify) ... add_library(foo ...) ... target_link_libraries(foo PRIVATE plugify::plugify)
Embedded (FetchContent)
Since CMake v3.11, FetchContent can be used to automatically download a release as a dependency at configure time.
Example:
include(FetchContent) FetchContent_Declare(plugify GIT_REPOSITORY https://github.com/untrustedmodders/plugify.git) FetchContent_MakeAvailable(plugify) target_link_libraries(foo PRIVATE plugify::plugify)
Note: It is recommended to use the URL approach described above which is supported as of version 1.0.0. See wiki for more information.
Supporting Both
To allow your project to support either an externally supplied or an embedded Plugify library, you can use a pattern akin to the following:
# Top level CMakeLists.txt project(FOO) ... option(FOO_USE_EXTERNAL_PLUGIFY "Use an external Plugify library" OFF) ... add_subdirectory(thirdparty) ... add_library(foo ...) ... # Note that the namespaced target will always be available regardless of the # import method target_link_libraries(foo PRIVATE plugify::plugify)
# thirdparty/CMakeLists.txt ... if(FOO_USE_EXTERNAL_PLUGIFY) find_package(plugify REQUIRED) else() add_subdirectory(plugify) endif() ...
thirdparty/plugify is then a complete copy of this source tree.
Example
This code creates an instance of the plugify::Plugify object. It sets up services, initializes the instance, and then interacts with a plugin manager. Error handling is included for initialization failures.
// Example 1: Simple usage with defaults int main() { auto result = plugify::MakePlugify("./app"); if (!result) { std::cerr << "Failed to create Plugify: " << result.error().message << std::endl; return 1; } auto plugify = result.value(); if (auto initResult = plugify->Initialize(); !initResult) { std::cerr << "Failed to initialize: " << initResult.error().message << std::endl; return 1; } // Load extensions const auto& manager = plugify->GetManager(); manager->Initialize(); // Main loop bool running = true; while (running) { plugify->Update(); // Your application logic here } plugify->Terminate(); return 0; }
// Example 2: Advanced configuration int main() { // Create custom logger auto logger = std::make_shared<plugify::impl::AsyncLogger>( std::make_shared<plugify::impl::FileLogger>("./logs/app.log") ); // Configure plugin manager plugify::Config config; config.paths.baseDir = "./app"; config.paths.extensionsDir = "extensions"; config.loading.enableHotReload = true; config.loading.parallelLoading = true; config.runtime.updateInterval = std::chrono::milliseconds(16); // Build Plugify instance auto result = plugify::Plugify::CreateBuilder() .WithConfig(config) .WithLogger(logger) .WithService<MyCustomService>(std::make_shared<MyCustomServiceImpl>()) .Build(); if (!result) { std::cerr << "Failed: " << result.error().message << std::endl; return 1; } auto plugify = result.value(); // Initialize asynchronously auto initFuture = plugify->InitializeAsync(); // Do other initialization... // Wait for initialization if (auto initResult = initFuture.get(); !initResult) { std::cerr << "Failed to initialize: " << initResult.error().message << std::endl; return 1; } // Access service locator for convenient operations auto logger = plugify->GetServices().Resolve<ILogger>(); logger->Log("Application started", Severity::Info); // Main loop bool running = true; while (running) { plugify->Update(); } plugify->Terminate(); return 0; }
Documentation
The documentation is based on doxygen. To build it:
cd build cmake .. -DPLUGIFY_BUILD_DOCS=ON cmake --build . --target docs
The API reference is created in HTML format in the build/docs/html directory.
To navigate it with your favorite browser:
cd build
your_favorite_browser docs/html/index.htmlThe same version is also available online
for the latest release, that is the last stable tag.
There is also a wiki page dedicated
to the project where users can find all related documentation pages.
Additionally, we offer an online documentation generator that allows you to easily create documentation for your plugin's manifest file.
Tests
To build the basic testing app:
-
Install dependencies:
a. Windows
Setting up CMake tools with Visual Studio Installer
b. Linux:
sudo apt-get install -y build-essential cmake ninja-build
c. Mac:
-
Clone the repo:
git clone https://github.com/untrustedmodders/plugify.git
-
Create build folder:
-
Build the project:
cmake .. cmake --build . --target plug
Extensions
Here is a list of all already implemented language modules:
- C++ Language Module
- C# (.NET) Language Module
- Go Language Module
- Python Language Module
- JavaScript Language Module
- Lua Language Module
- Rust Language Module
- D Language Module
- C# (Mono) Language Module
In Action
While Plugify is a relatively new project, it is making waves in the realm of server-side modding, particularly in the Counter-Strike 2 community. As of now, Plugify is primarily utilized in the ance of a new project known as S2-Plugify, which is also being developed by our team.
If you know of other resources out there that are about Plugify, feel free to open an issue or a PR and we will be glad to add them here.
Roadmap
See the open issues for a list of proposed features (and known issues).
- Top Feature Requests (Add your votes using the 👍 reaction)
- Top Bugs (Add your votes using the 👍 reaction)
- Newest Bugs
Reach out to the maintainer at one of the following places:
- Discord
- GitHub issues
- Contact options listed on this GitHub profile
Project assistance
If you want to say thank you or/and support active development of plugify:
- Add a GitHub Star to the project.
- Tweet about the plugify.
- Write interesting articles about the project on Dev.to, Medium or your personal blog.
Together, we can make plugify better!
Contributing
First off, thanks for taking the time to contribute! Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make will benefit everybody else and are greatly appreciated.
Please read our contribution guidelines, and thank you for being involved!
Authors & contributors
The original setup of this repository is by untrustedmodders.
For a full list of all authors and contributors, see the contributors page.
Security
Plugify follows good practices of security, but 100% security cannot be assured. Library is provided "as is" without any warranty. Use at your own risk.
For more information and to report security issues, please refer to our security documentation.
License
This project is licensed under the MIT license.
See LICENSE for more information.
Acknowledgements
[?] If your work was funded by any organization or institution, acknowledge their support here. In addition, if your work relies on other software libraries, or was inspired by looking at other work, it is appropriate to acknowledge this intellectual debt too.