前言

最近又玩儿起了求生之路2,但是服务器玩儿法太单一了,想用AI整点儿活儿,写点儿奇奇怪怪的插件,或者改下别人的插件,上传到自己的服务器,那么问题就来了,我们怎么去制作一个插件呢?写代码用AI,环境得咱们自己搭建一下,这里记录下插件编译环境的搭建。

之前写过一篇比较简陋的SourceMOD环境搭建,今天专门写一篇针对求生之路2插件编写的环境搭建。

安装VScode

我们就选微软的这个编辑器来做我们的工作台啊,它有丰富的插件,而且免费,点击链接下载安装 -> Visual Studio Code。

安装完成后,我们需要在VScode的插件市场安装三个插件:

  • Chinese (Simplified) (简体中文):中文支持
  • SourcePawn Studio:用于SP代码的高亮、语义检查、编译等
  • All Autocomplete:用于代码补全,方便写代码

image-20261013181155963

下载SourceMod

这里就是重点了,既然要编译源码,那我们就得下载编译器,直接下载SourceMod,里面包含编译工具 -> SourceMod下载。

直接点击那个Windows图标进行下载,目前最新版本是1.12 - build 7255。

image-20261013181851114

构建插件工作目录

接下来我们新建一个文件夹,专门用于开发求生之路2的插件,这里我的文件夹就叫l4d2-plugin,我的这个工作目录已经上传到Github了,读者们可以直接去InsectMk/l4d2-plugin查阅。我这里直接说明目录的结构,读者们可以选择自行创建,或者下载我的仓库文件后自行修改,文件结构如下(对于下面的spcomp.exe、compile.exe与include文件夹,我们需要去下载的SourceMod压缩包中提取,解压后的addons/sourcemod/scripting目录下):

image-20261013184952659

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
l4d2-plugin/                ← 工作区根
│
├── spcomp.exe ← SourcePawn 编译器(所有插件共用)
├── compile.exe ← SourcePawn 的封装调用工具
│
├── include/ ← 官方头文件层(公共基础库)
│ ├── sourcemod.inc
│ └── ...(其他 SourceMod 官方 .inc)
│
├── include-ext/ ← 跨插件共享的第三方 include(多个插件共用的库放这里)
│ ├── README.md ← 本目录使用说明
│ ├── multicolors.inc
│ ├── left4dhooks_silver.inc
│ └── ...(按需添加)
│
├── plugins/ ← 编译产物(与服务器 addons/sourcemod/plugins/ 同名)
│ ├── plugin_hello.smx
│ └── plugin_admin.smx
│
├── source/ ← 插件源码根目录
│ │
│ ├── plugin_hello/ ← 插件 A:示例 / 学习插件
│ │ ├── hello.sp ← 主源码文件
│ │ └── include/ ← 插件私有头文件(只属于这个插件)
│ │ ├── multicolors.inc
│ │ └── multicolors/ ← 兼容某些库用子目录组织 include 的情况
│ │ ├── morecolors.inc
│ │ └── colors.inc
│ │
│ ├── plugin_xxB/ ← 插件 B:xx相关插件
│ │ ├── plugin_xxB.sp
│ │ └── include/
│ │ └── left4dhooks_silver.inc
│ │
│ └── plugin_xxB/ ← 插件 C:xx相关插件
│ ├── plugin_xxB.sp
│ └── include/
│ └── (按需添加)

SourcePawn Studio配置

文件创建完成后,直接使用VScode打开该文件夹,目前对VScode来说还只是一种在编辑文本的状态,还并没有配好编译的流程。

