news 2026/9/16 14:31:37

AzerothCore 自定义脚本(Custom Scripts)接入指南:CMake 注册、脚本加载器与模块化开发

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AzerothCore 自定义脚本(Custom Scripts)接入指南:CMake 注册、脚本加载器与模块化开发

AzerothCore 自定义脚本(Custom Scripts)接入指南:CMake 注册、脚本加载器与模块化开发

【免费下载链接】azerothcore-wotlkComplete Open Source and Modular solution for MMO项目地址: https://gitcode.com/GitHub_Trending/az/azerothcore-wotlk

AzerothCore 为服务端开发者保留了独立的Custom脚本目录,让你可以在不污染官方源码的前提下,将自研的 NPC、法术、事件等脚本直接编译进worldserver。本指南基于 src/server/scripts/Custom/README.md 完整展开,并结合仓库内 CMake 宏定义、脚本加载器模板与真实脚本样例,说明如何从零注册一个自定义脚本、理解其编译链路,以及如何权衡"简单脚本"与"官方模块系统"两种方案。

Custom 目录的定位:被 Git 忽略的官方保留地

在 src/server/scripts 目录下,Custom是与WorldSpellsEasternKingdomsNorthrend等官方脚本模块并列的一级目录。它的特殊之处体现在仓库根目录的 .gitignore 中:

/src/server/scripts/Custom/* !/src/server/scripts/Custom/README.md

也就是说,该目录下除 README 外的所有内容都会被 Git 忽略。这意味着:

  • 你新增的.cpp.h以及CMakeLists.txt不会进入版本控制,也不会在git status/git diff中干扰官方更新;
  • 官方升级、拉取上游代码时不会与你的私有脚本冲突;
  • 该目录天然适合存放仅在本服使用的、不便公开的定制逻辑。

需要强调的是,该目录并非空目录——仓库内已预置一个最小示例 src/server/scripts/Custom/custom_script_loader.cpp,它定义了AddCustomScripts()空实现,作为你注册脚本时的参考起点。只要该文件存在,即使你尚未添加任何自定义脚本,构建系统也能正常工作。

为什么官方建议"优先使用模块系统"

README 中有一段醒目的建议(原文以**/!\ BTW**强调):强烈建议开发者使用模块系统(module system)来创建强大的自定义模块,而不是简单脚本

这一建议与仓库的实际结构相互印证:

  • modules 目录下提供了完整的模块化开发入口:modules/how_to_make_a_module.md 说明了模块创建流程(核心是运行 modules/create_module.sh),modules/CMakeLists.txt 展示了模块如何被独立收集、编译并链接进世界服务器;
  • 模块可以自带配置、数据库 SQL、独立的目录结构与社区分享能力,而 Custom 脚本仅能提供纯 C++ 逻辑。

因此合理的决策路径是:临时性、规模小、无需共享的逻辑放进Custom脚本;具备完整功能、需要配置项或打算开源分享的功能,走模块系统。本指南剩余部分专注于 Custom 脚本的接入细节。

第一步:在 Custom 目录创建 CMakeLists.txt

完整的注册模板

在 src/server/scripts/Custom/ 下新建CMakeLists.txt,内容如下(README 明确说明"以下所有内容都是必需的",只需替换成你自己的脚本名):

set(scripts_STAT_SRCS ${scripts_STAT_SRCS} ${AC_SCRIPTS_DIR}/Custom/your_script.cpp ${AC_SCRIPTS_DIR}/Custom/your_script.h ) AC_ADD_SCRIPT_LOADER("Custom" "ScriptLoader.h") message(" -> Prepared: My custom scripts")

各部分的作用:

片段作用
set(scripts_STAT_SRCS ...)把自定义脚本的.cpp/.h追加到脚本库源码列表中,${AC_SCRIPTS_DIR}指向src/server/scripts目录,因此${AC_SCRIPTS_DIR}/Custom/...即定位到本目录下的源文件
AC_ADD_SCRIPT_LOADER("Custom" "ScriptLoader.h")核心注册宏:声明并登记名为Custom的加载函数(详见下文"宏的底层行为")
message(...)在 CMake 配置阶段输出一行提示,便于确认你的脚本已被收集

宏的底层行为:AC_ADD_SCRIPT_LOADER 做了什么

该宏定义在 src/cmake/ac_macros.cmake 中,核心逻辑如下:

  • 它以"Custom"为参数,向全局列表AC_ADD_SCRIPTS_LIST追加条目AddCustomScripts();——即加载函数命名约定为Add${目录名}Scripts()
  • 第二个参数"ScriptLoader.h"会被登记进AC_ADD_SCRIPTS_INCLUDE全局列表,用于后续生成加载器时的头文件引用;
  • 宏还支持可变参数ARGN:当传入额外模块名时,可把低优先级模块从脚本列表中原位移除并重新追加,实现加载顺序的精细控制(对应源码中-- ${script_dec} demands lower priority: ...的提示信息)。

这些全局列表最终流向 modules/CMakeLists.txt:宏收集到的AC_ADD_SCRIPTS_LIST会生成void AddCustomScripts();前向声明与调用语句,说明Custom 脚本与模块共享同一套加载器生成机制

第二步:将脚本登记进 ScriptLoader.cpp

README 的第二个步骤是:打开ScriptLoader.cpp,翻到文件末尾,按同样的风格追加脚本声明与调用。

注意:ScriptLoader.cpp 是自动生成的

