从零创建一个 AzerothCore 模块:create_module.sh 使用指南与 CMake 构建原理解析

发布时间:2026/9/16 12:25:27
从零创建一个 AzerothCore 模块:create_module.sh 使用指南与 CMake 构建原理解析 从零创建一个 AzerothCore 模块create_module.sh 使用指南与 CMake 构建原理解析【免费下载链接】azerothcore-wotlkComplete Open Source and Modular solution for MMO项目地址: https://gitcode.com/GitHub_Trending/az/azerothcore-wotlkAzerothCore 是一款开源、模块化的 MMO 服务端解决方案其模块Module机制允许开发者在不修改核心源码的前提下以插件化方式扩展游戏逻辑、脚本与配置。本文以仓库内 modules/how_to_make_a_module.md 为主线结合 create_module.sh 脚本与 modules/CMakeLists.txt 构建系统源码系统讲解从生成模块骨架、初始化 Git 历史到接入 CMake 编译、分发模块的完整流程帮助读者掌握模块的目录规范、链接方式静态/动态/禁用以及配置文件自动复制等关键机制能够独立创建并发布自己的 AzerothCore 模块。一、模块机制概述为什么需要模块AzerothCore 的核心目标是Complete Open Source and Modular solution for MMO。其模块化架构将业务脚本scripts、游戏逻辑扩展与核心引擎解耦开发者把新玩法、自定义 Boss、NPC 脚本、公会功能等以独立目录的形式放进modules/下构建系统会自动发现并编译它们无需改动src/server/game与src/server/scripts的既有代码。这种设计带来三个直接收益可维护性每个模块独立于核心升级 AzerothCore 版本时不会因核心 diff 而产生合并冲突可分享性模块天然是可复用、可分发的最小单元社区可以像插件一样互相交换可选择性通过 CMake 的MODULES开关dynamic/static/disabled可以灵活控制每个模块的编译与链接方式按需取舍。仓库根目录 modules/ 下除 CMakeLists.txt、ModulesLoader.cpp.in.cmake、ModulesScriptLoader.h 等构建基础设施外还提供了两个关键开发辅助物create_module.sh 一键生成器以及本文所依据的官方指南 how_to_make_a_module.md。二、创建模块的三步流程官方指南把创建模块的流程高度浓缩为三个步骤先阅读官方 Wiki 了解模块规范再运行create_module.sh生成骨架最后把成果分享给社区。第一步阅读官方 Wiki正式动手前请先阅读 AzerothCore 官方 Wiki 的 Create a Module 页面它详细说明了模块的命名规范、目录结构约定与代码风格要求。这是后续步骤的文档基础本文其余章节则基于仓库源码补充其背后的实现细节。第二步运行 create_module.sh 生成模块骨架这是整个流程的核心动作。脚本位于 modules/create_module.sh针对不同操作系统提供了两种执行方式Windows使用 Git Bash 运行。如果你安装了 Git Extensions直接在脚本上右键选择 Git Bash 即可执行Linux直接用bash create_module.sh或./create_module.sh运行。脚本运行后首先会交互式询问模块名称read -p Enter the name of your future module: MODULE_NAME echo $MODULE_NAME | fgrep -q 注意这里有一个重要的命名约束脚本通过fgrep -q 检查名称中是否包含空格一旦包含空格就会反复提示Blanks are not allowed!并要求重新输入直到名称合法为止。因此模块名必须使用mod-xxx这类不含空格的短横线命名风格如mod-npc-beastmaster。输入合法名称后脚本会依次完成以下四件事# 1. 从官方骨架仓库克隆模板并去掉历史 git clone --depth 1 -b master $MODULE_TEMPLATE_URL $MODULE_NAME cd $MODULE_NAME rm -rf .git/ # 2. 初始化全新的 Git 仓库并提交首个 commit git init git add -A git commit -m Initial commit - $MODULE_NAME # 3. 为当前仓库配置提交信息模板 source $GIT_COMMIT_MSG_SETUP || bash $GIT_COMMIT_MSG_SETUP # 4. 完成 echo --- Ready to code具体含义如下浅克隆骨架模板MODULE_TEMPLATE_URL指向 AzerothCore 官方的skeleton-module仓库--depth 1 -b master表示只拉取最新一次提交保证模板最新且下载量最小。克隆完成后目标目录即命名为你输入的模块名。官方指南也提到你也可以手动克隆 skeleton-module、清理.git历史并自行配置但推荐始终使用脚本因为脚本把历史清理与 Git 配置一并自动化了清理 Git 历史删除骨架仓库自带的.git/目录避免你的模块继承 skeleton-module 的提交历史初始化全新仓库git init创建一个干净的仓库git add -A git commit生成以 Initial commit - 模块名 为信息的首个提交配置本地提交模板脚本通过source或bash调用 apps/git_tools/setup_git_commit_template.sh。该脚本执行git config --local commit.template .git_commit_template.txt只对当前模块仓库local 级别生效把提交信息模板指向.git_commit_template.txt这正是官方指南所说的add a git configuration option to this repository only (local config)。验证方式为git config -e。脚本末尾还保留了一段被注释掉的交互式代码TODO预演了未来可能的增强让用户选择代码托管平台GitHub / GitLab / Bitbucket、选择 HTTPS 或 SSH 协议并自动设置 remote origin。目前这些能力尚未启用生成的模块仓库不会自动绑定远程地址你需要自行git remote add origin ...。第三步分享给社区模块开发完成后官方指南建议通过 Discord 社区分享你的模块社区评审后可能将其官方 fork并收录进模块目录module catalogue供全社区检索与使用。此外也可以在 GitHub 上发布仓库并维护 README便于他人了解功能与安装方式。三、模块骨架的标准结构运行create_module.sh后你会得到一个符合 AzerothCore 模块规范的目录。结合构建系统源码可以还原出模块需要遵循的标准结构mod-my-module/ ├── src/ # 模块源码目录必须存在构建系统以此判定是否为模块 │ ├── *.cpp / *.h # 脚本实现与头文件 │ └── ... ├── conf/ # 配置目录存放 *.conf.dist 配置文件 ├── CMakeLists.txt # 模块自身的 CMake 构建文件 └── (可选) mod-my-module.cmake # 高级 CMake 钩子构建时会被内联进 Modules 配置关键点在于src/目录构建系统正是通过modules/名称/src是否为目录来判定该目录是否是一个有效模块的。见 ConfigureModules.cmake 中的模块发现逻辑function(GetModuleSourceList variable) GetModulesBasePath(BASE_PATH) # - ${CMAKE_SOURCE_DIR}/modules file(GLOB LOCALE_MODULE_LIST RELATIVE ${BASE_PATH} ${BASE_PATH}/*) foreach(SOURCE_MODULE ${LOCALE_MODULE_LIST}) GetPathToModuleSource(${SOURCE_MODULE} MODULE_SOURCE_PATH) if(IS_DIRECTORY ${MODULE_SOURCE_PATH}) # modules/name/src 存在才视为模块 list(APPEND ${variable} ${SOURCE_MODULE}) endif() endforeach() endfunction()也就是说任何放在modules/下且带有src/子目录的文件夹都会被自动识别为模块并纳入构建体系——这就是模块化的自动化基石。四、模块如何接入构建系统CMake 编译链路详解create_module.sh只负责生成骨架真正让模块跑起来的是 AzerothCore 的 CMake 构建体系。掌握这条链路你就能理解模块为何能被自动编译、以何种方式链接、以及如何加载。4.1 模块的发现与命名约定构建系统通过GetModuleSourceList扫描modules/下所有含src/的目录得到模块列表MODULES_MODULE_LIST。随后用ModuleNameToVariable把模块名转换成对应的链接方式变量# ConfigureModules.cmake function(ModuleNameToVariable module variable) string(TOUPPER ${module} ${variable}) # mod-foo - MOD_FOO set(${variable} MODULE_${${variable}}) # - MODULE_MOD_FOO endfunction()即模块mod-foo的链接方式由 CMake 变量MODULE_MOD_FOO控制。结合MODULES总开关dynamic/static/ 其他在 modules/CMakeLists.txt 中设定默认值if(MODULES MATCHES dynamic) set(MODULES_DEFAULT_LINKAGE dynamic) elseif(MODULES MATCHES static) set(MODULES_DEFAULT_LINKAGE static) else() set(MODULES_DEFAULT_LINKAGE disabled) endif()官方指南特别提醒的高级技巧就在这段逻辑之后如果你的模块文件夹内存在一个ModuleName.cmake文件它会被内联进 Modules 的 CMake 配置。对应实现位于 modules/CMakeLists.txt 末尾# Enables Devs to Include a cmake file in their module that will get run inline with the config. foreach(SOURCE_MODULE ${MODULES_MODULE_LIST}) include(${CMAKE_SOURCE_DIR}/modules/${SOURCE_MODULE}/${SOURCE_MODULE}.cmake OPTIONAL) endforeach()这意味着你可以编写mod-foo/mod-foo.cmake来做高级定制例如强制指定链接方式、定义编译宏、添加第三方依赖它会在每次 CMake 配置时随模块配置一并执行。这是文档中提到的Advanced CMake implementations的落地方式。4.2 三种链接方式dynamic / static / disabled模块变量取值有三种决定了模块的编译形态变量值行为产物dynamic编译为独立的动态链接库共享库运行时由 worldserver 动态加载libmod_foo.soLinux/mod_foo.dllWindowsstatic源码被直接收集进静态库modules随 worldserver 静态链接并入libmodules.a/ worldserver 二进制disabled不参与编译安装阶段还会卸载已存在的同名旧库无实现细节可对照 modules/CMakeLists.txtCollectSourceFiles与CollectIncludeDirectories负责收集源码与头文件路径ConfigureScriptLoader依据当前脚本项目是否为动态生成ACORE_IS_DYNAMIC_SCRIPTLOADER宏与加载函数声明动态模块通过add_library(... SHARED ...)创建静态模块则进入STATIC_SCRIPT_MODULES列表最终并入add_library(modules STATIC ...)。在最终的 CMake 输出中你可以看到模块依赖关系图module graph每个动态库名下列出其包含的模块disabled单独归组worldserver下列出所有静态模块。4.3 模块加载器ModulesLoader 是如何生成的无论静态还是动态模块最终都要把自己的AddXXXScripts()注册进 ScriptMgr。这一步由模板文件 ModulesLoader.cpp.in.cmake 完成——它是一份 CMake 模板配置时被configure_file渲染成真实的ModulesLoader.cpp// ModulesLoader.cpp.in.cmake节选 #cmakedefine ACORE_IS_DYNAMIC_SCRIPTLOADER ... // Includes list ACORE_SCRIPTS_FORWARD_DECL // 各模块加载函数的前置声明 #ifdef ACORE_IS_DYNAMIC_SCRIPTLOADER # define AC_MODULES_API AC_API_EXPORT // 动态模块导出宏 extern C { #else # define AC_MODULES_API #endif AC_MODULES_API void AddModulesScripts() { // Modules ACORE_SCRIPTS_INVOKE // 依次调用 Add模块名Scripts() // Deprecated api modules AC_SCRIPTS_LIST } AC_MODULES_API char const* GetModulesBuildDirective() { return AC_BUILD_TYPE; }其工作流程是ConfigureScriptLoader见 modules/CMakeLists.txt把每个模块目录名经string(REGEX REPLACE - _ ...)处理后拼出AddXXXScripts()加载函数名生成前置声明ACORE_SCRIPTS_FORWARD_DECL与调用列表ACORE_SCRIPTS_INVOKE再通过configure_file把模板渲染成最终加载器源码。静态模块由ConfigureScriptLoader(static ...)统一生成动态模块则各自独立生成。文件开头注释明确写着此文件由 CMake 根据你的脚本配置自动生成请通过重新配置 CMake 来更新切勿手动修改。4.4 模块配置文件的自动分发官方指南还隐含着模块的配置能力。构建系统会自动处理模块的conf/目录凡是modules/模块名/conf/*.conf.dist文件都会在构建时被复制到运行目录的configs/modules/下并去掉.dist后缀生成实际配置文件。相关逻辑同样在 modules/CMakeLists.txt 中foreach(ModuleName ${MODULE_LIST__}) GetPathToModuleConfig(${ModuleName} MODULE_CONFIG_PATH) # - modules/name/conf file(GLOB MODULE_CONFIG_LIST RELATIVE ${MODULE_CONFIG_PATH} ${MODULE_CONFIG_PATH}/*.conf.dist) foreach(configFileName ${MODULE_CONFIG_LIST}) CopyModuleConfig(${MODULE_CONFIG_PATH}/${configFileName}) ... endforeach() endforeach()CopyModuleConfig定义于 ConfigInstall.cmake在 Windows 下通过POST_BUILD把配置复制到bin/$(ConfigurationName)/configs/modules在 UNIX 下通过install(FILES ...)安装到${CONF_DIR}/modules。与此同时模块列表与配置列表会被编译进AC_MODULES_LIST与CONFIG_FILE_LIST两个宏target_compile_options供世界服务器在运行时识别已加载的模块与配置。五、模块开发的典型工作流与最佳实践综合官方指南与源码实现一个完整的模块开发工作流如下生成骨架在仓库根目录的modules/下运行bash create_module.sh输入不含空格的模块名推荐mod-前缀编写脚本在生成的src/中实现你的脚本类如继承CreatureScript、PlayerScript、WorldScript等并注册AddMyModuleScripts()加载函数可选添加配置在conf/下放置mod-mymodule.conf.dist构建时会自动分发为运行配置可选高级定制编写mod-mymodule.cmake实现高级 CMake 配置该文件会在构建配置时被自动 include编译验证以-DMODULESdynamic或为单模块设置-DMODULE_MOD_FOOstatic重新配置并编译观察 CMake 输出的模块依赖图确认模块被正确识别与链接测试与提交使用仓库内apps/git_tools/setup_git_commit_template.sh已配置的提交模板保持提交信息规范提交到本地 Git 仓库发布分享将仓库推送到公开托管平台需自行git remote add origin并在 Discord 社区分享争取收录进模块目录。实践建议保持模块名与目录名、CMake 变量名的一致遵循mod-命名惯例避免空格与特殊字符充分利用三种链接方式开发调试期用dynamic便于单独替换.so/.dll正式部署或追求启动性能时可切换static减少动态加载开销若你的模块需要覆盖或卸载旧版动态库使用disabled状态即可构建系统在安装阶段会清理对应产物若从旧版本 AzerothCore 迁移模块注意 modules/CMakeLists.txt 中 Add support old api modules 的兼容逻辑使用旧版 loader API 的模块会被强制按static编译。六、小结AzerothCore 的模块机制是一条从一键生成到自动编译再到配置分发的完整链路create_module.sh 解决模块骨架与 Git 历史初始化ConfigureModules.cmake 负责模块发现与命名modules/CMakeLists.txt 处理链接方式、加载器生成与配置分发ModulesLoader.cpp.in.cmake 最终把所有模块脚本注册进 ScriptMgr。理解这条链路你不仅能按官方三步流程快速创建模块还能在遇到编译、链接或加载问题时直接从构建系统源码层面定位根因真正把模块化开发用到实处。【免费下载链接】azerothcore-wotlkComplete Open Source and Modular solution for MMO项目地址: https://gitcode.com/GitHub_Trending/az/azerothcore-wotlk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询