我们之前下载了SourcePawn Studio插件,但是该插件需要进行配置,你可以通过图形界面进行设置,但是这里为了方便就直接使用VScode工作区配置settings.json的方式去配置,我们在l4d2-plugin下新建一个文件.vscode/settings.json,如果你下载我的Github仓库,就直接复制.vscode/settings.json.example,将.example后缀去除并修改即可,模板内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{
// ============================================================
// L4D2 SourceMod 插件工作区 - VSCode 配置模板
// ------------------------------------------------------------
// 使用方式:
// 1. 复制本文件为 .vscode/settings.json
// 2. 把所有 "xxxx" 占位符替换为你本机/服务器的实际值
// 3. 切勿把真实的 settings.json 提交到 Git(已通过 .gitignore 排除)
//
// 本文件本身是脱敏后的模板,可以安全提交到仓库
// ============================================================

// 指定 SourcePawn 编译器(spcomp.exe)的位置,使用绝对路径
// ⚠️ 把路径中的 xxxx 替换为你的 Windows 用户名
"SourcePawnLanguageServer.compiler.path": "C:/Users/xxxx/Documents/Hub/l4d2-plugin/spcomp.exe",

// 额外的头文件搜索路径(数组形式,可以写多个)
// 比如你项目里自己写的或者第三方插件的 include 文件放在别的文件夹,就加在这里
// 编译时,默认会带入sp源码同目录下的 include 文件夹
// ⚠️ 把路径中的 xxxx 替换为你的 Windows 用户名
"SourcePawnLanguageServer.includeDirectories": [
"C:/Users/xxxx/Documents/Hub/l4d2-plugin/include",
"C:/Users/xxxx/Documents/Hub/l4d2-plugin/include-ext"
],

// 编译后的 .smx 插件文件输出到哪个文件夹
// 这里配置后,按 ctrl + shift + d 编译,生成的 .smx 就会自动放进 该 文件夹,使用绝对路径
// ⚠️ 把路径中的 xxxx 替换为你的 Windows 用户名
"sourcepawn.outputDirectoryPath": "C:/Users/xxxx/Documents/Hub/l4d2-plugin/plugins/",

// 游戏服务器连接配置(用于远程编译、热重载插件或 RCON 管理)
"sourcepawn.SourceServerOptions": {
// 服务器的域名或 IP 地址
// ⚠️ 替换为你的服务器地址
"host": "xxxx",

// 服务器的端口号
"port": 27015,

// 通信时使用的字符编码,一般保持 ascii 即可
"encoding": "ascii",

// 连接服务器的超时时间(单位:毫秒),1000 = 1秒
"timeout": 1000,

// ⚠️ 服务器 RCON 或连接密码(敏感信息,不要提交到 Git!)
// ⚠️ 替换为你的 RCON 密码
"password": "xxxx"
},
// 编译成功后是否自动把 .smx 上传到服务器(依赖下方 UploadOptions)
// true = 上传并触发 RCON 重载;false = 仅在本地生成 .smx,不上传
"sourcepawn.uploadToServerAfterCompile": false,
// SFTP/FTP 上传配置(当 uploadToServerAfterCompile = true 时生效)
// 上传时按本地目录结构镜像推送到 remoteRoot 下,所以 plugins/foo.smx 会上传到 <remoteRoot>/plugins/foo.smx
"sourcepawn.UploadOptions": {
// SFTP/FTP 服务器的域名或 IP(可与 SourceServerOptions.host 不同)
// ⚠️ 替换为你的服务器地址
"host": "xxxx",

// 端口:SFTP=22,FTP=21
"port": 21,

// SFTP/FTP 登录用户名
// ⚠️ 替换为你的 SSH/FTP 用户名
"username": "xxxx",

// SFTP/FTP 登录密码(敏感信息,不要提交到 Git!)
// 用 SSH 密钥免密登录时留空
// ⚠️ 替换为你的 SSH/FTP 密码
"password": "xxxx",

// 是否使用 SFTP 协议(true=SFTP,false=FTP),推荐 SFTP 更安全
"sftp": false,

// 服务器上 SourceMod 的根目录的父目录,所有上传文件会按本地目录结构镜像到此目录下
// L4D2 一般为:/your/l4d2/server/left4dead2/addons/sourcemod
"remoteRoot": "/your/l4d2/server/left4dead2/addons/sourcemod",

// 上传时需要排除的文件/目录(glob 模式)
// 排除掉源码、配置、文档等,避免把开发文件推上生产服务器
"exclude": [
"source/**/",
"include/**/",
"include-ext/**/",
".vscode/**/",
".github/**/",
".gitignore",
"*.md",
".git",
"compile.dat",
"*.exe",
"LICENSE",
]
},
// 创建新插件脚手架时使用的 GitHub 用户名(SourcePawn Studio 内部使用)
// ⚠️ 替换为你的 GitHub 用户名
"sourcepawn.GithubName": "xxxx",

// 新建插件时自动填入 myinfo.author 字段的作者名
// ⚠️ 替换为你的昵称
"sourcepawn.AuthorName": "xxxx",

// 是否禁用 SourcePawn 语言服务器的内置 Linter
// false = 启用检查(推荐,会高亮潜在问题);true = 关闭所有 Lint 告警
"SourcePawnLanguageServer.linter.disable": false,
}

