繁体   English   中英

C++ 允许程序接受任意 Mod

[英]C++ Allow Program to Accept Arbitrary Mods

我正在开发一款我想拥有非常好的模组支持的游戏。 游戏采用 C++ 编程,将完全开源。 我希望能够让用户轻松添加和删除模组。 该游戏将是开源的,因此模组制作者将知道代码的外观,但我希望模组制作者能够覆盖代码编译版本中的功能并能够添加新功能。 我不想创建一个明确的 API 或使用另一种语言的 mod,因为这些必然限制可以用它们做什么。 理想的情况是用户下载一个模组并将其放在模组文件夹中,运行一次游戏以加载模组,然后关闭它并再次运行以加载包含模组的游戏。 怎么可能做到这一点?

一个例子是,如果我有这个程序:

#include <iostream>

char const* getName();

int main() {
    std::cout << getName() << std::endl;
}

char const* getName()
{
    return "Robert";
}

我将能够编写一个具有

char const* getName()
{
    return "Steve";
}

在同一个命名空间中,因此原始代码的结果将是“Steve”。

我将假设“运行游戏一次以加载 mods”您的意思是“让用户 go 进入菜单并指示动态库的位置”。

而不是 function getName ,您将拥有一个 function 指针getName ,以及一些将其设置为从动态库加载的 function 的代码。

作为草图:

struct Library {
    template<typename Signature>
    Signature getSymbol(std::string name) // get the function named name from this dynamic library
}

std::vector<Library> getMods(); // read from some configuration all the mod file paths, and load them into Library objects

const char* defaultGetName()
{
    return "Robert";
}

using Namer = const char * (*)();

Namer getName = defaultGetName;

int main()
{
    for(auto & lib : getMods()) {
        if (auto namer = lib.getSymbol<Namer>("getName")) {
            getName = namer;
        } // etc for other "overridable" functions
    }
    std::cout << getName() << std::endl;
}

Library部分将是特定于平台的。 Unix 有dlopen / dlsym , Windows 有LoadLibrary ( Ex ) / GetProcAddress

如果你把整个游戏(除了加载mod的部分)放到一个class中,并且让每个function都是virtual的,那么这个mod可以有一个派生的class来代替一些功能。 然后,您编写了替换函数的列表,因为它们都在 class 内并标记为virtual

以这种方式一次只能加载一个模组。 添加新功能或删除某些功能将破坏所有模组 - 模组可能仅适用于它们编写的确切游戏版本。

您可能会发现某些函数没有意义进行修改(例如计算两个数字的最小值),并且某些函数不属于一个大 class 但应该在其他类中(例如,如果您的游戏,则Building class有建筑物)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM