Skip to content

untrustedmodders/plugify

Repository files navigation

Documentation Discord channel

A Modern C++ Plugin and Package Manager with Multi-Language Support
Report a Bug Β· Request a Feature . Ask a Question

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

  1. 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.

  2. 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.

  3. 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.

  4. Package Manager:
    Lets your system manage packages. It has a robust package manager. Install, remove, update, downgrade packages easily and make your development environment keep up with the latest packages to read.

  5. Versatile Packages:
    The package system handles plugins and language modules, and covers most of a developer’s needs. Package your plugins and modules for easy sharing. Easily extend Plugify with new packages that meet the requirements of your project and fit the ecosystem.

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:

Actions build created for windows, linux and apple.

clang build gcc build msvc build msys build

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 URL https://github.com/untrustedmodders/plugify/releases/download/v1.0.0/plugify.tar.xz)
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 object implementing the plugify::IPlugify interface. It sets up logging, initializes the instance, and then interacts with a package manager and a plugin manager if they are available. Error handling is included for initialization failures.

std::shared_ptr<plugify::IPlugify> instance = plugify::MakePlugify();
if (instance) {
	auto logger = std::make_shared<StdLogger>();
	instance->SetLogger(logger);
	logger->SetSeverity(plugify::Severity::Debug);
	
	if (!instance->Initialize()) {
		std::cout << "No feet, no sweets!");
		return EXIT_FAILURE;
	}

	if (auto packageManager = instance->GetPackageManager().lock()) {
		packageManager->Initialize();

		if (packageManager->HasMissedPackages()) {
			std::cerr << "Plugin manager has missing packages." << std::endl;
			packageManager->InstallMissedPackages();
			continue;
		}
		if (packageManager->HasConflictedPackages()) {
			std::cerr << "Plugin manager has conflicted packages." << std::endl;
			packageManager->UninstallConflictedPackages();
			continue;
		}
	}

	if (auto pluginManager = instance->GetPluginManager().lock()) {
		pluginManager->Initialize();
	}
}

(back to top)

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.html

The 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.

(back to top)

Tests

To build the basic testing app:

  1. 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:

    brew install cmake ninja
  2. Clone the repo:

    git clone https://github.com/untrustedmodders/plugify.git
  3. Install CURL, otherwise build it in embedding mode with cmake options:

    a. Linux:

    sudo apt-get install -y libcurl4-openssl-dev

    b. Mac:

    brew install curl

    The dependencies can be used as external (find_package) and embedding (add_subdirectory), you can use plugify options to choose what you suits your need.

  4. Create build folder:

    mkdir build
    cd build
  5. Build the project:

    cmake .. 
    cmake --build . --target plug

(back to top)

Extensions

Here is a list of all already implemented language modules:

(back to top)

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 MM2-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).

(back to top)

Support

Reach out to the maintainer at one of the following places:

(back to top)

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!

(back to top)

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!

(back to top)

Authors & contributors

The original setup of this repository is by untrustedmodders.

For a full list of all authors and contributors, see the contributors page.

(back to top)

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.

(back to top)

License

This project is licensed under the MIT license.

See LICENSE for more information.

(back to top)

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.

(back to top)