//开头的全为注释,可删除可保留。

纯本地开发

对于只需要本地开发(本地编译生成.smx后缀的插件后,自行上传到服务器)的读者来说,只需要修改配置模板中的下面几个参数即可:

  • SourcePawnLanguageServer.compiler.path:编译器的路径,改成你l4d2-plugin/spcomp.exe的绝对路径就行了
  • SourcePawnLanguageServer.includeDirectories:编译时需要链接的头文件目录,改成你l4d2-plugin/include与l4d2-plugin/include-ext的绝对路径就行了
  • sourcepawn.outputDirectoryPath:存放编译后产生的.smx插件的目录,这里就用l4d2-plugin/plugins,与服务器的left4dead2/addons/sourcemod/plugins保持同名,如果你只需要本地开发的话,你可以随意命名

热部署开发 (推荐)

场景:每次编译后,直接将最新编译.smx后缀的插件上传到服务器插件目录,并重载插件以便于游戏内测试,settings.json配置步骤如下:

  1. 配置sourcepawn.SourceServerOptions

    直接看配置文件中的注释去配置即可,是用于在上传插件后在服务器l4d2终端中执行类似sm plugins reload xxxPlugin这样的指令以热更新插件的更改

    其中有些踩坑点:服务端的启动参数上需要加上-ip 0.0.0.0,这样你的开发机才能访问;password是在服务器left4dead2/cfg/server.cfg中配置的rcon_password内容

  2. 配置sourcepawn.uploadToServerAfterCompile:改成true就行了,表示编译后需要自动上传内容到服务器

  3. 配置sourcepawn.UploadOptions:与上面那个选项相关联,开启上面的选项后,使用此配置执行上传任务,还是阅读模板注释自行配置

    这里建议直接开启sftp,port就直接写SSH的端口就行了,一般为22,username与password填写具有文件夹权限的用户就行了。

    remoteRoot就填服务器left4dead2/addons/sourcemod的绝对路径,这样与插件的存放目录plugins一拼接,就可以直接将插件放到服务器正确的插件目录了。

    exclude已经给你配好了,上传是会将l4d2-plugin下所有的内容上传到remoteRoot配置的路径的,排除不要上传的目录、文件就行。

踩坑:自动编译上传并重载后,源码中的配置文件描述并不会同步到addons/cfg/sourcemod/xxx.cfg,哪怕删了也不行,需要关闭服务器并删除该文件,重启服务器后正确生成

编写代码

好了,完成上面的步骤就可以进行实际的开发了,我们在l4d2-plugin/source下新建一个插件源码l4d2-plugin/source/hello/hello.sp,写入以下测试内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>

#define PLUGIN_NAME "Hello"
#define PLUGIN_AUTHOR "InsectMk"
#define PLUGIN_DESCRIPTION "聊天框输入 !hello 或控制台输入 sm_hello 后向全服公屏打印 Hello World!"
#define PLUGIN_VERSION "1.0"
#define PLUGIN_URL ""

public Plugin myinfo = {
name = PLUGIN_NAME,
author = PLUGIN_AUTHOR,
description = PLUGIN_DESCRIPTION,
version = PLUGIN_VERSION,
url = PLUGIN_URL
};

public void OnPluginStart() {
RegConsoleCmd("sm_hello", cmdHello, "向全服公屏打印 Hello World!");
}

public Action cmdHello(int client, int args) {
PrintToChatAll("Hello World!");
return Plugin_Handled;
}

// 实现此 forward 即可自动接收聊天框中的 !hello / @hello,无需手动注册
public Action OnPlayerCommandChat(int client, int command, const char[] args) {
return cmdHello(client, 0);
}

让鼠标聚焦到hello.sp编辑框,右键 -> Compile file 或者直接 ctrl + shift + D,执行后,会在l4d2-plugin/plugins目录下生成hello.smx

image-20261013192943129

上传成功后,直接生效,不用重启服务器,也不用自己在终端输入reload指令,游戏内按u发送!hello即会打印Hello World!效果如图:

image-20261013194530091

至此,你已经可以借助AI工具自主测试开发求生插件了🥳🥳🥳!!!