mods如何工作?

时间:2011-02-12 14:25:14

标签: c++

人们如何让mods工作,例如,在游戏中? 通过mods我的意思是添加到最终的可执行文件。

如果我要制作游戏(使用编译语言),我是否可以允许自己或其他人添加它而无需创建某种脚本语言。

我的想法:(这会有用吗?)

  • 在基本程序本身中,创建堆栈或FIFO甚至链接列表。
  • 然后在程序之外,加载器将加载基础和任何mod,然后将mod的地址传递给基本程序。
  • 最后,基本程序做了它的事情,然后将执行切换到mods(也许用某种回调机制,比如[gasp!] goto)。当它们完成后,代码执行会返回到可以自行完成的基础。

3 个答案:

答案 0 :(得分:4)

如果不实现脚本语言,它将与您描述的方式类似。 Windows有一个叫做动态链接库(DLL)的东西,Linux有一个类似的概念叫做共享对象(SO)。

在任一OS上的程序中,程序可以动态地(通过查找某个目录中的文件或通过配置文件)加载这些文件。这些文件包含可执行代码,就像普通程序一样,只要程序知道函数的名称,加载它们的程序就可以调用它们内部的函数。

您可以对函数的名称进行硬编码,或将它们放在配置文件中,或者创建一个硬编码函数名称,以返回要加载的其他函数的名称或指向函数本身的指针。

这种方法很常见。这就是mysql允许用户定义的函数和索引,通过从特定目录加载共享库并调用“LOAD PLUGIN”命令中提供的函数。

答案 1 :(得分:3)

虽然这在理论上是有效的,但它不是通常的方式。

Mods通常不会被实现为本机代码。 Mod友好游戏通常使用数据驱动的方法,并提供一些脚本语言和配置方法,然后用于实现mod的自定义功能。

除此之外,这种方法的原因是:

  • 使用C ++实现mods通常感兴趣的高级东西是一种过度杀伤,脚本语言通常更容易使用,并且不需要高性能的C ++
  • 提供对本机代码的访问可能会导致严重的安全问题(有意和无意,因为很难编写本机代码,这不会导致任何内存泄漏,内存访问冲突和其他问题)
  • 使用本机回调时,很难定义(并强制执行)游戏与模组之间的接口

如果您不想创建自己的脚本语言,那么使用一些现成的(LUA在游戏中非常流行)相对容易。

答案 2 :(得分:3)

通常,您会将一些应用程序(游戏?)内部接口和对象暴露给mod编写器。 mod编写器将构建一个dll,它使用这些对象和接口来做一些有用的事情。然后,应用程序将动态加载mod dll并在必要时调用mod实现。

考虑它的另一种方法是想象你的游戏是一个操作系统(Windows),你的mod是一个应用程序(Word)。操作系统提供了一些API来创建和管理窗口,应用程序在必要时使用它们。

因此,作为游戏开发者,您可以创建并分发以下界面:

//mod.h
class Mod {
    //takes suggested damage as an arg and returns modified damage
    virtual int takeDamage(int damage);
};

并指示用户提供导出的函数来实例化和删除mod对象。

实施它:

//godmod.h
class GodMod : public Mod {
    int takeDamage(int damage) { return 0; } // god mode!!
}

__declspec(dllexport) Mod *create_mod() { return new GodMode(); }
__declspec(dllexport) void delete_mod(Mod *mod) { delete mod; }

然后,您必须在Windows上加载dll(LoadLibrary API),使用create_mod API导出delete_modGetProcAddress符号。之后在游戏中的某个地方,您将使用create_mod实例化mod,并在需要时使用它:

int damage = 100; //original damage
for (int i = 0; i < mods_count; i++) {
    damage = mods[i]->tageDamage(damage);
}
decrease_health(damage);

毕竟你必须从相应的dll中使用delete_mod释放mod。