与直觉相反,src/server/scripts 目录下并不存在手写的ScriptLoader.cpp。它由模板 src/server/scripts/ScriptLoader.cpp.in.cmake 在 CMake 配置阶段自动生成,生成逻辑位于 src/server/scripts/CMakeLists.txt 的ConfigureScriptLoader函数中:

  • 模板中的@ACORE_SCRIPTS_FORWARD_DECL@被替换为一系列加载函数的前向声明;
  • @ACORE_SCRIPTS_INVOKE@被替换为AddScripts()内部对每个加载函数的调用;
  • 生成文件输出到构建目录(如gen_scriptloader/.../ScriptLoader.cpp),因此不要在源码树中手改生成文件——正确做法是通过 CMake 宏登记,然后重新运行 CMake 配置。

以官方模块 src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp 为参照,其结构为"先声明void AddSC_xxx();,再在AddEasternKingdomsScripts()中逐一调用"。Custom 目录的对应文件 src/server/scripts/Custom/custom_script_loader.cpp 同样遵循此模式:

// 示例:声明你的脚本加载函数 // void AddSC_your_script_name(); void AddCustomScripts() { // AddSC_your_script_name(); }

注意其注释明确提示:加载函数名必须与Add${目录名}Scripts()约定一致,此处目录名为Custom,故为AddCustomScripts()。该函数经由宏登记后,会被自动生成的前向声明与AddScripts()调用链挂载,最终由世界服务器启动时通过ScriptMgr完成注册。

第三步:编写脚本本体并注册到 ScriptMgr

脚本文件的基本形态

以官方示例 src/server/scripts/World/npc_innkeeper.cpp 为模板,一个最简脚本通常包含两部分:

  1. 脚本类:继承CreatureScriptSpellScriptPlayerScript等基类(见 src/server/scripts/ScriptPCH.h 中的预编译头引用),在构造函数中传入脚本名;
  2. 加载函数:与声明一一对应的AddSC_xxx()函数,内部执行new npc_xxx;完成实例化:
void AddSC_npc_innkeeper() { new npc_innkeeper; }

对象构造时,脚本会经由 src/server/game/Scripting/ScriptDefines 下的ScriptRegistry<T>::AddScript(...)注册进全局ScriptMgr,之后即可被世界服务器按脚本名检索调用。

完整接入步骤总结

  1. your_script.cpp(及可选的your_script.h)放入 src/server/scripts/Custom/;
  2. 按上文模板创建CMakeLists.txt并替换文件名;
  3. 在 src/server/scripts/Custom/custom_script_loader.cpp 中声明并调用你的AddSC_xxx()
  4. 重新运行 CMake 配置并重新编译世界服务器(静态编译模式下脚本直接链接进worldserver,动态模式下则生成独立的脚本共享库,构建细节见 src/server/scripts/CMakeLists.txt 中的SCRIPTS构建选项)。

验证与排错

  • CMake 配置输出:若你的CMakeLists.txt生效,配置阶段应能看到-> Prepared: My custom scripts提示,同时脚本模块树(script graph)中会列出Custom模块及其链接方式(static / dynamic / disabled);
  • Add${目录名}Scripts命名约定:加载函数名与目录名不一致是常见的链接报错来源,可对照 src/server/scripts/CMakeLists.txt 中"Add${LOCALE_SCRIPT_MODULE}Scripts()"的生成规则逐一核对;
  • Git 状态确认:由于.gitignore忽略规则,git status中不应出现Custom目录下的新文件,这是该机制生效的直观信号。

结语:两条路径的取舍

本文完整复刻并深化了 src/server/scripts/Custom/README.md 的全部步骤:创建CMakeLists.txt收集源码、通过AC_ADD_SCRIPT_LOADER宏登记加载器、在自动生成的ScriptLoader.cpp链路中挂载AddCustomScripts(),最终由ScriptMgr注册生效。若你的需求只是少量私有逻辑,Custom 目录是零侵入的快捷通道;若你希望功能具备配置能力、可维护性与社区分享价值,则应转向 modules/how_to_make_a_module.md 描述的模块系统——两者共享同一套脚本注册机制,迁移成本也因此保持在较低水平。

【免费下载链接】azerothcore-wotlkComplete Open Source and Modular solution for MMO项目地址: https://gitcode.com/GitHub_Trending/az/azerothcore-wotlk

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 14:30:40

Node.js+Vue自习室预约系统架构设计与实践

1. 项目背景与核心价值自习室预约管理系统是当前高校和公共图书馆数字化转型中的刚需产品。传统的人工登记方式存在排队时间长、座位利用率低、管理成本高等痛点。我们团队基于Node.jsVue技术栈开发的这套系统&#xff0c;在3所高校实际运行中实现了95%以上的座位利用率&#x…

作者头像 李华
网站建设 2026/9/16 14:29:40

Android工业RFID开发:Java直驱HAL层实战指南

简介&#xff1a;这是一套面向Android开发初学者与RFID行业应用开发者的学习型实战源码&#xff0c;聚焦于仓储物流场景下的物料全流程追踪管理。项目基于Java语言开发&#xff0c;完整实现盘询标签、物料入托、托盘/物料入库与出库等核心业务功能&#xff0c;可直接部署到Andr…

作者头像 李华
网站建设 2026/9/16 14:29:40

亚马逊A9算法与领导者效应实战解析

1. 亚马逊商业生态中的"领导者效应"解析在亚马逊这个全球最大的电商平台上&#xff0c;"成为第一"绝非简单的营销口号&#xff0c;而是一个经过验证的商业法则。作为从业多年的亚马逊运营专家&#xff0c;我发现许多卖家对"领导者效应"的理解仅停…

作者头像 李华