<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[samp | open.mp 联机社区论坛 - 门户]]></title>
		<link>https://open-mp.cn/</link>
		<description><![CDATA[samp | open.mp 联机社区论坛 - https://open-mp.cn]]></description>
		<pubDate>Fri, 19 Jun 2026 11:11:23 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[PawnREST - HTTP/S 文件传输与 REST API]]></title>
			<link>https://open-mp.cn/showthread.php?tid=36</link>
			<pubDate>Thu, 11 Jun 2026 21:59:11 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=1">siwode</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=36</guid>
			<description><![CDATA[<span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">PawnREST - HTTP/S 文件传输与 REST API 框架</span></span><br />
<br />
一个为 SA-MP/open.mp 服务器提供 HTTP/S 文件上传下载功能以及完整 REST API 框架的插件。<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: xx-large;" class="mycode_size">下载地址 <a href="https://github.com/Fanorisky/PawnREST" target="_blank" rel="noopener" class="mycode_url">https://github.com/Fanorisky/PawnREST</a></span></span><br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Wiki 文档</span></span><br />
<br />
API 文档与使用指南位于：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>wiki/</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Pawn 示例脚本</span></span><br />
<br />
示例脚本位于：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>example/</code></div></div><ul class="mycode_list"><li>01_server_routes.pwn - 自定义 REST 路由示例<br />
</li>
<li>02_file_routes_and_ops.pwn - 文件路由与文件操作示例<br />
</li>
<li>03_json_nodes.pwn - JSON 节点创建与响应示例<br />
</li>
<li>04_outbound_uploads.pwn - 外部文件上传示例<br />
</li>
<li>05_outbound_requests.pwn - HTTP/S 请求客户端示例<br />
</li>
<li>06_websocket_client.pwn - WebSocket 客户端示例<br />
</li>
<li>07_crc_utils.pwn - CRC32 校验与文件比较工具<br />
</li>
<li>08_request_input_fallbacks.pwn - 请求参数读取示例<br />
</li>
<li>09_discord_webhook.pwn - Discord Webhook 集成示例<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✨ 功能特性</span></span><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">文件上传服务器</span> - 通过 HTTP POST 接收文件并进行验证<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">文件下载 API</span> - 通过 HTTP GET 提供文件下载<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">外部文件上传</span> - 上传文件到第三方服务器<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">上传客户端</span> - 复用基础 URL 与默认请求头<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">HTTP 请求客户端</span> - REST_Request / REST_RequestJSON<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">WebSocket 客户端</span> - 支持 ws:// 与 wss://<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">REST API 框架</span> - 支持 GET、POST、PUT、PATCH、DELETE、HEAD、OPTIONS<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">强大的请求访问器</span> - URL 查询参数与 Header 解析<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">纯节点 JSON API</span> - JSON 构建与解析<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">鉴权系统</span> - Bearer Token 路由认证<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">HTTPS/TLS 支持</span> - OpenSSL 支持<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">结构化错误回调</span> - 提供详细错误信息<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">CRC32 完整性校验</span> - 文件校验验证<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">安装方法</span></span><br />
<br />
<ol type="1" class="mycode_list"><li>下载适用于你平台的最新版本（Windows 为 .dll，Linux 为 .so）<br />
</li>
<li>放入 open.mp 服务器的 components 目录<br />
</li>
<li>将 PawnREST.inc 放入 Pawn 编译器 include 目录<br />
</li>
<li>在脚本中添加：<br />
</li>
</ol>
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;PawnREST&gt;</code></div></div><br />
公共 API 使用以下前缀：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>REST_*  // HTTP 与 REST 功能<br />
FILE_*  // 文件上传下载功能</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">快速开始</span></span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
#include &lt;PawnREST&gt;<br />
new g_MapRoute = -1;<br />
new g_ApiPlayers = -1;<br />
public OnGameModeInit()<br />
{<br />
    REST_Start(8080);<br />
    g_MapRoute = FILE_RegisterRoute(<br />
        "/maps",<br />
        "scriptfiles/maps/",<br />
        ".map,.json",<br />
        50<br />
    );<br />
    FILE_AddAuthKey(g_MapRoute, "upload-secret-key");<br />
    FILE_AllowList(g_MapRoute, true);<br />
    FILE_AllowDownload(g_MapRoute, true);<br />
    g_ApiPlayers = REST_RegisterAPIRoute(<br />
        HTTP_METHOD_GET,<br />
        "/api/players",<br />
        "OnGetPlayers"<br />
    );<br />
    REST_SetRouteAuthKey(g_ApiPlayers, "api-secret-key");<br />
    return 1;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">HTTP 方法常量</span></span><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">常量</span></td>
<td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">对应方法</span></td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_GET</td>
<td style="border:1px solid #ddd;padding:6px 10px;">GET</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_POST</td>
<td style="border:1px solid #ddd;padding:6px 10px;">POST</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_PUT</td>
<td style="border:1px solid #ddd;padding:6px 10px;">PUT</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_PATCH</td>
<td style="border:1px solid #ddd;padding:6px 10px;">PATCH</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_DELETE</td>
<td style="border:1px solid #ddd;padding:6px 10px;">DELETE</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_HEAD</td>
<td style="border:1px solid #ddd;padding:6px 10px;">HEAD</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_OPTIONS</td>
<td style="border:1px solid #ddd;padding:6px 10px;">OPTIONS</td>
</tr>
</table>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">文件上传路由</span></span><br />
<br />
支持：<br />
<ul class="mycode_list"><li>上传文件<br />
</li>
<li>文件列表<br />
</li>
<li>文件下载<br />
</li>
<li>文件删除<br />
</li>
<li>文件信息查询<br />
</li>
<li>CRC32 校验<br />
</li>
<li>上传鉴权<br />
</li>
<li>冲突处理策略<br />
</li>
</ul>
<br />
主要函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>FILE_RegisterRoute(...)<br />
FILE_AddAuthKey(...)<br />
FILE_AllowList(...)<br />
FILE_AllowDownload(...)<br />
FILE_AllowDelete(...)<br />
FILE_AllowInfo(...)<br />
FILE_Delete(...)<br />
FILE_GetCount(...)<br />
FILE_GetSize(...)</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">REST API 路由</span></span><br />
<br />
注册自定义接口：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>REST_RegisterAPIRoute(<br />
    HTTP_METHOD_GET,<br />
    "/api/server",<br />
    "OnGetServer"<br />
);</code></div></div><br />
支持：<br />
<ul class="mycode_list"><li>GET<br />
</li>
<li>POST<br />
</li>
<li>PUT<br />
</li>
<li>PATCH<br />
</li>
<li>DELETE<br />
</li>
<li>HEAD<br />
</li>
<li>OPTIONS<br />
</li>
</ul>
<br />
支持 URL 参数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/api/player/{id}</code></div></div><br />
示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/api/player/5</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">请求数据读取</span></span><br />
<br />
支持：<br />
<ul class="mycode_list"><li>客户端 IP<br />
</li>
<li>HTTP 方法<br />
</li>
<li>请求路径<br />
</li>
<li>请求体 Body<br />
</li>
<li>URL 参数<br />
</li>
<li>Query 参数<br />
</li>
<li>HTTP Header<br />
</li>
</ul>
<br />
例如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>REST_GetParamInt(requestId, "id");<br />
REST_GetQueryInt(requestId, "page");<br />
REST_GetHeader(requestId, "Authorization");</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">JSON API</span></span><br />
<br />
特点：<br />
<ul class="mycode_list"><li>纯 Node 节点系统<br />
</li>
<li>JSON 解析<br />
</li>
<li>JSON 构建<br />
</li>
<li>对象与数组操作<br />
</li>
<li>序列化输出<br />
</li>
</ul>
<br />
创建对象：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new payload = JsonObject(<br />
    "name", JsonString("PawnREST"),<br />
    "version", JsonString("1.0")<br />
);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">响应函数</span></span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>Respond(...)<br />
RespondJSON(...)<br />
RespondNode(...)<br />
RespondError(...)<br />
SetResponseHeader(...)</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">☁️ 外部 HTTP 请求</span></span><br />
<br />
支持：<br />
<ul class="mycode_list"><li>HTTP 请求<br />
</li>
<li>JSON 请求<br />
</li>
<li>请求取消<br />
</li>
<li>请求状态查询<br />
</li>
<li>错误信息获取<br />
</li>
</ul>
<br />
主要函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>REST_CreateRequestClient(...)<br />
REST_Request(...)<br />
REST_RequestJSON(...)</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">WebSocket 客户端</span></span><br />
<br />
支持：<br />
<ul class="mycode_list"><li>文本 WebSocket<br />
</li>
<li>JSON WebSocket<br />
</li>
<li>TLS/WSS<br />
</li>
<li>发送消息<br />
</li>
<li>关闭连接<br />
</li>
</ul>
<br />
主要函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>REST_WebSocketClient(...)<br />
REST_JsonWebSocketClient(...)<br />
REST_WebSocketSend(...)<br />
REST_JsonWebSocketSend(...)</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CRC32 工具</span></span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>FILE_VerifyCRC32(...)<br />
FILE_GetCRC32(...)<br />
FILE_Compare(...)</code></div></div><br />
用于：<br />
<ul class="mycode_list"><li>文件完整性验证<br />
</li>
<li>上传校验<br />
</li>
<li>文件比较<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">回调列表</span></span><br />
<br />
上传相关：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>OnIncomingUploadCompleted<br />
OnIncomingUploadFailed<br />
OnIncomingUploadProgress<br />
OnOutgoingUploadStarted<br />
OnOutgoingUploadProgress<br />
OnOutgoingUploadCompleted<br />
OnOutgoingUploadFailed</code></div></div><br />
请求相关：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>OnRequestFailure<br />
OnWebSocketDisconnect</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">内置接口</span></span><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">接口</span></td>
<td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">说明</span></td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">GET /health</td>
<td style="border:1px solid #ddd;padding:6px 10px;">健康检查</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">GET /stats</td>
<td style="border:1px solid #ddd;padding:6px 10px;">服务器统计</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">GET {route}/files</td>
<td style="border:1px solid #ddd;padding:6px 10px;">获取文件列表</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">GET {route}/files/{name}</td>
<td style="border:1px solid #ddd;padding:6px 10px;">下载文件</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">GET {route}/files/{name}/info</td>
<td style="border:1px solid #ddd;padding:6px 10px;">获取文件信息</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">DELETE {route}/files/{name}</td>
<td style="border:1px solid #ddd;padding:6px 10px;">删除文件</td>
</tr>
</table>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">鸣谢</span></span><br />
<ul class="mycode_list"><li>yhirose - HTTP 库<br />
</li>
<li>Southclaws - pawn-requests API 参考<br />
</li>
<li>Fanorisky - 项目实现<br />
</li>
<li>SA-MP Team<br />
</li>
<li>open.mp Contributors<br />
</li>
</ul>
]]></description>
			<content:encoded><![CDATA[<span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">PawnREST - HTTP/S 文件传输与 REST API 框架</span></span><br />
<br />
一个为 SA-MP/open.mp 服务器提供 HTTP/S 文件上传下载功能以及完整 REST API 框架的插件。<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: xx-large;" class="mycode_size">下载地址 <a href="https://github.com/Fanorisky/PawnREST" target="_blank" rel="noopener" class="mycode_url">https://github.com/Fanorisky/PawnREST</a></span></span><br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Wiki 文档</span></span><br />
<br />
API 文档与使用指南位于：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>wiki/</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Pawn 示例脚本</span></span><br />
<br />
示例脚本位于：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>example/</code></div></div><ul class="mycode_list"><li>01_server_routes.pwn - 自定义 REST 路由示例<br />
</li>
<li>02_file_routes_and_ops.pwn - 文件路由与文件操作示例<br />
</li>
<li>03_json_nodes.pwn - JSON 节点创建与响应示例<br />
</li>
<li>04_outbound_uploads.pwn - 外部文件上传示例<br />
</li>
<li>05_outbound_requests.pwn - HTTP/S 请求客户端示例<br />
</li>
<li>06_websocket_client.pwn - WebSocket 客户端示例<br />
</li>
<li>07_crc_utils.pwn - CRC32 校验与文件比较工具<br />
</li>
<li>08_request_input_fallbacks.pwn - 请求参数读取示例<br />
</li>
<li>09_discord_webhook.pwn - Discord Webhook 集成示例<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✨ 功能特性</span></span><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">文件上传服务器</span> - 通过 HTTP POST 接收文件并进行验证<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">文件下载 API</span> - 通过 HTTP GET 提供文件下载<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">外部文件上传</span> - 上传文件到第三方服务器<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">上传客户端</span> - 复用基础 URL 与默认请求头<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">HTTP 请求客户端</span> - REST_Request / REST_RequestJSON<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">WebSocket 客户端</span> - 支持 ws:// 与 wss://<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">REST API 框架</span> - 支持 GET、POST、PUT、PATCH、DELETE、HEAD、OPTIONS<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">强大的请求访问器</span> - URL 查询参数与 Header 解析<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">纯节点 JSON API</span> - JSON 构建与解析<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">鉴权系统</span> - Bearer Token 路由认证<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">HTTPS/TLS 支持</span> - OpenSSL 支持<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">结构化错误回调</span> - 提供详细错误信息<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">CRC32 完整性校验</span> - 文件校验验证<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">安装方法</span></span><br />
<br />
<ol type="1" class="mycode_list"><li>下载适用于你平台的最新版本（Windows 为 .dll，Linux 为 .so）<br />
</li>
<li>放入 open.mp 服务器的 components 目录<br />
</li>
<li>将 PawnREST.inc 放入 Pawn 编译器 include 目录<br />
</li>
<li>在脚本中添加：<br />
</li>
</ol>
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;PawnREST&gt;</code></div></div><br />
公共 API 使用以下前缀：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>REST_*  // HTTP 与 REST 功能<br />
FILE_*  // 文件上传下载功能</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">快速开始</span></span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
#include &lt;PawnREST&gt;<br />
new g_MapRoute = -1;<br />
new g_ApiPlayers = -1;<br />
public OnGameModeInit()<br />
{<br />
    REST_Start(8080);<br />
    g_MapRoute = FILE_RegisterRoute(<br />
        "/maps",<br />
        "scriptfiles/maps/",<br />
        ".map,.json",<br />
        50<br />
    );<br />
    FILE_AddAuthKey(g_MapRoute, "upload-secret-key");<br />
    FILE_AllowList(g_MapRoute, true);<br />
    FILE_AllowDownload(g_MapRoute, true);<br />
    g_ApiPlayers = REST_RegisterAPIRoute(<br />
        HTTP_METHOD_GET,<br />
        "/api/players",<br />
        "OnGetPlayers"<br />
    );<br />
    REST_SetRouteAuthKey(g_ApiPlayers, "api-secret-key");<br />
    return 1;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">HTTP 方法常量</span></span><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">常量</span></td>
<td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">对应方法</span></td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_GET</td>
<td style="border:1px solid #ddd;padding:6px 10px;">GET</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_POST</td>
<td style="border:1px solid #ddd;padding:6px 10px;">POST</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_PUT</td>
<td style="border:1px solid #ddd;padding:6px 10px;">PUT</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_PATCH</td>
<td style="border:1px solid #ddd;padding:6px 10px;">PATCH</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_DELETE</td>
<td style="border:1px solid #ddd;padding:6px 10px;">DELETE</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_HEAD</td>
<td style="border:1px solid #ddd;padding:6px 10px;">HEAD</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">HTTP_METHOD_OPTIONS</td>
<td style="border:1px solid #ddd;padding:6px 10px;">OPTIONS</td>
</tr>
</table>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">文件上传路由</span></span><br />
<br />
支持：<br />
<ul class="mycode_list"><li>上传文件<br />
</li>
<li>文件列表<br />
</li>
<li>文件下载<br />
</li>
<li>文件删除<br />
</li>
<li>文件信息查询<br />
</li>
<li>CRC32 校验<br />
</li>
<li>上传鉴权<br />
</li>
<li>冲突处理策略<br />
</li>
</ul>
<br />
主要函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>FILE_RegisterRoute(...)<br />
FILE_AddAuthKey(...)<br />
FILE_AllowList(...)<br />
FILE_AllowDownload(...)<br />
FILE_AllowDelete(...)<br />
FILE_AllowInfo(...)<br />
FILE_Delete(...)<br />
FILE_GetCount(...)<br />
FILE_GetSize(...)</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">REST API 路由</span></span><br />
<br />
注册自定义接口：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>REST_RegisterAPIRoute(<br />
    HTTP_METHOD_GET,<br />
    "/api/server",<br />
    "OnGetServer"<br />
);</code></div></div><br />
支持：<br />
<ul class="mycode_list"><li>GET<br />
</li>
<li>POST<br />
</li>
<li>PUT<br />
</li>
<li>PATCH<br />
</li>
<li>DELETE<br />
</li>
<li>HEAD<br />
</li>
<li>OPTIONS<br />
</li>
</ul>
<br />
支持 URL 参数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/api/player/{id}</code></div></div><br />
示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/api/player/5</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">请求数据读取</span></span><br />
<br />
支持：<br />
<ul class="mycode_list"><li>客户端 IP<br />
</li>
<li>HTTP 方法<br />
</li>
<li>请求路径<br />
</li>
<li>请求体 Body<br />
</li>
<li>URL 参数<br />
</li>
<li>Query 参数<br />
</li>
<li>HTTP Header<br />
</li>
</ul>
<br />
例如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>REST_GetParamInt(requestId, "id");<br />
REST_GetQueryInt(requestId, "page");<br />
REST_GetHeader(requestId, "Authorization");</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">JSON API</span></span><br />
<br />
特点：<br />
<ul class="mycode_list"><li>纯 Node 节点系统<br />
</li>
<li>JSON 解析<br />
</li>
<li>JSON 构建<br />
</li>
<li>对象与数组操作<br />
</li>
<li>序列化输出<br />
</li>
</ul>
<br />
创建对象：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new payload = JsonObject(<br />
    "name", JsonString("PawnREST"),<br />
    "version", JsonString("1.0")<br />
);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">响应函数</span></span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>Respond(...)<br />
RespondJSON(...)<br />
RespondNode(...)<br />
RespondError(...)<br />
SetResponseHeader(...)</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">☁️ 外部 HTTP 请求</span></span><br />
<br />
支持：<br />
<ul class="mycode_list"><li>HTTP 请求<br />
</li>
<li>JSON 请求<br />
</li>
<li>请求取消<br />
</li>
<li>请求状态查询<br />
</li>
<li>错误信息获取<br />
</li>
</ul>
<br />
主要函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>REST_CreateRequestClient(...)<br />
REST_Request(...)<br />
REST_RequestJSON(...)</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">WebSocket 客户端</span></span><br />
<br />
支持：<br />
<ul class="mycode_list"><li>文本 WebSocket<br />
</li>
<li>JSON WebSocket<br />
</li>
<li>TLS/WSS<br />
</li>
<li>发送消息<br />
</li>
<li>关闭连接<br />
</li>
</ul>
<br />
主要函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>REST_WebSocketClient(...)<br />
REST_JsonWebSocketClient(...)<br />
REST_WebSocketSend(...)<br />
REST_JsonWebSocketSend(...)</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CRC32 工具</span></span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>FILE_VerifyCRC32(...)<br />
FILE_GetCRC32(...)<br />
FILE_Compare(...)</code></div></div><br />
用于：<br />
<ul class="mycode_list"><li>文件完整性验证<br />
</li>
<li>上传校验<br />
</li>
<li>文件比较<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">回调列表</span></span><br />
<br />
上传相关：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>OnIncomingUploadCompleted<br />
OnIncomingUploadFailed<br />
OnIncomingUploadProgress<br />
OnOutgoingUploadStarted<br />
OnOutgoingUploadProgress<br />
OnOutgoingUploadCompleted<br />
OnOutgoingUploadFailed</code></div></div><br />
请求相关：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>OnRequestFailure<br />
OnWebSocketDisconnect</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">内置接口</span></span><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">接口</span></td>
<td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">说明</span></td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">GET /health</td>
<td style="border:1px solid #ddd;padding:6px 10px;">健康检查</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">GET /stats</td>
<td style="border:1px solid #ddd;padding:6px 10px;">服务器统计</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">GET {route}/files</td>
<td style="border:1px solid #ddd;padding:6px 10px;">获取文件列表</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">GET {route}/files/{name}</td>
<td style="border:1px solid #ddd;padding:6px 10px;">下载文件</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">GET {route}/files/{name}/info</td>
<td style="border:1px solid #ddd;padding:6px 10px;">获取文件信息</td>
</tr>
<tr>
<td style="border:1px solid #ddd;padding:6px 10px;">DELETE {route}/files/{name}</td>
<td style="border:1px solid #ddd;padding:6px 10px;">删除文件</td>
</tr>
</table>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">鸣谢</span></span><br />
<ul class="mycode_list"><li>yhirose - HTTP 库<br />
</li>
<li>Southclaws - pawn-requests API 参考<br />
</li>
<li>Fanorisky - 项目实现<br />
</li>
<li>SA-MP Team<br />
</li>
<li>open.mp Contributors<br />
</li>
</ul>
]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[网页版 TextDraws在线编辑]]></title>
			<link>https://open-mp.cn/showthread.php?tid=35</link>
			<pubDate>Thu, 11 Jun 2026 21:39:25 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=1">siwode</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=35</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b"><span style="font-size: xx-large;" class="mycode_size">网站地址 ：<br />
<a href="https://san-andreas-online.github.io/web-textdraw-editor/" target="_blank" rel="noopener" class="mycode_url">Web Textdraw Editor (san-andreas-online.github.io)</a><br />
</span></span><br />
<br />
<img src="https://raw.githubusercontent.com/San-Andreas-Online/web-textdraw-editor/main/_docs/canvas.gif" loading="lazy"  alt="[图片: canvas.gif]" class="mycode_img" />]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b"><span style="font-size: xx-large;" class="mycode_size">网站地址 ：<br />
<a href="https://san-andreas-online.github.io/web-textdraw-editor/" target="_blank" rel="noopener" class="mycode_url">Web Textdraw Editor (san-andreas-online.github.io)</a><br />
</span></span><br />
<br />
<img src="https://raw.githubusercontent.com/San-Andreas-Online/web-textdraw-editor/main/_docs/canvas.gif" loading="lazy"  alt="[图片: canvas.gif]" class="mycode_img" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[西部角色扮演 Wild-West-Roleplay]]></title>
			<link>https://open-mp.cn/showthread.php?tid=34</link>
			<pubDate>Thu, 11 Jun 2026 21:19:42 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=1">siwode</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=34</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b"><span style="font-size: xx-large;" class="mycode_size">Wild West Roleplay（荒野西部角色扮演）<br />
</span></span><br />
<span style="color: #c10300;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size">点击前往 </span></span><a href="https://github.com/DignitySAMP/Wild-West-Roleplay" target="_blank" rel="noopener" class="mycode_url"><span style="font-weight: bold;" class="mycode_b"><span style="color: #c10300;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size">下载地址</span></span></span></a> <br />
<img src="https://raw.githubusercontent.com/DignitySAMP/Wild-West-Roleplay/main/server_map.png" loading="lazy"  alt="[图片: server_map.png]" class="mycode_img" /><br />
这是我在 2016 至 2018 年期间最具代表性的作品，也是让我在 SA-MP 圈内打响名号的游戏模式。它是一款拥有大量 RPG 元素的角色扮演服务器，在 2016 年将 SA-MP 提升到了全新的层次：整个地图被重新制作、拥有自定义马匹载具系统，以及大量当时前所未见的 RPG 玩法（其中许多都是我们首创）。<br />
服务器最初于 2016 年开放，最高在线人数达到 90 人。运营约四至五个月后，由于我们在管理方面经验不足，最终导致服务器关闭。后来在开发 Medieval Roleplay（中世纪 RP）期间，我们于 2018 年重新开放了该服务器，并加入大量更新内容，以展示 SA-MP 0.3DL 的强大能力（全动画马匹、自定义城镇、自定义附件模型等）。<br />
<blockquote class="mycode_quote"><cite>引用:</cite>该脚本已经非常过时。之所以开源，仅作为历史档案保存，因为它一直躺在我的硬盘里积灰。<span style="font-weight: bold;" class="mycode_b">不建议直接投入使用，仅供参考与怀旧。</span></blockquote>
开发者名单：<ul class="mycode_list"><li>DignitySAMP（项目负责人）<br />
</li>
<li>DTVSamp（主要开发者）<br />
</li>
<li>Rusu（主要开发者）<br />
</li>
</ul>
我认为能成功运行它的人不会太多（至少很难达到可游玩的状态），如果你对当年服务器的实际效果感兴趣，可以观看演示视频：<br />
<a href="https://www.youtube.com/watch?v=Me0RweOwJLk" target="_blank" rel="noopener" class="mycode_url">https://www.youtube.com/watch?v=Me0RweOwJLk</a><br />
不会提供任何运行支持，因为它本来就不是为了重新上线而发布的。我希望通过公开这个脚本，大家能够学习其中的一些技术实现、创新方案，以及从我们的失误中吸取经验。<br />
<hr class="mycode_hr" />
功能列表<br />
<blockquote class="mycode_quote"><cite>引用:</cite>请注意，我可能遗漏了一些功能。该服务器最后一次运行是在 2018 年，我只是快速浏览文件并根据记忆进行整理。</blockquote>
<hr class="mycode_hr" />
账号系统<ul class="mycode_list"><li>基础随机 RP 问答测试（每次题目不同）<br />
</li>
<li>基础新手教程（目前未启用，但理论上仍可运行）<br />
</li>
<li>基础新玩家任务系统（替代旧教程）<br />
</li>
<li>基础经验与等级系统<br />
</li>
<li>注册时使用交互式 TextDraw 选择：<ul class="mycode_list"><li>性别<br />
</li>
<li>种族<br />
</li>
<li>城镇<br />
</li>
<li>皮肤<br />
</li>
<li>年龄<br />
</li>
</ul>
</li>
<li>智能出生系统：<ul class="mycode_list"><li>监狱<br />
</li>
<li>牢房<br />
</li>
<li>崩溃位置恢复<br />
</li>
<li>房屋<br />
</li>
<li>商业点<br />
</li>
<li>城镇等<br />
</li>
</ul>
</li>
<li>主账号系统（支持多个角色）<br />
</li>
<li>角色/账号改名系统<br />
</li>
<li><div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/relog</code></div></div>、<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/logout</code></div></div></li>
</ul>
<hr class="mycode_hr" />
马匹系统<ul class="mycode_list"><li>Medieval Roleplay 中著名的马匹系统<br />
</li>
<li>多种马匹模型<br />
</li>
<li>所有马匹均由服务器端动画驱动<br />
</li>
<li>完全替代传统车辆系统<br />
</li>
<li>停放状态的马匹可受伤<br />
</li>
<li>自定义马匹音效（文件已遗失）<br />
</li>
<li>马匹速度与生命值 HUD<br />
</li>
</ul>
<hr class="mycode_hr" />
狩猎系统<ul class="mycode_list"><li>鹿会动态在地图中游荡<br />
</li>
<li>基础 AI：<ul class="mycode_list"><li>避开障碍<br />
</li>
<li>动态转向<br />
</li>
<li>不发生碰撞<br />
</li>
</ul>
</li>
<li>鹿为自定义动画模型<br />
</li>
<li>不同武器造成不同伤害<br />
</li>
<li>击杀后可剥皮<br />
</li>
<li>获取肉类与皮革出售<br />
</li>
<li>剥皮后尸体会变成血腥状态并逐渐消失（参考 RDR2）<br />
</li>
<li>需要狩猎刀进行剥皮<br />
</li>
<li>属于后期职业玩法<br />
</li>
</ul>
<hr class="mycode_hr" />
生存需求系统<ul class="mycode_list"><li>饥饿值<br />
</li>
<li>口渴值<br />
</li>
<li>温度系统<ul class="mycode_list"><li>北部区域会变冷<br />
</li>
<li>篝火取暖<br />
</li>
<li>保暖服装<br />
</li>
</ul>
</li>
<li>自定义 HUD 界面显示状态<br />
</li>
</ul>
<hr class="mycode_hr" />
自定义地图<ul class="mycode_list"><li>登录/注册界面自定义地图<br />
</li>
<li>自定义出生区域<br />
</li>
<li>Las Barrancas 与 El Quebrados 全面重制<br />
</li>
<li>Bayside 雪地区域<ul class="mycode_list"><li>需要保暖装备<br />
</li>
<li>后期区域<br />
</li>
</ul>
</li>
<li>全地图程序化植被系统<br />
</li>
<li>自定义监狱地图<br />
</li>
<li>大量符合西部风格的室内地图<br />
</li>
<li>包含 Medieval RP 遗留模型<br />
</li>
<li>全地图道路改为泥土路<br />
</li>
<li>使用 GangZone 遮挡未使用地图区域<br />
</li>
<li>自定义区域提示系统<br />
</li>
</ul>
<hr class="mycode_hr" />
背包系统<ul class="mycode_list"><li>全 TextDraw 界面<br />
</li>
<li>烹饪系统<br />
</li>
<li>背包容量升级<br />
</li>
<li>类似魔兽世界的物品品质系统<br />
</li>
<li><div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/showitems</code></div></div></li>
<li>丢弃与拾取物品<br />
</li>
<li>大量预设物品<br />
</li>
<li>物品销毁<br />
</li>
<li>物品使用系统<br />
</li>
<li>完整物品增减接口<br />
</li>
</ul>
<hr class="mycode_hr" />
RPG 技能系统<br />
可升级多种技能：<br />
战斗技能<ul class="mycode_list"><li>武器熟练度<br />
</li>
<li>瞄准技巧<br />
</li>
<li>拔枪速度<br />
</li>
</ul>
职业技能<ul class="mycode_list"><li>钓鱼<br />
</li>
<li>伐木<br />
</li>
<li>采矿<br />
</li>
<li>狩猎<br />
</li>
<li>农业<br />
</li>
<li>铁匠<br />
</li>
</ul>
生存技能<ul class="mycode_list"><li>游泳<br />
</li>
<li>徒手格斗<br />
</li>
<li>生命值<br />
</li>
<li>刀具使用<br />
</li>
<li>飞刀投掷<br />
</li>
</ul>
<hr class="mycode_hr" />
武器系统<ul class="mycode_list"><li>所有武器均为自定义系统<br />
</li>
<li>显示当前武器及弹仓子弹<br />
</li>
<li>服务端追踪子弹<br />
</li>
<li>拥有真实换弹机制<br />
</li>
<li>弹壳掉落系统<br />
</li>
<li>警长可调查弹壳<br />
</li>
<li>枪套系统<br />
</li>
<li>玩家身上可见武器<br />
</li>
<li>铁匠打造武器<br />
</li>
<li>武器交易<br />
</li>
<li>武器掉落拾取<br />
</li>
<li>切换已装备与挂载武器<br />
</li>
<li>武器挂载位置编辑<br />
</li>
<li>新手需要训练才能熟练使用武器<br />
</li>
</ul>
<hr class="mycode_hr" />
金钱系统<ul class="mycode_list"><li>支持零钱<ul class="mycode_list"><li>例如 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>&#36;12.75</code></div></div></li>
</ul>
</li>
<li>经济体系参考《荒野大镖客2》<br />
</li>
<li>拥有 100 美元已属于富裕阶层<br />
</li>
</ul>
<hr class="mycode_hr" />
伤害系统<ul class="mycode_list"><li>流血系统<br />
</li>
<li>血迹拖尾<br />
</li>
<li>绷带止血<br />
</li>
<li>屏幕血迹效果<br />
</li>
<li>服务端爆炸与火焰伤害<br />
</li>
<li>骨折系统<br />
</li>
<li>死亡尸体系统<ul class="mycode_list"><li>搬运<br />
</li>
<li>埋葬<br />
</li>
<li>焚烧<br />
</li>
</ul>
</li>
<li>受伤时自动跌落马匹<br />
</li>
<li><div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/showinjuries</code></div></div></li>
<li><div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/showwounds</code></div></div></li>
</ul>
<hr class="mycode_hr" />
工作系统<br />
职业包括：<ul class="mycode_list"><li>钓鱼<br />
</li>
<li>伐木<br />
</li>
<li>采矿<br />
</li>
</ul>
特色：<ul class="mycode_list"><li>进度条小游戏<br />
</li>
<li>技能等级影响效率<br />
</li>
<li>更高级资源需要更高技能<br />
</li>
<li>资源与其他系统联动<br />
</li>
<li>统一 Action Panel 操作界面<br />
</li>
</ul>
<hr class="mycode_hr" />
小游戏<br />
扑克<ul class="mycode_list"><li>基于 LorenC 的 SF-CNR 修改<br />
</li>
</ul>
二十一点（Blackjack）<ul class="mycode_list"><li>支持多人对庄家<br />
</li>
</ul>
<hr class="mycode_hr" />
胡须系统<br />
受 RDR2 启发：<ul class="mycode_list"><li>胡须随时间自然生长<br />
</li>
<li>接近完成状态<br />
</li>
<li>从未正式投入生产环境<br />
</li>
</ul>
<hr class="mycode_hr" />
套索系统<br />
执法人员专属：<ul class="mycode_list"><li>投掷套索<br />
</li>
<li>将目标拉下马<br />
</li>
<li>捆绑玩家<br />
</li>
</ul>
<hr class="mycode_hr" />
陷阱系统<ul class="mycode_list"><li>布置陷阱<br />
</li>
<li>捕捉玩家与动物<br />
</li>
<li>造成流血<br />
</li>
<li>武装/拆除/检查机制<br />
</li>
</ul>
<hr class="mycode_hr" />
捐赠系统<br />
开发中：<ul class="mycode_list"><li>多级赞助等级<br />
</li>
<li>专属聊天频道<br />
</li>
<li>更高工资<br />
</li>
<li>专属马匹<br />
</li>
<li>自动到期移除<br />
</li>
</ul>
<hr class="mycode_hr" />
动态 NPC 系统<ul class="mycode_list"><li>预设商店 NPC 类型<br />
</li>
<li>管理员自由创建编辑<br />
</li>
<li>支持动作动画<br />
</li>
<li>H 键交互框架<br />
</li>
</ul>
<hr class="mycode_hr" />
农业系统（开发中）<ul class="mycode_list"><li>耕地<br />
</li>
<li>播种<br />
</li>
<li>多种作物<br />
</li>
<li>土壤状态<br />
</li>
<li>水分状态<br />
</li>
<li>健康状态<br />
</li>
</ul>
<hr class="mycode_hr" />
动态商业系统<br />
商店类型：<ul class="mycode_list"><li>杂货店<br />
</li>
<li>武器店<br />
</li>
<li>服装店<br />
</li>
<li>理发店<br />
</li>
<li>酒馆<br />
</li>
<li>狩猎商店<br />
</li>
<li>银行<br />
</li>
<li>邮局<br />
</li>
<li>警局<br />
</li>
<li>铁匠铺<br />
</li>
<li>马厩<br />
</li>
</ul>
功能：<ul class="mycode_list"><li>房间租赁<br />
</li>
<li>武器储存<br />
</li>
<li>收银系统<br />
</li>
<li>新手旅馆<br />
</li>
<li>家具系统<br />
</li>
<li>广告系统<br />
</li>
<li>电报系统<br />
</li>
</ul>
<hr class="mycode_hr" />
动态帮派（Posse）系统<ul class="mycode_list"><li>武器柜<br />
</li>
<li>警长指控系统<br />
</li>
<li>监狱系统<br />
</li>
<li>无线电通讯<br />
</li>
<li>擒拿系统<br />
</li>
<li>不同阵营聊天颜色<br />
</li>
<li>查看所有帮派在线成员<br />
</li>
</ul>
<hr class="mycode_hr" />
通缉令系统<ul class="mycode_list"><li>通缉海报 TextDraw<br />
</li>
<li>警察可在任意地点张贴通缉令<br />
</li>
</ul>
<hr class="mycode_hr" />
管理员系统<br />
Management（管理层）<ul class="mycode_list"><li>动态创建内容<br />
</li>
<li>分配职位<br />
</li>
</ul>
Admin（管理员）<ul class="mycode_list"><li>处罚系统<br />
</li>
<li>反 Ban Evade<br />
</li>
</ul>
Helper（助手）<ul class="mycode_list"><li>回答问题<br />
</li>
<li>开发组<br />
</li>
<li>活动组<br />
</li>
<li>帮派管理<br />
</li>
<li>地图组<br />
</li>
</ul>
其它功能：<ul class="mycode_list"><li>管理记录<br />
</li>
<li>管理备注<br />
</li>
<li>Skyrim 风格传送命令<br />
</li>
<li>Staff Island<br />
</li>
<li>大量管理工具<br />
</li>
</ul>
<hr class="mycode_hr" />
更新记录系统<ul class="mycode_list"><li><div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/updates</code></div></div></li>
<li>登录自动提示更新内容<br />
</li>
</ul>
<hr class="mycode_hr" />
动画系统<ul class="mycode_list"><li>大量 RP 动作<br />
</li>
<li>动画预加载<br />
</li>
</ul>
<hr class="mycode_hr" />
反作弊系统（极其过时）<br />
检测：<ul class="mycode_list"><li>金钱作弊<br />
</li>
<li>生命作弊<br />
</li>
<li>武器作弊<br />
</li>
<li>弹药作弊<br />
</li>
<li>飞天<br />
</li>
<li>C-Bug<br />
</li>
<li>非法武器<br />
</li>
<li>Ban Evade<br />
</li>
<li>传送外挂<br />
</li>
<li>加速外挂<br />
</li>
</ul>
<hr class="mycode_hr" />
附件系统<ul class="mycode_list"><li>购买附件<br />
</li>
<li>调整位置<br />
</li>
<li>调整骨骼<br />
</li>
<li>部分附件提供保暖效果<br />
</li>
</ul>
<hr class="mycode_hr" />
篝火系统<ul class="mycode_list"><li>提高体温<br />
</li>
<li>添加燃料<br />
</li>
<li>增加持续时间与热量<br />
</li>
</ul>
<hr class="mycode_hr" />
动态标签系统<ul class="mycode_list"><li>管理员创建 3D Text Label<br />
</li>
<li>玩家申请场景标签<br />
</li>
<li>管理员审核<br />
</li>
</ul>
<hr class="mycode_hr" />
彩票系统<ul class="mycode_list"><li>购买彩票增加奖池<br />
</li>
<li>使用 Pawn <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>random()</code></div></div></li>
<li>多人中奖自动平分<br />
</li>
</ul>
<hr class="mycode_hr" />
其它杂项系统<ul class="mycode_list"><li>命令防刷屏<br />
</li>
<li>属性系统 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/attribute</code></div></div></li>
<li>蒙眼与淡入淡出<br />
</li>
<li>面具系统<br />
</li>
<li>MOTD 系统<br />
</li>
<li>暂停检测<br />
</li>
<li>握手系统 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/shakehand</code></div></div></li>
<li>自定义时间系统<ul class="mycode_list"><li>1 游戏日 = 288 分钟现实时间<br />
</li>
</ul>
</li>
<li>搜身系统<br />
</li>
<li>抛硬币 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/coin</code></div></div></li>
<li>骰子 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/rolldice</code></div></div></li>
<li>自定义名牌<br />
</li>
<li>RP 聊天动作<br />
</li>
<li>口音系统<br />
</li>
<li>炸药系统<br />
</li>
<li>会话追踪<br />
</li>
<li>快速旅行系统<br />
</li>
</ul>
<hr class="mycode_hr" />
动态大门系统<ul class="mycode_list"><li>可绑定玩家<br />
</li>
<li>可绑定帮派<br />
</li>
<li>公共权限<br />
</li>
<li>管理员动态创建<br />
</li>
<li>基于 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/gate</code></div></div></li>
<li>使用动态物体实现<br />
</li>
</ul>
<hr class="mycode_hr" />
这是一个非常超前的西部 RP Gamemode，在 2016 年的 SA-MP 环境下已经接近独立 RPG 游戏的规模，融合了《荒野大镖客》《魔兽世界》和传统 RP 服务器的设计理念。许多系统即使放到今天的 open.mp 环境中依然具有很高的参考价值。]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b"><span style="font-size: xx-large;" class="mycode_size">Wild West Roleplay（荒野西部角色扮演）<br />
</span></span><br />
<span style="color: #c10300;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size">点击前往 </span></span><a href="https://github.com/DignitySAMP/Wild-West-Roleplay" target="_blank" rel="noopener" class="mycode_url"><span style="font-weight: bold;" class="mycode_b"><span style="color: #c10300;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size">下载地址</span></span></span></a> <br />
<img src="https://raw.githubusercontent.com/DignitySAMP/Wild-West-Roleplay/main/server_map.png" loading="lazy"  alt="[图片: server_map.png]" class="mycode_img" /><br />
这是我在 2016 至 2018 年期间最具代表性的作品，也是让我在 SA-MP 圈内打响名号的游戏模式。它是一款拥有大量 RPG 元素的角色扮演服务器，在 2016 年将 SA-MP 提升到了全新的层次：整个地图被重新制作、拥有自定义马匹载具系统，以及大量当时前所未见的 RPG 玩法（其中许多都是我们首创）。<br />
服务器最初于 2016 年开放，最高在线人数达到 90 人。运营约四至五个月后，由于我们在管理方面经验不足，最终导致服务器关闭。后来在开发 Medieval Roleplay（中世纪 RP）期间，我们于 2018 年重新开放了该服务器，并加入大量更新内容，以展示 SA-MP 0.3DL 的强大能力（全动画马匹、自定义城镇、自定义附件模型等）。<br />
<blockquote class="mycode_quote"><cite>引用:</cite>该脚本已经非常过时。之所以开源，仅作为历史档案保存，因为它一直躺在我的硬盘里积灰。<span style="font-weight: bold;" class="mycode_b">不建议直接投入使用，仅供参考与怀旧。</span></blockquote>
开发者名单：<ul class="mycode_list"><li>DignitySAMP（项目负责人）<br />
</li>
<li>DTVSamp（主要开发者）<br />
</li>
<li>Rusu（主要开发者）<br />
</li>
</ul>
我认为能成功运行它的人不会太多（至少很难达到可游玩的状态），如果你对当年服务器的实际效果感兴趣，可以观看演示视频：<br />
<a href="https://www.youtube.com/watch?v=Me0RweOwJLk" target="_blank" rel="noopener" class="mycode_url">https://www.youtube.com/watch?v=Me0RweOwJLk</a><br />
不会提供任何运行支持，因为它本来就不是为了重新上线而发布的。我希望通过公开这个脚本，大家能够学习其中的一些技术实现、创新方案，以及从我们的失误中吸取经验。<br />
<hr class="mycode_hr" />
功能列表<br />
<blockquote class="mycode_quote"><cite>引用:</cite>请注意，我可能遗漏了一些功能。该服务器最后一次运行是在 2018 年，我只是快速浏览文件并根据记忆进行整理。</blockquote>
<hr class="mycode_hr" />
账号系统<ul class="mycode_list"><li>基础随机 RP 问答测试（每次题目不同）<br />
</li>
<li>基础新手教程（目前未启用，但理论上仍可运行）<br />
</li>
<li>基础新玩家任务系统（替代旧教程）<br />
</li>
<li>基础经验与等级系统<br />
</li>
<li>注册时使用交互式 TextDraw 选择：<ul class="mycode_list"><li>性别<br />
</li>
<li>种族<br />
</li>
<li>城镇<br />
</li>
<li>皮肤<br />
</li>
<li>年龄<br />
</li>
</ul>
</li>
<li>智能出生系统：<ul class="mycode_list"><li>监狱<br />
</li>
<li>牢房<br />
</li>
<li>崩溃位置恢复<br />
</li>
<li>房屋<br />
</li>
<li>商业点<br />
</li>
<li>城镇等<br />
</li>
</ul>
</li>
<li>主账号系统（支持多个角色）<br />
</li>
<li>角色/账号改名系统<br />
</li>
<li><div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/relog</code></div></div>、<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/logout</code></div></div></li>
</ul>
<hr class="mycode_hr" />
马匹系统<ul class="mycode_list"><li>Medieval Roleplay 中著名的马匹系统<br />
</li>
<li>多种马匹模型<br />
</li>
<li>所有马匹均由服务器端动画驱动<br />
</li>
<li>完全替代传统车辆系统<br />
</li>
<li>停放状态的马匹可受伤<br />
</li>
<li>自定义马匹音效（文件已遗失）<br />
</li>
<li>马匹速度与生命值 HUD<br />
</li>
</ul>
<hr class="mycode_hr" />
狩猎系统<ul class="mycode_list"><li>鹿会动态在地图中游荡<br />
</li>
<li>基础 AI：<ul class="mycode_list"><li>避开障碍<br />
</li>
<li>动态转向<br />
</li>
<li>不发生碰撞<br />
</li>
</ul>
</li>
<li>鹿为自定义动画模型<br />
</li>
<li>不同武器造成不同伤害<br />
</li>
<li>击杀后可剥皮<br />
</li>
<li>获取肉类与皮革出售<br />
</li>
<li>剥皮后尸体会变成血腥状态并逐渐消失（参考 RDR2）<br />
</li>
<li>需要狩猎刀进行剥皮<br />
</li>
<li>属于后期职业玩法<br />
</li>
</ul>
<hr class="mycode_hr" />
生存需求系统<ul class="mycode_list"><li>饥饿值<br />
</li>
<li>口渴值<br />
</li>
<li>温度系统<ul class="mycode_list"><li>北部区域会变冷<br />
</li>
<li>篝火取暖<br />
</li>
<li>保暖服装<br />
</li>
</ul>
</li>
<li>自定义 HUD 界面显示状态<br />
</li>
</ul>
<hr class="mycode_hr" />
自定义地图<ul class="mycode_list"><li>登录/注册界面自定义地图<br />
</li>
<li>自定义出生区域<br />
</li>
<li>Las Barrancas 与 El Quebrados 全面重制<br />
</li>
<li>Bayside 雪地区域<ul class="mycode_list"><li>需要保暖装备<br />
</li>
<li>后期区域<br />
</li>
</ul>
</li>
<li>全地图程序化植被系统<br />
</li>
<li>自定义监狱地图<br />
</li>
<li>大量符合西部风格的室内地图<br />
</li>
<li>包含 Medieval RP 遗留模型<br />
</li>
<li>全地图道路改为泥土路<br />
</li>
<li>使用 GangZone 遮挡未使用地图区域<br />
</li>
<li>自定义区域提示系统<br />
</li>
</ul>
<hr class="mycode_hr" />
背包系统<ul class="mycode_list"><li>全 TextDraw 界面<br />
</li>
<li>烹饪系统<br />
</li>
<li>背包容量升级<br />
</li>
<li>类似魔兽世界的物品品质系统<br />
</li>
<li><div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/showitems</code></div></div></li>
<li>丢弃与拾取物品<br />
</li>
<li>大量预设物品<br />
</li>
<li>物品销毁<br />
</li>
<li>物品使用系统<br />
</li>
<li>完整物品增减接口<br />
</li>
</ul>
<hr class="mycode_hr" />
RPG 技能系统<br />
可升级多种技能：<br />
战斗技能<ul class="mycode_list"><li>武器熟练度<br />
</li>
<li>瞄准技巧<br />
</li>
<li>拔枪速度<br />
</li>
</ul>
职业技能<ul class="mycode_list"><li>钓鱼<br />
</li>
<li>伐木<br />
</li>
<li>采矿<br />
</li>
<li>狩猎<br />
</li>
<li>农业<br />
</li>
<li>铁匠<br />
</li>
</ul>
生存技能<ul class="mycode_list"><li>游泳<br />
</li>
<li>徒手格斗<br />
</li>
<li>生命值<br />
</li>
<li>刀具使用<br />
</li>
<li>飞刀投掷<br />
</li>
</ul>
<hr class="mycode_hr" />
武器系统<ul class="mycode_list"><li>所有武器均为自定义系统<br />
</li>
<li>显示当前武器及弹仓子弹<br />
</li>
<li>服务端追踪子弹<br />
</li>
<li>拥有真实换弹机制<br />
</li>
<li>弹壳掉落系统<br />
</li>
<li>警长可调查弹壳<br />
</li>
<li>枪套系统<br />
</li>
<li>玩家身上可见武器<br />
</li>
<li>铁匠打造武器<br />
</li>
<li>武器交易<br />
</li>
<li>武器掉落拾取<br />
</li>
<li>切换已装备与挂载武器<br />
</li>
<li>武器挂载位置编辑<br />
</li>
<li>新手需要训练才能熟练使用武器<br />
</li>
</ul>
<hr class="mycode_hr" />
金钱系统<ul class="mycode_list"><li>支持零钱<ul class="mycode_list"><li>例如 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>&#36;12.75</code></div></div></li>
</ul>
</li>
<li>经济体系参考《荒野大镖客2》<br />
</li>
<li>拥有 100 美元已属于富裕阶层<br />
</li>
</ul>
<hr class="mycode_hr" />
伤害系统<ul class="mycode_list"><li>流血系统<br />
</li>
<li>血迹拖尾<br />
</li>
<li>绷带止血<br />
</li>
<li>屏幕血迹效果<br />
</li>
<li>服务端爆炸与火焰伤害<br />
</li>
<li>骨折系统<br />
</li>
<li>死亡尸体系统<ul class="mycode_list"><li>搬运<br />
</li>
<li>埋葬<br />
</li>
<li>焚烧<br />
</li>
</ul>
</li>
<li>受伤时自动跌落马匹<br />
</li>
<li><div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/showinjuries</code></div></div></li>
<li><div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/showwounds</code></div></div></li>
</ul>
<hr class="mycode_hr" />
工作系统<br />
职业包括：<ul class="mycode_list"><li>钓鱼<br />
</li>
<li>伐木<br />
</li>
<li>采矿<br />
</li>
</ul>
特色：<ul class="mycode_list"><li>进度条小游戏<br />
</li>
<li>技能等级影响效率<br />
</li>
<li>更高级资源需要更高技能<br />
</li>
<li>资源与其他系统联动<br />
</li>
<li>统一 Action Panel 操作界面<br />
</li>
</ul>
<hr class="mycode_hr" />
小游戏<br />
扑克<ul class="mycode_list"><li>基于 LorenC 的 SF-CNR 修改<br />
</li>
</ul>
二十一点（Blackjack）<ul class="mycode_list"><li>支持多人对庄家<br />
</li>
</ul>
<hr class="mycode_hr" />
胡须系统<br />
受 RDR2 启发：<ul class="mycode_list"><li>胡须随时间自然生长<br />
</li>
<li>接近完成状态<br />
</li>
<li>从未正式投入生产环境<br />
</li>
</ul>
<hr class="mycode_hr" />
套索系统<br />
执法人员专属：<ul class="mycode_list"><li>投掷套索<br />
</li>
<li>将目标拉下马<br />
</li>
<li>捆绑玩家<br />
</li>
</ul>
<hr class="mycode_hr" />
陷阱系统<ul class="mycode_list"><li>布置陷阱<br />
</li>
<li>捕捉玩家与动物<br />
</li>
<li>造成流血<br />
</li>
<li>武装/拆除/检查机制<br />
</li>
</ul>
<hr class="mycode_hr" />
捐赠系统<br />
开发中：<ul class="mycode_list"><li>多级赞助等级<br />
</li>
<li>专属聊天频道<br />
</li>
<li>更高工资<br />
</li>
<li>专属马匹<br />
</li>
<li>自动到期移除<br />
</li>
</ul>
<hr class="mycode_hr" />
动态 NPC 系统<ul class="mycode_list"><li>预设商店 NPC 类型<br />
</li>
<li>管理员自由创建编辑<br />
</li>
<li>支持动作动画<br />
</li>
<li>H 键交互框架<br />
</li>
</ul>
<hr class="mycode_hr" />
农业系统（开发中）<ul class="mycode_list"><li>耕地<br />
</li>
<li>播种<br />
</li>
<li>多种作物<br />
</li>
<li>土壤状态<br />
</li>
<li>水分状态<br />
</li>
<li>健康状态<br />
</li>
</ul>
<hr class="mycode_hr" />
动态商业系统<br />
商店类型：<ul class="mycode_list"><li>杂货店<br />
</li>
<li>武器店<br />
</li>
<li>服装店<br />
</li>
<li>理发店<br />
</li>
<li>酒馆<br />
</li>
<li>狩猎商店<br />
</li>
<li>银行<br />
</li>
<li>邮局<br />
</li>
<li>警局<br />
</li>
<li>铁匠铺<br />
</li>
<li>马厩<br />
</li>
</ul>
功能：<ul class="mycode_list"><li>房间租赁<br />
</li>
<li>武器储存<br />
</li>
<li>收银系统<br />
</li>
<li>新手旅馆<br />
</li>
<li>家具系统<br />
</li>
<li>广告系统<br />
</li>
<li>电报系统<br />
</li>
</ul>
<hr class="mycode_hr" />
动态帮派（Posse）系统<ul class="mycode_list"><li>武器柜<br />
</li>
<li>警长指控系统<br />
</li>
<li>监狱系统<br />
</li>
<li>无线电通讯<br />
</li>
<li>擒拿系统<br />
</li>
<li>不同阵营聊天颜色<br />
</li>
<li>查看所有帮派在线成员<br />
</li>
</ul>
<hr class="mycode_hr" />
通缉令系统<ul class="mycode_list"><li>通缉海报 TextDraw<br />
</li>
<li>警察可在任意地点张贴通缉令<br />
</li>
</ul>
<hr class="mycode_hr" />
管理员系统<br />
Management（管理层）<ul class="mycode_list"><li>动态创建内容<br />
</li>
<li>分配职位<br />
</li>
</ul>
Admin（管理员）<ul class="mycode_list"><li>处罚系统<br />
</li>
<li>反 Ban Evade<br />
</li>
</ul>
Helper（助手）<ul class="mycode_list"><li>回答问题<br />
</li>
<li>开发组<br />
</li>
<li>活动组<br />
</li>
<li>帮派管理<br />
</li>
<li>地图组<br />
</li>
</ul>
其它功能：<ul class="mycode_list"><li>管理记录<br />
</li>
<li>管理备注<br />
</li>
<li>Skyrim 风格传送命令<br />
</li>
<li>Staff Island<br />
</li>
<li>大量管理工具<br />
</li>
</ul>
<hr class="mycode_hr" />
更新记录系统<ul class="mycode_list"><li><div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/updates</code></div></div></li>
<li>登录自动提示更新内容<br />
</li>
</ul>
<hr class="mycode_hr" />
动画系统<ul class="mycode_list"><li>大量 RP 动作<br />
</li>
<li>动画预加载<br />
</li>
</ul>
<hr class="mycode_hr" />
反作弊系统（极其过时）<br />
检测：<ul class="mycode_list"><li>金钱作弊<br />
</li>
<li>生命作弊<br />
</li>
<li>武器作弊<br />
</li>
<li>弹药作弊<br />
</li>
<li>飞天<br />
</li>
<li>C-Bug<br />
</li>
<li>非法武器<br />
</li>
<li>Ban Evade<br />
</li>
<li>传送外挂<br />
</li>
<li>加速外挂<br />
</li>
</ul>
<hr class="mycode_hr" />
附件系统<ul class="mycode_list"><li>购买附件<br />
</li>
<li>调整位置<br />
</li>
<li>调整骨骼<br />
</li>
<li>部分附件提供保暖效果<br />
</li>
</ul>
<hr class="mycode_hr" />
篝火系统<ul class="mycode_list"><li>提高体温<br />
</li>
<li>添加燃料<br />
</li>
<li>增加持续时间与热量<br />
</li>
</ul>
<hr class="mycode_hr" />
动态标签系统<ul class="mycode_list"><li>管理员创建 3D Text Label<br />
</li>
<li>玩家申请场景标签<br />
</li>
<li>管理员审核<br />
</li>
</ul>
<hr class="mycode_hr" />
彩票系统<ul class="mycode_list"><li>购买彩票增加奖池<br />
</li>
<li>使用 Pawn <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>random()</code></div></div></li>
<li>多人中奖自动平分<br />
</li>
</ul>
<hr class="mycode_hr" />
其它杂项系统<ul class="mycode_list"><li>命令防刷屏<br />
</li>
<li>属性系统 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/attribute</code></div></div></li>
<li>蒙眼与淡入淡出<br />
</li>
<li>面具系统<br />
</li>
<li>MOTD 系统<br />
</li>
<li>暂停检测<br />
</li>
<li>握手系统 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/shakehand</code></div></div></li>
<li>自定义时间系统<ul class="mycode_list"><li>1 游戏日 = 288 分钟现实时间<br />
</li>
</ul>
</li>
<li>搜身系统<br />
</li>
<li>抛硬币 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/coin</code></div></div></li>
<li>骰子 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/rolldice</code></div></div></li>
<li>自定义名牌<br />
</li>
<li>RP 聊天动作<br />
</li>
<li>口音系统<br />
</li>
<li>炸药系统<br />
</li>
<li>会话追踪<br />
</li>
<li>快速旅行系统<br />
</li>
</ul>
<hr class="mycode_hr" />
动态大门系统<ul class="mycode_list"><li>可绑定玩家<br />
</li>
<li>可绑定帮派<br />
</li>
<li>公共权限<br />
</li>
<li>管理员动态创建<br />
</li>
<li>基于 <br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/gate</code></div></div></li>
<li>使用动态物体实现<br />
</li>
</ul>
<hr class="mycode_hr" />
这是一个非常超前的西部 RP Gamemode，在 2016 年的 SA-MP 环境下已经接近独立 RPG 游戏的规模，融合了《荒野大镖客》《魔兽世界》和传统 RP 服务器的设计理念。许多系统即使放到今天的 open.mp 环境中依然具有很高的参考价值。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[插件] kook-connect]]></title>
			<link>https://open-mp.cn/showthread.php?tid=33</link>
			<pubDate>Fri, 01 May 2026 01:07:22 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=1">siwode</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=33</guid>
			<description><![CDATA[<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">samp-kook-connector 插件 Wiki</span></span><br />
<br />
将 Kook 机器人集成到你的 SA-MP / open.mp 服务器游戏模式中。<br />
<br />
下载地址：<a href="https://github.com/siwode1/samp-kook-connect" target="_blank" rel="noopener" class="mycode_url">siwode1/samp-kook-connect: SA:MP 插件用于控制 Kook bot (github.com)</a><br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">目录</span><br />
<br />
<ol type="1" class="mycode_list"><li><a href="http://#install" target="_blank" rel="noopener" class="mycode_url">安装</a><br />
</li>
<li><a href="http://#notes" target="_blank" rel="noopener" class="mycode_url">重要说明</a><br />
</li>
<li><a href="http://#natives" target="_blank" rel="noopener" class="mycode_url">Natives（原生函数）</a><ul class="mycode_list"><li><a href="http://#ch" target="_blank" rel="noopener" class="mycode_url">频道</a><br />
</li>
<li><a href="http://#msg" target="_blank" rel="noopener" class="mycode_url">消息</a><br />
</li>
<li><a href="http://#usr" target="_blank" rel="noopener" class="mycode_url">用户</a><br />
</li>
<li><a href="http://#role" target="_blank" rel="noopener" class="mycode_url">身份组</a><br />
</li>
<li><a href="http://#guild" target="_blank" rel="noopener" class="mycode_url">服务器</a><br />
</li>
<li><a href="http://#bot" target="_blank" rel="noopener" class="mycode_url">机器人</a><br />
</li>
<li><a href="http://#embed" target="_blank" rel="noopener" class="mycode_url">嵌入消息</a><br />
</li>
<li><a href="http://#emoji" target="_blank" rel="noopener" class="mycode_url">表情</a><br />
</li>
<li><a href="http://#react" target="_blank" rel="noopener" class="mycode_url">反应</a><br />
</li>
<li><a href="http://#misc" target="_blank" rel="noopener" class="mycode_url">其他</a><br />
</li>
</ul>
</li>
<li><a href="http://#callbacks" target="_blank" rel="noopener" class="mycode_url">Callbacks（回调函数）</a><ul class="mycode_list"><li><a href="http://#cb-ch" target="_blank" rel="noopener" class="mycode_url">频道回调</a><br />
</li>
<li><a href="http://#cb-msg" target="_blank" rel="noopener" class="mycode_url">消息回调</a><br />
</li>
<li><a href="http://#cb-usr" target="_blank" rel="noopener" class="mycode_url">用户回调</a><br />
</li>
<li><a href="http://#cb-guild" target="_blank" rel="noopener" class="mycode_url">服务器回调</a><br />
</li>
</ul>
</li>
</ol>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">1. 安装</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">1.1 创建 Kook 机器人</span><br />
<br />
<ol type="1" class="mycode_list"><li>访问 <a href="https://developer.kookapp.cn/" target="_blank" rel="noopener" class="mycode_url">https://developer.kookapp.cn/</a><br />
</li>
<li>创建一个新的应用 / 机器人<br />
</li>
<li>输入机器人名称并完成创建<br />
</li>
<li><a href="https://developer.kookapp.cn/doc/websocket" target="_blank" rel="noopener" class="mycode_url"><span style="color: #000000;" class="mycode_color"><span style="font-size: 1pt;" class="mycode_size"><span style="font-family: 'PingFang SC', 'Microsoft YaHei', Whitney, 'Helvetica Neue', Helvetica, Arial, sans-serif;" class="mycode_font">机器人连接模式</span></span></span></a>选择 <span style="font-weight: bold;" class="mycode_b">WEBSOCKET</span><br />
</li>
<li>从机器人设置页面获取你的 <span style="font-weight: bold;" class="mycode_b">机器人令牌（Bot Token）</span><br />
</li>
<li>通过开发者门户或邀请链接，将机器人邀请到你的服务器<br />
</li>
</ol>
<br />
<span style="text-decoration: underline;" class="mycode_u">1.2 配置令牌</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">SA-MP（server.cfg）：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>kook_bot_token YOUR_BOT_TOKEN_HERE</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">open.mp（config.json）：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"kook": {<br />
        "bot_token": "token"<br />
    }</code></div></div><br />
也可以使用环境变量代替：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SAMP_KOOK_BOT_TOKEN=YOUR_BOT_TOKEN_HERE</code></div></div><br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">注意事项：</span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">永远不要</span>将机器人令牌分享给任何人<br />
</li>
<li>确保服务器时钟定期同步，否则速率限制器将无法正常工作，机器人可能会被封禁<br />
</li>
<li>此插件专为 open.mp (OMP) 服务器设计<br />
</li>
</ul>
</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">2. 重要说明</span></span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">关于 Kook ID 与内部 ID：</span><br />
Kook ID 是一个很大的数字，无法放入 PAWN 的 32 位整数中。因此插件采用两套 ID 体系：<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Kook ID</span>：Kook 平台使用的真实 ID，必须以字符串形式传递<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">内部 ID</span>：插件内部使用的整数索引，通过 <span style="font-family: courier;" class="mycode_font">KCC_Find*</span> / <span style="font-family: courier;" class="mycode_font">KCC_Get*</span> 系列函数获取<br />
</li>
</ul>
<br />
你的脚本只需持有内部 ID（索引），插件会在内部维护与真实 ID 的映射关系。</blockquote>
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">关于发送私信：</span><br />
向用户发送私信需要两步：<br />
<ol type="1" class="mycode_list"><li>调用 <span style="font-family: courier;" class="mycode_font">KCC_CreatePrivateChannel(user, "回调函数名")</span> 打开私信频道<br />
</li>
<li>在回调函数中调用 <span style="font-family: courier;" class="mycode_font">KCC_GetCreatedPrivateChannel()</span> 获取频道 ID<br />
</li>
<li>使用该频道 ID 调用 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 等频道函数发送消息<br />
</li>
</ol>
</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">3. Natives（原生函数）</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.1 频道</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KOOK_FindChannelById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KOOK_FindChannelById(const channel_id[])</code></div></div>通过 Kook ID 查找频道，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Channel</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelId(KCC_Channel:channel, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取频道的 Kook ID，以文本形式存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelType</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelType(KCC_Channel:channel, &amp;KCC_ChannelType:type)</code></div></div>获取频道类型，存入 <span style="font-family: courier;" class="mycode_font">type</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelGuild</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelGuild(KCC_Channel:channel, &amp;KCC_Guild:guild)</code></div></div>获取频道所属服务器，存入 <span style="font-family: courier;" class="mycode_font">guild</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelName(KCC_Channel:channel, dest[], max_size = sizeof dest)</code></div></div>获取频道名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelTopic</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelTopic(KCC_Channel:channel, dest[], max_size = sizeof dest)</code></div></div>获取频道主题，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelPosition</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelPosition(KCC_Channel:channel, &amp;position)</code></div></div>获取频道排列位置，存入 <span style="font-family: courier;" class="mycode_font">position</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SendChannelMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SendChannelMessage(KCC_Channel:channel, const message[], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>向指定频道发送消息。<span style="font-family: courier;" class="mycode_font">callback</span>（可选）为消息发送确认后调用的公共函数，<span style="font-family: courier;" class="mycode_font">format</span> 及后续参数为回调参数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetChannelName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetChannelName(KCC_Channel:channel, const name[])</code></div></div>修改频道名称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetChannelTopic</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetChannelTopic(KCC_Channel:channel, const topic[])</code></div></div>修改频道主题。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteChannel(KCC_Channel:channel)</code></div></div>删除指定频道。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.2 消息</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageId(KCC_Message:message, dest[KCC_ID_SIZE], max_size = KCC_ID_SIZE)</code></div></div>获取消息的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageChannel(KCC_Message:message, &amp;KCC_Channel:channel)</code></div></div>获取消息所在频道，存入 <span style="font-family: courier;" class="mycode_font">channel</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageAuthor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageAuthor(KCC_Message:message, &amp;KCC_User:author)</code></div></div>获取消息发送者，存入 <span style="font-family: courier;" class="mycode_font">author</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageContent</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageContent(KCC_Message:message, dest[], max_size = sizeof dest)</code></div></div>获取消息文本内容，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsMessageMentioningEveryone</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsMessageMentioningEveryone(KCC_Message:message, &amp;bool:mentions_everyone)</code></div></div>检查消息是否 @全体成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageUserMentionCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageUserMentionCount(KCC_Message:message, &amp;mentioned_user_count)</code></div></div>获取消息中提及的用户数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageUserMention</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageUserMention(KCC_Message:message, offset, &amp;KCC_User:mentioned_user)</code></div></div>按索引获取消息中提及的某个用户。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageRoleMentionCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageRoleMentionCount(KCC_Message:message, &amp;mentioned_role_count)</code></div></div>获取消息中提及的身份组数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageRoleMention</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageRoleMention(KCC_Message:message, offset, &amp;KCC_Role:mentioned_role)</code></div></div>按索引获取消息中提及的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteMessage(KCC_Message:message)</code></div></div>在 Kook 上删除该消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedMessage()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 的回调中使用，返回刚发送的消息的内部 ID（带 <span style="font-family: courier;" class="mycode_font">KCC_Message</span> 标签）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteInternalMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteInternalMessage(KCC_Message:message)</code></div></div>从插件内部存储中移除该消息（<span style="font-weight: bold;" class="mycode_b">不会</span>在 Kook 上删除消息），用于持久化消息的清理。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_EditMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_EditMessage(KCC_Message:message, const content[], KCC_Embed:embed = KCC_Embed:0)</code></div></div>编辑消息内容，可选附带嵌入消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetMessagePersistent</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetMessagePersistent(KCC_Message:message, bool:persistent)</code></div></div>设置消息是否持久保存在插件内部存储中。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CacheChannelMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CacheChannelMessage(const channel_id[DCC_ID_SIZE], const message_id[DCC_ID_SIZE], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>通过 Kook ID 将指定消息缓存到插件中，缓存完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.3 用户</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>用户的 discriminator 是附加在 Kook 用户名后的 4 位数字标识。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindUserByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindUserByName(const user_name[], const user_discriminator[])</code></div></div>通过用户名 + discriminator 查找用户，返回带 <span style="font-family: courier;" class="mycode_font">KCC_User</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindUserById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindUserById(const user_id[])</code></div></div>通过 Kook ID 查找用户，返回带 <span style="font-family: courier;" class="mycode_font">KCC_User</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserId(KCC_User:user, dest[DCC_ID_SIZE], max_size = DCC_ID_SIZE)</code></div></div>获取用户的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserName(KCC_User:user, dest[DCC_USERNAME_SIZE], max_size = sizeof dest)</code></div></div>获取用户名，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserDiscriminator</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserDiscriminator(KCC_User:user, dest[], max_size = DCC_ID_SIZE)</code></div></div>获取用户的 discriminator，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsUserBot</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsUserBot(KCC_User:user, &amp;bool:is_bot)</code></div></div>检查用户是否为机器人。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsUserVerified</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsUserVerified(KCC_User:user, &amp;bool:is_verified)</code></div></div>检查用户是否已完成验证。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.4 身份组</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 DCC_ID_SIZE。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindRoleByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindRoleByName(KCC_Guild:guild, const role_name[])</code></div></div>在指定服务器中按名称查找身份组，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Role</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindRoleById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindRoleById(const role_id[])</code></div></div>通过 Kook ID 查找身份组，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Role</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleId(KCC_Role:role, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取身份组的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleName(KCC_Role:role, dest[], max_size = sizeof dest)</code></div></div>获取身份组名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleColor(KCC_Role:role, &amp;color)</code></div></div>获取身份组颜色值，存入 <span style="font-family: courier;" class="mycode_font">color</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRolePermissions</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRolePermissions(KCC_Role:role, &amp;perm_high, &amp;perm_low)</code></div></div>获取身份组权限（64 位整数分为高低两个 32 位部分）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsRoleHoist</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsRoleHoist(KCC_Role:role, &amp;bool:is_hoist)</code></div></div>检查身份组是否在成员列表中单独显示（提升显示）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRolePosition</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRolePosition(KCC_Role:role, &amp;position)</code></div></div>获取身份组的排列位置，存入 <span style="font-family: courier;" class="mycode_font">position</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsRoleMentionable</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsRoleMentionable(KCC_Role:role, &amp;bool:is_mentionable)</code></div></div>检查身份组是否可被 @ 提及。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.5 服务器</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 DCC_ID_SIZE。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">— 查询 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindGuildByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindGuildByName(const guild_name[])</code></div></div>按名称查找服务器，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Guild</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindGuildById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindGuildById(const guild_id[])</code></div></div>通过 Kook ID 查找服务器，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Guild</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildId(KCC_Guild:guild, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取服务器的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildName(KCC_Guild:guild, dest[], max_size = sizeof dest)</code></div></div>获取服务器名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildOwnerId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildOwnerId(KCC_Guild:guild, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取服务器所有者的 Kook 用户 ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetAllGuilds</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetAllGuilds(KCC_Guild:dest[], max_size = sizeof dest)</code></div></div>获取所有服务器的内部 ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span> 数组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 频道 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildChannel(KCC_Guild:guild, offset, &amp;KCC_Channel:channel)</code></div></div>按索引获取服务器中的某个频道。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildChannelCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildChannelCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器的频道总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildChannel(KCC_Guild:guild, const name[], DCC_ChannelType:type, const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>在服务器中创建新频道，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedGuildChannel()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreateGuildChannel</span> 的回调中使用，返回新创建频道的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 成员 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMember</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMember(KCC_Guild:guild, offset, &amp;KCC_User:user)</code></div></div>按索引获取服务器中的某个成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器成员总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberVoiceChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberVoiceChannel(KCC_Guild:guild, KCC_User:user, &amp;KCC_Channel:channel)</code></div></div>获取成员当前所在的语音频道。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberNickname</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberNickname(KCC_Guild:guild, KCC_User:user, dest[DCC_NICKNAME_SIZE], max_size = sizeof dest)</code></div></div>获取成员在服务器中的昵称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberRole(KCC_Guild:guild, KCC_User:user, offset, &amp;KCC_Role:role)</code></div></div>按索引获取成员拥有的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberRoleCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberRoleCount(KCC_Guild:guild, KCC_User:user, &amp;count)</code></div></div>获取成员拥有的身份组数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_HasGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_HasGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role, &amp;bool:has_role)</code></div></div>检查成员是否拥有指定身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildMemberNickname</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildMemberNickname(KCC_Guild:guild, KCC_User:user, const nickname[])</code></div></div>修改成员昵称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_AddGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_AddGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role)</code></div></div>为成员添加身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role)</code></div></div>移除成员的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMember</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMember(KCC_Guild:guild, KCC_User:user)</code></div></div>踢出服务器成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildMemberBan</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildMemberBan(KCC_Guild:guild, KCC_User:user, const reason[] = "")</code></div></div>封禁成员，可附带原因。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMemberBan</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMemberBan(KCC_Guild:guild, KCC_User:user)</code></div></div>解封成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 身份组管理 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildRole(KCC_Guild:guild, offset, &amp;KCC_Role:role)</code></div></div>按索引获取服务器中的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildRoleCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildRoleCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器的身份组总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildRole(KCC_Guild:guild, const name[], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>在服务器中创建新身份组，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedGuildRole()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreateGuildRole</span> 的回调中使用，返回新创建身份组的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteGuildRole(KCC_Guild:guild, KCC_Role:role)</code></div></div>删除服务器中的身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleName(KCC_Guild:guild, KCC_Role:role, const name[])</code></div></div>修改身份组名称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRolePermissions</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRolePermissions(KCC_Guild:guild, KCC_Role:role, perm_high, perm_low)</code></div></div>修改身份组权限（64 位整数分为高低两个 32 位部分）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleColor(KCC_Guild:guild, KCC_Role:role, color)</code></div></div>修改身份组颜色。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleHoist</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleHoist(KCC_Guild:guild, KCC_Role:role, bool:hoist)</code></div></div>设置身份组是否在成员列表中单独显示。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleMentionable</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleMentionable(KCC_Guild:guild, KCC_Role:role, bool:mentionable)</code></div></div>设置身份组是否可被 @ 提及。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.6 机器人</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreatePrivateChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreatePrivateChannel(KCC_User:user, const callback[], const format[] = "", {Float, _}:...)</code></div></div>向指定用户打开私信频道，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedPrivateChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedPrivateChannel()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreatePrivateChannel</span> 的回调中使用，返回私信频道的内部 ID（可直接用于 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 等函数）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.7 嵌入消息</span><br />
<br />
嵌入消息（Embed）允许向 Kook 频道发送富文本内容消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateEmbed</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateEmbed(const title[] = "", const description[] = "", const url[] = "", const timestamp[] = "", color = 0, const footer_text[] = "", const footer_icon_url[] = "", const thumbnail_url[] = "", const image_url[] = "")</code></div></div>创建一个嵌入消息，所有参数均为可选，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Embed</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteEmbed</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteEmbed(KCC_Embed:embed)</code></div></div>删除嵌入消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SendChannelEmbedMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SendChannelEmbedMessage(KCC_Channel:channel, KCC_Embed:embed, const message[] = "", const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>向频道发送带嵌入消息的内容，可附带普通文字。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_AddEmbedField</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_AddEmbedField(KCC_Embed:embed, const name[], const value[], bool:inline = false)</code></div></div>为嵌入消息添加字段，<span style="font-family: courier;" class="mycode_font">inline</span> 为 <span style="font-family: courier;" class="mycode_font">true</span> 时字段并排显示。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedTitle</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedTitle(KCC_Embed:embed, const title[])</code></div></div>设置嵌入消息标题。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedDescription</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedDescription(KCC_Embed:embed, const description[])</code></div></div>设置嵌入消息描述。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedUrl</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedUrl(KCC_Embed:embed, const url[])</code></div></div>设置嵌入消息链接。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedTimestamp</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedTimestamp(KCC_Embed:embed, const timestamp[])</code></div></div>设置嵌入消息时间戳。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedColor(KCC_Embed:embed, color)</code></div></div>设置嵌入消息左侧色条颜色。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedFooter</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedFooter(KCC_Embed:embed, const footer_text[], const footer_icon_url[] = "")</code></div></div>设置嵌入消息页脚文本，可附带图标 URL。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedThumbnail</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedThumbnail(KCC_Embed:embed, const thumbnail_url[])</code></div></div>设置嵌入消息缩略图。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedImage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedImage(KCC_Embed:embed, const image_url[])</code></div></div>设置嵌入消息主图片。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.8 表情</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 <span style="font-family: courier;" class="mycode_font">DCC_EMOJI_NAME_SIZE</span>。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateEmoji</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateEmoji(const name[DCC_EMOJI_NAME_SIZE], const snowflake[DCC_ID_SIZE] = "")</code></div></div>创建一个表情对象，<span style="font-family: courier;" class="mycode_font">snowflake</span> 为可选的 Kook 雪花 ID，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Emoji</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteEmoji</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteEmoji(KCC_Emoji:emoji)</code></div></div>删除表情对象。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetEmojiName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetEmojiName(KCC_Emoji:emoji, dest[DCC_EMOJI_NAME_SIZE], maxlen = DCC_EMOJI_NAME_SIZE)</code></div></div>获取表情名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.9 反应</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateReaction(KCC_Message:message, KCC_Emoji:reaction_emoji)</code></div></div>对指定消息添加表情反应。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteMessageReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteMessageReaction(KCC_Message:message, KCC_Emoji:reaction_emoji = KCC_Emoji:0)</code></div></div>移除消息上的表情反应。<span style="font-family: courier;" class="mycode_font">reaction_emoji</span> 为 0（默认）时删除该消息上的<span style="font-weight: bold;" class="mycode_b">所有</span>反应。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.10 其他</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_EscapeMarkdown</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_EscapeMarkdown(const src[], dest[], max_size = sizeof dest)</code></div></div>对字符串中的 Markdown 特殊字符进行转义，使文本在 Kook 消息中原样显示，不被格式化。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">4. Callbacks（回调函数）</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.1 频道回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelCreate(KCC_Channel:channel)</code></div></div>触发时机：服务器中有新频道创建时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelUpdate(KCC_Channel:channel)</code></div></div>触发时机：频道信息更新时（名称、权限等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelDelete(KCC_Channel:channel)</code></div></div>触发时机：频道被删除时。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.2 消息回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageCreate(KCC_Message:message)</code></div></div>触发时机：频道中有新消息发送时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageDelete(KCC_Message:message)</code></div></div>触发时机：消息被删除时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageReaction(KCC_Message:message, KCC_User:reaction_user, KCC_Emoji:emoji, DCC_MessageReactionType:reaction_type)</code></div></div>触发时机：消息添加或移除表情反应时。<ul class="mycode_list"><li><span style="font-family: courier;" class="mycode_font">message</span>：消息内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">reaction_user</span>：操作反应的用户内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">emoji</span>：使用的表情内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">reaction_type</span>：反应事件类型（添加 / 移除等）<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.3 用户回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnUserUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnUserUpdate(KCC_User:user)</code></div></div>触发时机：用户资料更新时（用户名、头像等）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.4 服务器回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildCreate(KCC_Guild:guild)</code></div></div>触发时机：服务器创建，或机器人加入新服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildUpdate(KCC_Guild:guild)</code></div></div>触发时机：服务器信息更新时（名称、图标等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildDelete(KCC_Guild:guild)</code></div></div>触发时机：服务器删除，或机器人离开服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberAdd</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberAdd(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：用户加入服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberUpdate(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：成员信息更新时（昵称、身份组等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberVoiceUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberVoiceUpdate(KCC_Guild:guild, KCC_User:user, KCC_Channel:channel)</code></div></div>触发时机：成员语音状态变化时（加入 / 离开语音频道）。<ul class="mycode_list"><li><span style="font-family: courier;" class="mycode_font">channel</span>：语音频道内部 ID，用户离开语音时该值可能无效<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberRemove</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberRemove(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：用户离开或被踢出服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleCreate(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器中创建新身份组时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleUpdate(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器身份组更新时（名称、颜色、权限等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleDelete(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器身份组被删除时。]]></description>
			<content:encoded><![CDATA[<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">samp-kook-connector 插件 Wiki</span></span><br />
<br />
将 Kook 机器人集成到你的 SA-MP / open.mp 服务器游戏模式中。<br />
<br />
下载地址：<a href="https://github.com/siwode1/samp-kook-connect" target="_blank" rel="noopener" class="mycode_url">siwode1/samp-kook-connect: SA:MP 插件用于控制 Kook bot (github.com)</a><br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">目录</span><br />
<br />
<ol type="1" class="mycode_list"><li><a href="http://#install" target="_blank" rel="noopener" class="mycode_url">安装</a><br />
</li>
<li><a href="http://#notes" target="_blank" rel="noopener" class="mycode_url">重要说明</a><br />
</li>
<li><a href="http://#natives" target="_blank" rel="noopener" class="mycode_url">Natives（原生函数）</a><ul class="mycode_list"><li><a href="http://#ch" target="_blank" rel="noopener" class="mycode_url">频道</a><br />
</li>
<li><a href="http://#msg" target="_blank" rel="noopener" class="mycode_url">消息</a><br />
</li>
<li><a href="http://#usr" target="_blank" rel="noopener" class="mycode_url">用户</a><br />
</li>
<li><a href="http://#role" target="_blank" rel="noopener" class="mycode_url">身份组</a><br />
</li>
<li><a href="http://#guild" target="_blank" rel="noopener" class="mycode_url">服务器</a><br />
</li>
<li><a href="http://#bot" target="_blank" rel="noopener" class="mycode_url">机器人</a><br />
</li>
<li><a href="http://#embed" target="_blank" rel="noopener" class="mycode_url">嵌入消息</a><br />
</li>
<li><a href="http://#emoji" target="_blank" rel="noopener" class="mycode_url">表情</a><br />
</li>
<li><a href="http://#react" target="_blank" rel="noopener" class="mycode_url">反应</a><br />
</li>
<li><a href="http://#misc" target="_blank" rel="noopener" class="mycode_url">其他</a><br />
</li>
</ul>
</li>
<li><a href="http://#callbacks" target="_blank" rel="noopener" class="mycode_url">Callbacks（回调函数）</a><ul class="mycode_list"><li><a href="http://#cb-ch" target="_blank" rel="noopener" class="mycode_url">频道回调</a><br />
</li>
<li><a href="http://#cb-msg" target="_blank" rel="noopener" class="mycode_url">消息回调</a><br />
</li>
<li><a href="http://#cb-usr" target="_blank" rel="noopener" class="mycode_url">用户回调</a><br />
</li>
<li><a href="http://#cb-guild" target="_blank" rel="noopener" class="mycode_url">服务器回调</a><br />
</li>
</ul>
</li>
</ol>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">1. 安装</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">1.1 创建 Kook 机器人</span><br />
<br />
<ol type="1" class="mycode_list"><li>访问 <a href="https://developer.kookapp.cn/" target="_blank" rel="noopener" class="mycode_url">https://developer.kookapp.cn/</a><br />
</li>
<li>创建一个新的应用 / 机器人<br />
</li>
<li>输入机器人名称并完成创建<br />
</li>
<li><a href="https://developer.kookapp.cn/doc/websocket" target="_blank" rel="noopener" class="mycode_url"><span style="color: #000000;" class="mycode_color"><span style="font-size: 1pt;" class="mycode_size"><span style="font-family: 'PingFang SC', 'Microsoft YaHei', Whitney, 'Helvetica Neue', Helvetica, Arial, sans-serif;" class="mycode_font">机器人连接模式</span></span></span></a>选择 <span style="font-weight: bold;" class="mycode_b">WEBSOCKET</span><br />
</li>
<li>从机器人设置页面获取你的 <span style="font-weight: bold;" class="mycode_b">机器人令牌（Bot Token）</span><br />
</li>
<li>通过开发者门户或邀请链接，将机器人邀请到你的服务器<br />
</li>
</ol>
<br />
<span style="text-decoration: underline;" class="mycode_u">1.2 配置令牌</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">SA-MP（server.cfg）：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>kook_bot_token YOUR_BOT_TOKEN_HERE</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">open.mp（config.json）：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"kook": {<br />
        "bot_token": "token"<br />
    }</code></div></div><br />
也可以使用环境变量代替：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SAMP_KOOK_BOT_TOKEN=YOUR_BOT_TOKEN_HERE</code></div></div><br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">注意事项：</span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">永远不要</span>将机器人令牌分享给任何人<br />
</li>
<li>确保服务器时钟定期同步，否则速率限制器将无法正常工作，机器人可能会被封禁<br />
</li>
<li>此插件专为 open.mp (OMP) 服务器设计<br />
</li>
</ul>
</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">2. 重要说明</span></span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">关于 Kook ID 与内部 ID：</span><br />
Kook ID 是一个很大的数字，无法放入 PAWN 的 32 位整数中。因此插件采用两套 ID 体系：<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Kook ID</span>：Kook 平台使用的真实 ID，必须以字符串形式传递<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">内部 ID</span>：插件内部使用的整数索引，通过 <span style="font-family: courier;" class="mycode_font">KCC_Find*</span> / <span style="font-family: courier;" class="mycode_font">KCC_Get*</span> 系列函数获取<br />
</li>
</ul>
<br />
你的脚本只需持有内部 ID（索引），插件会在内部维护与真实 ID 的映射关系。</blockquote>
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">关于发送私信：</span><br />
向用户发送私信需要两步：<br />
<ol type="1" class="mycode_list"><li>调用 <span style="font-family: courier;" class="mycode_font">KCC_CreatePrivateChannel(user, "回调函数名")</span> 打开私信频道<br />
</li>
<li>在回调函数中调用 <span style="font-family: courier;" class="mycode_font">KCC_GetCreatedPrivateChannel()</span> 获取频道 ID<br />
</li>
<li>使用该频道 ID 调用 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 等频道函数发送消息<br />
</li>
</ol>
</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">3. Natives（原生函数）</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.1 频道</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KOOK_FindChannelById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KOOK_FindChannelById(const channel_id[])</code></div></div>通过 Kook ID 查找频道，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Channel</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelId(KCC_Channel:channel, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取频道的 Kook ID，以文本形式存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelType</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelType(KCC_Channel:channel, &amp;KCC_ChannelType:type)</code></div></div>获取频道类型，存入 <span style="font-family: courier;" class="mycode_font">type</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelGuild</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelGuild(KCC_Channel:channel, &amp;KCC_Guild:guild)</code></div></div>获取频道所属服务器，存入 <span style="font-family: courier;" class="mycode_font">guild</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelName(KCC_Channel:channel, dest[], max_size = sizeof dest)</code></div></div>获取频道名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelTopic</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelTopic(KCC_Channel:channel, dest[], max_size = sizeof dest)</code></div></div>获取频道主题，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelPosition</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelPosition(KCC_Channel:channel, &amp;position)</code></div></div>获取频道排列位置，存入 <span style="font-family: courier;" class="mycode_font">position</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SendChannelMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SendChannelMessage(KCC_Channel:channel, const message[], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>向指定频道发送消息。<span style="font-family: courier;" class="mycode_font">callback</span>（可选）为消息发送确认后调用的公共函数，<span style="font-family: courier;" class="mycode_font">format</span> 及后续参数为回调参数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetChannelName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetChannelName(KCC_Channel:channel, const name[])</code></div></div>修改频道名称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetChannelTopic</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetChannelTopic(KCC_Channel:channel, const topic[])</code></div></div>修改频道主题。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteChannel(KCC_Channel:channel)</code></div></div>删除指定频道。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.2 消息</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageId(KCC_Message:message, dest[KCC_ID_SIZE], max_size = KCC_ID_SIZE)</code></div></div>获取消息的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageChannel(KCC_Message:message, &amp;KCC_Channel:channel)</code></div></div>获取消息所在频道，存入 <span style="font-family: courier;" class="mycode_font">channel</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageAuthor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageAuthor(KCC_Message:message, &amp;KCC_User:author)</code></div></div>获取消息发送者，存入 <span style="font-family: courier;" class="mycode_font">author</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageContent</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageContent(KCC_Message:message, dest[], max_size = sizeof dest)</code></div></div>获取消息文本内容，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsMessageMentioningEveryone</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsMessageMentioningEveryone(KCC_Message:message, &amp;bool:mentions_everyone)</code></div></div>检查消息是否 @全体成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageUserMentionCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageUserMentionCount(KCC_Message:message, &amp;mentioned_user_count)</code></div></div>获取消息中提及的用户数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageUserMention</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageUserMention(KCC_Message:message, offset, &amp;KCC_User:mentioned_user)</code></div></div>按索引获取消息中提及的某个用户。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageRoleMentionCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageRoleMentionCount(KCC_Message:message, &amp;mentioned_role_count)</code></div></div>获取消息中提及的身份组数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageRoleMention</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageRoleMention(KCC_Message:message, offset, &amp;KCC_Role:mentioned_role)</code></div></div>按索引获取消息中提及的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteMessage(KCC_Message:message)</code></div></div>在 Kook 上删除该消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedMessage()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 的回调中使用，返回刚发送的消息的内部 ID（带 <span style="font-family: courier;" class="mycode_font">KCC_Message</span> 标签）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteInternalMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteInternalMessage(KCC_Message:message)</code></div></div>从插件内部存储中移除该消息（<span style="font-weight: bold;" class="mycode_b">不会</span>在 Kook 上删除消息），用于持久化消息的清理。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_EditMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_EditMessage(KCC_Message:message, const content[], KCC_Embed:embed = KCC_Embed:0)</code></div></div>编辑消息内容，可选附带嵌入消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetMessagePersistent</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetMessagePersistent(KCC_Message:message, bool:persistent)</code></div></div>设置消息是否持久保存在插件内部存储中。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CacheChannelMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CacheChannelMessage(const channel_id[DCC_ID_SIZE], const message_id[DCC_ID_SIZE], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>通过 Kook ID 将指定消息缓存到插件中，缓存完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.3 用户</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>用户的 discriminator 是附加在 Kook 用户名后的 4 位数字标识。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindUserByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindUserByName(const user_name[], const user_discriminator[])</code></div></div>通过用户名 + discriminator 查找用户，返回带 <span style="font-family: courier;" class="mycode_font">KCC_User</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindUserById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindUserById(const user_id[])</code></div></div>通过 Kook ID 查找用户，返回带 <span style="font-family: courier;" class="mycode_font">KCC_User</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserId(KCC_User:user, dest[DCC_ID_SIZE], max_size = DCC_ID_SIZE)</code></div></div>获取用户的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserName(KCC_User:user, dest[DCC_USERNAME_SIZE], max_size = sizeof dest)</code></div></div>获取用户名，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserDiscriminator</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserDiscriminator(KCC_User:user, dest[], max_size = DCC_ID_SIZE)</code></div></div>获取用户的 discriminator，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsUserBot</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsUserBot(KCC_User:user, &amp;bool:is_bot)</code></div></div>检查用户是否为机器人。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsUserVerified</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsUserVerified(KCC_User:user, &amp;bool:is_verified)</code></div></div>检查用户是否已完成验证。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.4 身份组</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 DCC_ID_SIZE。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindRoleByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindRoleByName(KCC_Guild:guild, const role_name[])</code></div></div>在指定服务器中按名称查找身份组，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Role</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindRoleById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindRoleById(const role_id[])</code></div></div>通过 Kook ID 查找身份组，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Role</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleId(KCC_Role:role, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取身份组的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleName(KCC_Role:role, dest[], max_size = sizeof dest)</code></div></div>获取身份组名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleColor(KCC_Role:role, &amp;color)</code></div></div>获取身份组颜色值，存入 <span style="font-family: courier;" class="mycode_font">color</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRolePermissions</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRolePermissions(KCC_Role:role, &amp;perm_high, &amp;perm_low)</code></div></div>获取身份组权限（64 位整数分为高低两个 32 位部分）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsRoleHoist</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsRoleHoist(KCC_Role:role, &amp;bool:is_hoist)</code></div></div>检查身份组是否在成员列表中单独显示（提升显示）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRolePosition</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRolePosition(KCC_Role:role, &amp;position)</code></div></div>获取身份组的排列位置，存入 <span style="font-family: courier;" class="mycode_font">position</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsRoleMentionable</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsRoleMentionable(KCC_Role:role, &amp;bool:is_mentionable)</code></div></div>检查身份组是否可被 @ 提及。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.5 服务器</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 DCC_ID_SIZE。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">— 查询 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindGuildByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindGuildByName(const guild_name[])</code></div></div>按名称查找服务器，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Guild</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindGuildById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindGuildById(const guild_id[])</code></div></div>通过 Kook ID 查找服务器，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Guild</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildId(KCC_Guild:guild, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取服务器的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildName(KCC_Guild:guild, dest[], max_size = sizeof dest)</code></div></div>获取服务器名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildOwnerId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildOwnerId(KCC_Guild:guild, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取服务器所有者的 Kook 用户 ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetAllGuilds</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetAllGuilds(KCC_Guild:dest[], max_size = sizeof dest)</code></div></div>获取所有服务器的内部 ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span> 数组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 频道 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildChannel(KCC_Guild:guild, offset, &amp;KCC_Channel:channel)</code></div></div>按索引获取服务器中的某个频道。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildChannelCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildChannelCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器的频道总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildChannel(KCC_Guild:guild, const name[], DCC_ChannelType:type, const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>在服务器中创建新频道，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedGuildChannel()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreateGuildChannel</span> 的回调中使用，返回新创建频道的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 成员 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMember</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMember(KCC_Guild:guild, offset, &amp;KCC_User:user)</code></div></div>按索引获取服务器中的某个成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器成员总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberVoiceChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberVoiceChannel(KCC_Guild:guild, KCC_User:user, &amp;KCC_Channel:channel)</code></div></div>获取成员当前所在的语音频道。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberNickname</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberNickname(KCC_Guild:guild, KCC_User:user, dest[DCC_NICKNAME_SIZE], max_size = sizeof dest)</code></div></div>获取成员在服务器中的昵称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberRole(KCC_Guild:guild, KCC_User:user, offset, &amp;KCC_Role:role)</code></div></div>按索引获取成员拥有的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberRoleCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberRoleCount(KCC_Guild:guild, KCC_User:user, &amp;count)</code></div></div>获取成员拥有的身份组数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_HasGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_HasGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role, &amp;bool:has_role)</code></div></div>检查成员是否拥有指定身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildMemberNickname</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildMemberNickname(KCC_Guild:guild, KCC_User:user, const nickname[])</code></div></div>修改成员昵称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_AddGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_AddGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role)</code></div></div>为成员添加身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role)</code></div></div>移除成员的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMember</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMember(KCC_Guild:guild, KCC_User:user)</code></div></div>踢出服务器成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildMemberBan</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildMemberBan(KCC_Guild:guild, KCC_User:user, const reason[] = "")</code></div></div>封禁成员，可附带原因。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMemberBan</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMemberBan(KCC_Guild:guild, KCC_User:user)</code></div></div>解封成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 身份组管理 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildRole(KCC_Guild:guild, offset, &amp;KCC_Role:role)</code></div></div>按索引获取服务器中的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildRoleCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildRoleCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器的身份组总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildRole(KCC_Guild:guild, const name[], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>在服务器中创建新身份组，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedGuildRole()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreateGuildRole</span> 的回调中使用，返回新创建身份组的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteGuildRole(KCC_Guild:guild, KCC_Role:role)</code></div></div>删除服务器中的身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleName(KCC_Guild:guild, KCC_Role:role, const name[])</code></div></div>修改身份组名称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRolePermissions</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRolePermissions(KCC_Guild:guild, KCC_Role:role, perm_high, perm_low)</code></div></div>修改身份组权限（64 位整数分为高低两个 32 位部分）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleColor(KCC_Guild:guild, KCC_Role:role, color)</code></div></div>修改身份组颜色。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleHoist</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleHoist(KCC_Guild:guild, KCC_Role:role, bool:hoist)</code></div></div>设置身份组是否在成员列表中单独显示。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleMentionable</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleMentionable(KCC_Guild:guild, KCC_Role:role, bool:mentionable)</code></div></div>设置身份组是否可被 @ 提及。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.6 机器人</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreatePrivateChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreatePrivateChannel(KCC_User:user, const callback[], const format[] = "", {Float, _}:...)</code></div></div>向指定用户打开私信频道，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedPrivateChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedPrivateChannel()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreatePrivateChannel</span> 的回调中使用，返回私信频道的内部 ID（可直接用于 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 等函数）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.7 嵌入消息</span><br />
<br />
嵌入消息（Embed）允许向 Kook 频道发送富文本内容消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateEmbed</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateEmbed(const title[] = "", const description[] = "", const url[] = "", const timestamp[] = "", color = 0, const footer_text[] = "", const footer_icon_url[] = "", const thumbnail_url[] = "", const image_url[] = "")</code></div></div>创建一个嵌入消息，所有参数均为可选，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Embed</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteEmbed</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteEmbed(KCC_Embed:embed)</code></div></div>删除嵌入消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SendChannelEmbedMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SendChannelEmbedMessage(KCC_Channel:channel, KCC_Embed:embed, const message[] = "", const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>向频道发送带嵌入消息的内容，可附带普通文字。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_AddEmbedField</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_AddEmbedField(KCC_Embed:embed, const name[], const value[], bool:inline = false)</code></div></div>为嵌入消息添加字段，<span style="font-family: courier;" class="mycode_font">inline</span> 为 <span style="font-family: courier;" class="mycode_font">true</span> 时字段并排显示。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedTitle</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedTitle(KCC_Embed:embed, const title[])</code></div></div>设置嵌入消息标题。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedDescription</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedDescription(KCC_Embed:embed, const description[])</code></div></div>设置嵌入消息描述。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedUrl</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedUrl(KCC_Embed:embed, const url[])</code></div></div>设置嵌入消息链接。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedTimestamp</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedTimestamp(KCC_Embed:embed, const timestamp[])</code></div></div>设置嵌入消息时间戳。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedColor(KCC_Embed:embed, color)</code></div></div>设置嵌入消息左侧色条颜色。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedFooter</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedFooter(KCC_Embed:embed, const footer_text[], const footer_icon_url[] = "")</code></div></div>设置嵌入消息页脚文本，可附带图标 URL。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedThumbnail</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedThumbnail(KCC_Embed:embed, const thumbnail_url[])</code></div></div>设置嵌入消息缩略图。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedImage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedImage(KCC_Embed:embed, const image_url[])</code></div></div>设置嵌入消息主图片。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.8 表情</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 <span style="font-family: courier;" class="mycode_font">DCC_EMOJI_NAME_SIZE</span>。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateEmoji</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateEmoji(const name[DCC_EMOJI_NAME_SIZE], const snowflake[DCC_ID_SIZE] = "")</code></div></div>创建一个表情对象，<span style="font-family: courier;" class="mycode_font">snowflake</span> 为可选的 Kook 雪花 ID，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Emoji</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteEmoji</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteEmoji(KCC_Emoji:emoji)</code></div></div>删除表情对象。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetEmojiName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetEmojiName(KCC_Emoji:emoji, dest[DCC_EMOJI_NAME_SIZE], maxlen = DCC_EMOJI_NAME_SIZE)</code></div></div>获取表情名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.9 反应</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateReaction(KCC_Message:message, KCC_Emoji:reaction_emoji)</code></div></div>对指定消息添加表情反应。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteMessageReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteMessageReaction(KCC_Message:message, KCC_Emoji:reaction_emoji = KCC_Emoji:0)</code></div></div>移除消息上的表情反应。<span style="font-family: courier;" class="mycode_font">reaction_emoji</span> 为 0（默认）时删除该消息上的<span style="font-weight: bold;" class="mycode_b">所有</span>反应。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.10 其他</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_EscapeMarkdown</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_EscapeMarkdown(const src[], dest[], max_size = sizeof dest)</code></div></div>对字符串中的 Markdown 特殊字符进行转义，使文本在 Kook 消息中原样显示，不被格式化。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">4. Callbacks（回调函数）</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.1 频道回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelCreate(KCC_Channel:channel)</code></div></div>触发时机：服务器中有新频道创建时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelUpdate(KCC_Channel:channel)</code></div></div>触发时机：频道信息更新时（名称、权限等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelDelete(KCC_Channel:channel)</code></div></div>触发时机：频道被删除时。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.2 消息回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageCreate(KCC_Message:message)</code></div></div>触发时机：频道中有新消息发送时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageDelete(KCC_Message:message)</code></div></div>触发时机：消息被删除时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageReaction(KCC_Message:message, KCC_User:reaction_user, KCC_Emoji:emoji, DCC_MessageReactionType:reaction_type)</code></div></div>触发时机：消息添加或移除表情反应时。<ul class="mycode_list"><li><span style="font-family: courier;" class="mycode_font">message</span>：消息内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">reaction_user</span>：操作反应的用户内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">emoji</span>：使用的表情内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">reaction_type</span>：反应事件类型（添加 / 移除等）<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.3 用户回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnUserUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnUserUpdate(KCC_User:user)</code></div></div>触发时机：用户资料更新时（用户名、头像等）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.4 服务器回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildCreate(KCC_Guild:guild)</code></div></div>触发时机：服务器创建，或机器人加入新服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildUpdate(KCC_Guild:guild)</code></div></div>触发时机：服务器信息更新时（名称、图标等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildDelete(KCC_Guild:guild)</code></div></div>触发时机：服务器删除，或机器人离开服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberAdd</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberAdd(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：用户加入服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberUpdate(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：成员信息更新时（昵称、身份组等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberVoiceUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberVoiceUpdate(KCC_Guild:guild, KCC_User:user, KCC_Channel:channel)</code></div></div>触发时机：成员语音状态变化时（加入 / 离开语音频道）。<ul class="mycode_list"><li><span style="font-family: courier;" class="mycode_font">channel</span>：语音频道内部 ID，用户离开语音时该值可能无效<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberRemove</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberRemove(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：用户离开或被踢出服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleCreate(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器中创建新身份组时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleUpdate(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器身份组更新时（名称、颜色、权限等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleDelete(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器身份组被删除时。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[圣安地列斯联机二十年：SA:MP 与 open.mp 历史]]></title>
			<link>https://open-mp.cn/showthread.php?tid=30</link>
			<pubDate>Tue, 24 Mar 2026 20:45:15 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=30</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">圣安地列斯联机二十年：SA:MP 与 open.mp 历史</h2><br />
<br />
2026 年。GTA6 即将在今年 11 月发售，新的时代正在敲门。<br />
<br />
也是在这一年，《侠盗猎车手：圣安地列斯》PC 版上市整整二十年，SA:MP 的第一个可玩版本也已走过二十个年头。<br />
<br />
一座从未被设计为联机游戏的城市，有人在这里认识了一辈子的朋友。有人在这里第一次学会了写代码。有人在角色扮演服务器里扮演一个JC或一个黑帮头目。有人在一个无聊的下午打开了游戏，然后就再也没有那个下午了。<br />
<br />
SA:MP 从来不是一个精致的产品。它是一群人强行塞进一款单人游戏里的多人世界。它有数不清的 bug，有争议不断的管理者，有过漫长的停滞与分裂——它也有 open.mp，有一批不肯让它消失的开发者，有如今可以在手机上随时上线的客户端，不管你还记不记得服务器的 IP，不管你当年是服主、脚本开发者，还是只是一个普通的玩家——你在这里的时间是真实的。<br />
<br />
GTA6 会带来它的世界。但圣安地列斯的街道，还在。服务器还在跑，玩家还在上线，有人还在第一次输入 /register。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">前言</h3><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>本文以客观事实为准绳。所有关键事件、人物声明、原始帖文，均完整收录于正文之中，不以外部链接替代实质内容。链接仅作考证索引，供读者溯源查验，不构成叙述本身的一部分。<br />
<br />
凡引用原文处，均以引用块标注，并注明来源与时间。凡转述处，均忠实于原意，不加渲染，不作价值评判。<br />
<br />
这是一部关于热爱、控制、背叛与重建的故事，也是一个游戏社区在二十年间走过的记录。</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">卷首语：一个不该有多人模式的游戏</h3><br />
<br />
2004 年 10 月 26 日，《侠盗猎车手：圣安地列斯》（Grand Theft Auto: San Andreas）在 PlayStation 2 平台正式发售。2005 年 6 月 10 日，PC 版本上市。<br />
<br />
这款游戏从未被设计为多人联机。Rockstar Games 为它设计了一个宏大的单人故事——主角 CJ 在帮派、JC与腐败之间挣扎求生，横跨三座城市、一片乡野。游戏没有联机大厅，没有服务器浏览器，没有任何供多人游玩的接口。<br />
<br />
然而在 GTA 模组社区里，有一批人从不接受"这不可能"这个答案。<br />
<br />
他们是一群来自世界各地的年轻人，大多数有着普通的日间生活——学生、程序员、上班族——他们一点一点地撬开这款游戏的外壳，试图将它改造成一个可以容纳数百人同时在线的多人世界。<br />
<br />
这便是 SA:MP 的起点。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第一卷：诞生（2004–2006）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第一章　从 Vice City 到 San Andreas</h4><br />
<br />
在《圣安地列斯》PC 版尚未发售之前，GTA 模组社区已经有人在为《GTA 罪恶都市》（Vice City）制作多人联机改造，这个项目被命名为 <span style="font-weight: bold;" class="mycode_b">VC:MP（Vice City Multiplayer）</span>。<br />
<br />
领导这支早期团队的，是一个网名叫 <span style="font-weight: bold;" class="mycode_b">kyeman</span> 的开发者，真名 <span style="font-weight: bold;" class="mycode_b">Kye Bitossi</span>。他在 GTA 模组社区中颇有声望，是公认的技术核心人物。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2005 年 4 月初</span>，kyeman 在全球最大的 GTA 社区论坛 <span style="font-weight: bold;" class="mycode_b">GTAForums</span> 上发布了一篇帖子，正式宣布 SA:MP 项目的存在。帖子标题是：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"[WIP] SA-MP: Multiplayer for San Andreas PC"</span><br />
——kyeman，GTAForums，2005年4月3日</blockquote>
<br />
消息一出，社区立刻沸腾。预告视频和截图开始在各大 GTA 论坛流传，项目的小型社区论坛在尚未开放任何测试的情况下，已吸引了约 <span style="font-weight: bold;" class="mycode_b">120 名注册用户</span>。<br />
<br />
公开 beta 测试期间，服务器承载能力远不及涌入的测试者数量，进入测试服务器需要排队等候，等待时间往往很长。这种盛况，是对整个项目最好的背书。<br />
<br />
进入开发团队的成员，来自 GTA 模组社区的各个方向，过去的SA-MP 0.2开发者和测试者包括：kyeman、spookie、Y_Less、mike、jax、Mike、Cam、adamcs、bakasan、Born Acorn、Dalpura、Damian、Delfi、dexx、DrAke&#36;、Drift、ECLiPSE、f3llah1n、him selfe、illspirit、littlewhitey、MrJax、njr1489、Posty、PsYcHoGoD、Shizz、Simon、sockx、squiddy、Static、steve-m、The Azer、Trix、Wacko、XcR、[ULK]Crack，其中许多人既是开发者也是测试员。<br />
<br />
他们大多是业余爱好者，利用业余时间共同推进这个无人出资的项目。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第二章　合作模式的争议与团队第一次动荡</h4><br />
<br />
然而，SA:MP 从一开始便并非一片和谐。<br />
<br />
开发团队内部，关于游戏核心玩法的方向，爆发了一场至今仍被一些老玩家提起的根本性争论：<br />
<br />
一部分人主张将 SA:MP 建设为一款<span style="font-weight: bold;" class="mycode_b">合作模式（Co-op）</span>游戏，设想最多 6 名玩家共同游玩，保留完整的 NPC 行为、警察追捕系统与任务流程，让多人体验尽可能接近单人游戏的质感；<br />
<br />
另一方，以 kyeman 为首，坚持将其建设为一个能够容纳大量玩家同时在线的<span style="font-weight: bold;" class="mycode_b">大规模死亡竞技（Deathmatch）</span>式多人服务器。<br />
<br />
这场分歧并未在内部平息，而是溢出到了 GTANet 社区论坛，引发了玩家的大量公开讨论与批评，负面声音之多，令整个项目团队承受了巨大压力。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2005 年 9 月 18 日</span>，kyeman 在持续的内外压力下，宣布因个人事务无暇继续领导项目，将主导权移交给团队二号核心开发者 <span style="font-weight: bold;" class="mycode_b">spooky</span>。<br />
<br />
spooky 接手后，将项目更名为 <span style="font-weight: bold;" class="mycode_b">GTA:Multiplayer（GTA:M）</span>，以示风格与管理方式的转变。<br />
<br />
然而，约一个月后，kyeman 重新归队。合作模式方案在此期间被彻底搁置，项目名称最终改回 <span style="font-weight: bold;" class="mycode_b">San Andreas Multiplayer（SA:MP）</span>，方向确定为大规模多人在线游戏。<br />
<br />
关于"Grand Theft Auto"字样是否应出现在项目名称中，团队在命名时也有过考量——使用 Rockstar 的商标可能引发法律风险，最终以缩写"SA:MP"作为正式名称，在一定程度上规避了这一问题。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第三章　2006 年：第一个可玩版本</h4><br />
<br />
在经历了那段动荡之后，SA:MP 于 <span style="font-weight: bold;" class="mycode_b">2006 年</span> 发布了第一个向公众开放的可玩版本。<br />
<br />
从技术层面看，这是一项相当可观的成就：开发者们在完全没有官方支持的前提下，用逆向工程的方式强行将联机功能"嵌入"进一款从未被设计为多人联机的作品，使其能够支持最多 <span style="font-weight: bold;" class="mycode_b">1000 名玩家</span>同时在线，在同一片虚拟的圣安地列斯地图中驾车、射击、竞速。<br />
<br />
服务器使用 <span style="font-weight: bold;" class="mycode_b">Pawn</span> 作为脚本语言，服务器主可以自行编写游戏模式（GameMode）与过滤脚本（FilterScript）。这一设计赋予了整个生态极高的开放性——任何人只要学会 Pawn，就可以在圣安地列斯的地图上建造出属于自己的世界。<br />
<br />
0.2.2 版本是这一阶段的代表版本，也是现存有据可查的最早可玩 SA:MP 版本记录之一。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第二卷：黄金时代与暗流（2006–2009）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第四章　版本迭代与社区的兴盛</h4><br />
<br />
2006 年至 2014 年，是 SA:MP 最活跃的开发阶段。Kalcor（此时 kyeman 已开始使用这个网名）陆续发布了一系列重要版本：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">0.2 系列</span>（2006–2008）期间，SA:MP 奠定了基本架构，确立了 Pawn 脚本语言作为游戏模式开发的标准。这段时间并非全然顺利——一次大规模安全漏洞爆发，险些让整个团队就此放弃。而最终让他们坚持下来的，是一份在线请愿：短短时间内，数以千计的玩家签名支持 SA:MP 继续存在。这份来自社区的温度，让开发者重新燃起了动力。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">0.3a</span>（约 2010 年）是 SA:MP 历史上最具里程碑意义的版本之一。单服务器玩家上限从原来的数百人扩展至 <span style="font-weight: bold;" class="mycode_b">500 人</span>（后续版本更高），引入了鼠标驱动的记分板与聊天界面，增加了可编程的 NPC 机器人系统（允许服务器创建可驾驶火车、飞机的脚本机器人），网络同步质量大幅改善。<br />
<br />
此后数年，<span style="font-weight: bold;" class="mycode_b">0.3c、0.3d、0.3e、0.3x、0.3z</span> 相继发布，带来了音频流媒体支持、延迟补偿模式、自定义对象渲染距离、新的安全更新等功能。每一个版本的发布，都在 SA:MP 官方论坛的"新闻与更新"板块留下了一条由 Kalcor 亲自发布的公告。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2015 年 5 月 1 日</span>，Kalcor 发布了 SA:MP <span style="font-weight: bold;" class="mycode_b">0.3.7</span>，这是 SA:MP 有史以来最后一个带有实质性新功能的正式版本。0.3.7 新增了超过 500 个物体 ID（含特技物件与地形物件）、界面字体大小调整选项、若干新版警察皮肤、服务端对车门与车窗的控制权、为未标记警车添加警报灯的能力，以及一个简单的静态 NPC actor 系统。<br />
<br />
这个版本在此后数年间成为整个 SA:MP 生态的事实标准，直至今日仍是服务器主最常使用的版本。<br />
<br />
与此同时，这个社区在技术之外也在野蛮生长。<span style="font-weight: bold;" class="mycode_b">角色扮演（RP）服务器</span>在这段时期走向成熟，玩家们在 SA:MP 的世界中建构起了拥有经济系统、帮派政治、法律体系的虚拟社会。来自世界各地大型服务器先后崛起。SA:MP 不再只是一个小众模组，它已经成为一个真实的、活跃的、跨越语言与国境的国际社区。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第五章　Y_Less 的双重身份与 YSI 的诞生</h4><br />
<br />
在 SA:MP 的所有社区开发者中，有一个人的名字几乎是无可回避的：<span style="font-weight: bold;" class="mycode_b">Y_Less</span>，真名 Alex Cole。<br />
<br />
Y_Less 最初以 beta 测试员的身份加入 SA:MP 团队，随后正式成为开发团队成员，主要负责 Pawn 脚本语言相关的功能开发。然而，他与 Kalcor 之间的分歧，从他正式入队的第一天起便已埋下。<br />
<br />
用 Y_Less 自己后来的话说：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"加入开发团队之后，我开始开发 Pawn，但我发现自己能做的事被 Kye 严重限制。我们之间存在重大的意见分歧：他认为 90% 的开发精力应该投入同步（sync）工作，Pawn 几乎只是顺手提供一点额外功能的附属品。而我认为，虽然同步很重要，但他已经把同步覆盖得很好了，我更想专注于 Pawn 的功能与函数。然而他是老板，说了算，严重限制了我被允许做的事。此外，他有个坏习惯——每次版本迭代之后，只要在某个细枝末节的测试中有任何不稳定，就要来指责我，尽管测试本来就是我们有 beta 测试团队的原因。不用说，这不是一个好的工作环境，但我仍然喜欢 SA:MP 这个产品本身。"</span></blockquote>
<br />
在这种压抑的工作环境中，Y<span style="font-style: italic;" class="mycode_i">Less 于 <span style="font-weight: bold;" class="mycode_b">2007 年</span> 开始独立开发 <span style="font-weight: bold;" class="mycode_b">YSI（Y</span>Less' Server/Script Includes）</span>。<br />
<br />
YSI 最初是他此前若干工具的整合与升级，同时也是他在 Kalcor 的管控边界之外，以纯 Pawn 脚本的方式，实现他认为 SA:MP 脚本系统应当具备的扩展能力。他在这个过程中也加入了一些辅助性的函数，例如 player objects 功能，最初是专门为了支撑他的对象流式传输器 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">e_objects</code> 而写的。<br />
<br />
用 Y_Less 自己的话说：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"2007 年，我开始开发 YSI。这部分是对若干早期工具的更新与整合，部分也是在 Kye 的控制之外，以 Pawn 能力范围内的方式带来我认为 Pawn 所需的扩展功能——尽管以纯 Pawn 来做，能实现的事情自然有其上限。YSI 成为我的主要项目这一事实惹恼了 Kye，因为他认为这说明我没有把时间花在 SA:MP 上，尽管我实际上一直都在。"</span></blockquote>
<br />
YSI 涵盖了命令处理（y<span style="font-style: italic;" class="mycode_i">commands）、玩家迭代器（y</span>iterate）、钩子机制（y<span style="font-style: italic;" class="mycode_i">hooks）、INI 文件读写（y</span>ini）、多语言支持（y_languages）等数十个子模块，是当时 SA:MP 社区功能最全面、使用最广泛的第三方脚本库。<br />
<br />
至于"YSI"到底代表什么，连 Y_Less 本人也说不清：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"最初的想法是'Y[i]Less' Server Includes'，但 Server 和 Script 经常被混用，而且现在参与的开发者不止 Y</span>Less 一人，所以'Y'就变成了一个递归缩写，代表'YSI'本身。"[/i]</blockquote>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第六章　2008 年底：GTANet 风波与团队大出走</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2008 年底</span>，SA:MP 开发团队内部爆发了一场与 GTANet 社区相关的严重矛盾。关于这场风波的具体细节，现有的公开资料已难以完整还原，但其结果是清晰且影响深远的：<span style="font-weight: bold;" class="mycode_b">Mike、aru 和 Peter</span> 等多名核心开发者相继以此为由宣布离队。<br />
<br />
Y_Less 在日后的声明中这样描述这段经历：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"2008 年底，GTANet 风波爆发，Mike、aru 和 Peter 因此离开，我也因为团队氛围实在太差，加之大家都在走，便也一同离开了。"</span></blockquote>
<br />
这一波出走之后，SA:MP 的开发工作几乎完全落回 Kalcor 一人肩上，这进一步强化了整个项目对他个人的高度依赖，也使得社区的任何集体意见都更加难以产生实质影响。<br />
<br />
然而事情并未就此平息。Y_Less 出走后，出于他自己也说不清的原因，重新回归了团队。他在后来的声明中写道：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"不知为何，真的记不清了，我之后又重新加入了团队。那时候 Kye 想要关闭 SA:MP，我提出愿意接手，他拒绝了。然后我再次退出——不是因为我没接手到，这一点需要说明——于是 Kye 决定封禁我的论坛账号，而且不只是封号，而是彻底抹除——删掉了我所有的帖子。这意味着原版《实用函数》帖没了，旧版 FAQ 帖没了，大量迷你教程没了，《Pawn 关键词》帖也没了——我只有在非常必要的时候才发帖，那些帖子都有其存在的价值，它们的消失被大量用户注意到并提出了强烈抗议。"</span></blockquote>
<br />
这便是 2008 年底那次"第一次封号"事件的始末——相对低调，但已经是一个信号。真正震动整个社区的风波，还在后面。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第七章　2009 年 1 月：YSF 封号事件</h4><br />
<br />
从团队再度离开之后，Y<span style="font-style: italic;" class="mycode_i">Less 没有停止为社区创作工具。他开发了 <span style="font-weight: bold;" class="mycode_b">YSF（Y</span>Less' Server Fixes）</span>——一个以服务端插件形式存在的 bug 修复集合。<br />
<br />
YSF 的设计理念很简单：SA:MP 有很多 Kalcor 长期忽略或拒绝修复的 bug，既然拿不到源代码，那就通过内存操作（memory patching）的方式，在运行时强行修正这些行为。这个方法技术上相当复杂，但效果立竿见影。<br />
<br />
Y_Less 事后这样形容 YSF：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"YSF 是我最成功的项目，因为它做到了所有人都想要的事。它本质上是一个更新版的服务端——人们总是渴望新版本带来修复和新功能，功能方面已经有其他插件（包括 YSI 插件）覆盖了，所以我选择了修复这条路（以及一些小功能——显然正是这些小功能引发了麻烦）。"</span></blockquote>
<br />
YSF 在社区中广泛流传，大量服务器安装并使用它。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">2009 年 1 月 19 日</span>，事件的直接导火索被点燃。<br />
<br />
当天，Kalcor 私信给 Y_Less，表达了对 YSF 的不满。他的顾虑有两项：<br />
<br />
第一，他认为 YSF 可能与 SA:MP 未来版本产生脚本兼容性问题；第二，他认为 YSF 代码中存在与 SA:MP 服务端源代码相似的内容，以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">functions.cpp</code> 中的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">IsNickInvalid</code> 函数为例。<br />
<br />
Y_Less 对此逐一作出回应。关于兼容性问题，他指出 YSF 恰恰是在让脚本对未来版本<span style="font-weight: bold;" class="mycode_b">更加</span>兼容，而非相反；关于源代码问题，他坦言：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"这实际上并非盗用，但我承认看起来非常相似，因为它做的事情完全一样，而且也不是什么复杂的函数，我懒得争，就直接把它彻底重写了。"</span></blockquote>
<br />
他还顺带提到，Kalcor 自己曾主导过一些令他反对的修改决策——比如改变服务端的默认运行风格，以及在 0.3 版本中移除对象（最后改为以 IPL 文件形式替代，而非完全移除）——当初他的反对意见被 Kalcor 直接否决。<br />
<br />
双方讨论的最终结果，表面上是达成了共识：Kalcor 表示接受了 Y_Less 的解释，YSF 可以继续存在。<br />
<br />
然而，Y_Less 第二天登录论坛，发现自己已经被封号。<br />
<br />
他在后来的声明中还原了这段过程：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"就在我们讨论同意 YSF 可以继续存在，之后，他发现了 SetServerRule，并意识到它可以用来修改只读控制台变量——比如服务器版本号——从而让人们能够违反 SA:MP 服务条款第（g）条：'你不得人为地增加玩家数量，或向 SA:MP 查询机制提供虚假信息。'"</span></blockquote>
<br />
Kalcor 认为，Y_Less 在 YSF 中提供了这样一个功能，就等同于为违规行为提供了手段，因此必须承担责任。<br />
<br />
封号通知的原文如下（Y_Less 在声明中直接引用）：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>*"抱歉 ssǝן‾ʎ，你已被禁止使用本论坛！  <br />
滥用前开发者身份。入侵服务器，并为他人违反服务条款提供手段。"*</blockquote>
<br />
封号的同时，Kalcor 再次<span style="font-weight: bold;" class="mycode_b">删除了 Y_Less 在 SA:MP 官方论坛上的全部历史帖子</span>。大量教程、工具发布帖、FAQ 就此永久消失，众多用户注意到这些帖子的蒸发，并提出了强烈抗议。<br />
<br />
Y_Less 随即在社区发布了一篇完整声明，以下是他原文的核心段落：<br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"基本上，我因为 YSF 被 SA:MP 官方论坛封号了！</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">历史：</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">200x 年（实在记不清了），在与 Spookie 讨论之后，我以 beta 测试员的身份加入了 SA:MP 团队——那还是第一次公开 beta 之前的事——并开始编写 Pawn 相关的代码。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">没过多久，我正式加入了开发团队，专注于 Pawn 的开发，但我很快发现自己受到 Kye 的诸多限制，做不了想做的事。我们之间存在重大分歧：他认为 90% 的开发精力应该用于同步（sync），Pawn 只是顺手提供一点额外功能的附属品；而我认为，虽然同步很重要，但他已经把同步做得很好了，我更想把时间花在 Pawn 的功能扩展上。然而他是老板，说了算，严重限制了我能做的事。更让人受不了的是，他有个习惯——每次版本迭代后，只要在某个犄角旮旯的测试里出了任何小问题，就要来责怪我，哪怕我们有 beta 测试团队本来就是为了发现这些问题的。说实话那不是一个好的工作环境，但我还是喜欢 SA:MP 这个产品本身。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2007 年，我开始开发 YSI。这一方面是对此前一批旧项目的整合升级，另一方面也是想在 Kye 的管控之外，以纯 Pawn 脚本的方式实现我认为 Pawn 所需要的扩展功能——尽管能做到的事情有限，毕竟纯 Pawn 本身有其局限（我确实额外添加了一些辅助函数，比如 player objects 功能完全是为了写我最初的对象流式传输器 e\_objects 而专门实现的）。YSI 成为我的主要项目这件事惹恼了 Kye，因为他觉得我没有把时间花在 SA:MP 上——尽管我实际上一直都在。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2008 年底，GTANet 社区风波爆发，Mike、aru 和 Peter 因此离队。我也因为团队氛围实在太差，加上大家都在走，便也跟着离开了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不知为何（真的记不清了），我之后又重新回归了团队。那时候 Kye 想要关闭 SA:MP，我主动提出愿意接手，他拒绝了。然后我再次退出——不是因为没接手到，这一点需要说清楚——于是 Kye 决定封禁我的论坛账号，而且不只是封号，而是彻底抹除，删掉了我所有的帖子。这意味着原版《实用函数》帖没了，旧版 FAQ 帖没了，大量迷你教程没了，《Pawn 关键词》帖也没了——我只有在非常必要的时候才会发帖，那些帖子都有其价值，它们的消失被大量用户注意到并提出了抗议。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不管怎样，我还是喜欢 SA:MP 和这个社区本身（至少喜欢其中的一部分），所以我还是留了下来（现在回想起来真不知道当时为什么，深感后悔），并继续努力让 SA:MP 变得更好——尽管 Kye 的存在让这件事很难。我继续开发 YSI、写教程和帮助帖，后来又创作了 YSF。YSF 大概是我最成功的项目了，因为它做到了所有人都想要的事。它本质上就是一个改进版的服务端——人们总是渴望新版本带来修复和新功能，功能方面已经有其他插件（包括 YSI 插件）覆盖了，所以我选择了专注于修复这条路（以及一些小功能——显然正是这些小功能引发了这次麻烦）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">总之，Kye 和我一般都各自行事、互不干扰（至少我是这么以为的），有一段时间相安无事。直到 2009 年 1 月 19 日，我收到了 Kye 的消息，说他不太喜欢我在 YSF 里做的事。经过一番交涉，才明白他的顾虑在于：YSF 可能与未来版本的脚本产生兼容性问题（这话从他嘴里说出来真是讽刺——我当初就反对过他把默认运行方式改掉，以及 0.3 版本里删除对象的决定，但他否决了我；对象最后是改成了 IPL 文件的形式，而非完全删除，但也没有了 per-player objects，至少我最后听到的消息是这样）。此外，他还质疑 YSF 里有 SA:MP 服务端的源代码——他举的例子是 functions.cpp 里的 IsNickInvalid 函数。这个函数其实不是照抄的，但我承认看起来确实很像，毕竟它做的事完全一样，而且也不是什么复杂的函数，我懒得争，就直接把它彻底重写了。在我指出 YSF 并不会造成兼容性问题（恰恰相反，它让脚本对未来版本的兼容性更好），并同意日后不再使用 SA:MP 源代码（尽管我此前一直在刻意避免这样做）之后，他让步了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">第二天我上论坛，发现自己已经被封了……</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">原来在我们达成共识之后，他又发现了 SetServerRule 这个功能，意识到它可以用来修改只读控制台变量（比如服务器版本号），从而让人能够违反 SA:MP 服务条款第（g）条：'你不得人为地增加玩家数量，或向 SA:MP 查询机制提供虚假信息。'</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我解释说，我本人根本没有这样做，这个功能的设计初衷是好的，只是不幸被人滥用了。我甚至想过反问他：他提供论坛和 IRC 频道，同样也给人们提供了违反条款（c）（d）条的方式，按他的逻辑，他也应该被封号——但我懒得说了。封号通知的原文是：</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">'抱歉 ssǝן‾ʎ，你已被禁止使用本论坛！滥用前开发者身份。入侵服务器，并为他人违反服务条款提供手段。'</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">所谓'滥用'，是指我用它改善了所有人的游戏体验；所谓'入侵服务器'，是指我修复了它；所谓'提供手段'，意思是人们可以拿我提供的工具做坏事——但这不代表我支持或认可这种行为，这只是一个有用工具所带来的无奈副作用。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">Kye 说 YSF 的事已经覆水难收，他只能发布新版本来屏蔽它，伤害已经造成，它已经广泛传播，人们正在用它黑自己的服务器，没有人能阻止，所以我必须被封。我回应说，如果我没被封，我本来可以发布最新版本，在修复拾取物 bug 的同时，加入对规则的只读标志检查——虽然这无法彻底解决问题，但能大幅减少滥用，因为几乎没有人会主动把它改回旧方式，大多数人会为了这个重要修复而升级。说到这里，他就不再回复我了（我觉得他是意识到自己断掉了快速、高效解决这件事的唯一合理途径，然后不想认账了——如果不是这样，我欢迎他来回应）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">总之，我决定把当时正在写的那段代码（YSI 的示例脚本）收个尾，毕竟我还是喜欢使用 YSI 的那些人，上传最终版本，然后就此结束。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">所以，截至目前：YSI 1.0、YSF 1.0、YSI2 1.0、YPI 1.0，到此为止，我不干了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言：Kye 正在研究一种过滤"修改版本服务端"并将其列入黑名单的机制——我可能会发布一个不自动修改版本号的 YSF 版本，这样用它的人就不会因为我的失误被连坐；请留意这里的动态（我可能也会顺带加入拾取物修复，但不会保留只读变量相关的功能）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言二：IRC 才是王道，我还活跃在 GTANet 的大量频道里，包括 #YSI 和 #Y_Less，欢迎来找我。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言三：不知道 MTA 的源代码长什么样……</span>"</blockquote>
<br />
——Y_Less，2009年1月，TMS Forums<br />
<br />
<hr class="mycode_hr" />
<br />
这篇声明在社区引发了强烈反响。数日后，经社区压力，Y_Less 得以解封，YSF 在不修改只读变量的前提下被允许继续使用。从表面上看，风波平息了。<br />
<br />
但那句"附言三"——"不知道 MTA 的源代码长什么样"——如今读来，已不再只是一句无心之语。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第三卷：停滞、管控与分歧（2014–2019）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第八章　0.3.7 之后的沉寂（含源码泄漏事件）</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2015 年 5 月 1 日</span>，SA:MP <span style="font-weight: bold;" class="mycode_b">0.3.7</span> 发布。此后，Kalcor 在新功能层面的开发近乎陷入停滞。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年前后</span>，Kalcor 发布了 <span style="font-weight: bold;" class="mycode_b">SA-MP 0.3.DL</span>——一个支持服务端向玩家客户端推送自定义模型（Download Content）的版本。这是社区长期以来最渴望的功能之一，玩家们可以在 SA:MP 服务器上看到服务器自定义的车辆、皮肤、物件模型，而不再局限于原版游戏资产。<br />
<br />
然而 0.3.DL 的推出并不顺利：安全问题（恶意服务器可能推送损坏的模型文件危害客户端）和与旧版 0.3.7 的兼容性问题，使得相当一部分服务器拒绝迁移。SA:MP 社区自此一分为二，0.3.7 阵营与 0.3.DL 阵营长期并存。<br />
<br />
这种分裂令社区感到困惑与沮丧。有人多次在论坛呼吁将两个版本合并，但得不到任何回应。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">源码泄漏事件（2010 年起源，2018 年爆发）</h4><br />
<br />
在 0.3.DL 引发社区分裂的同一时期，另一条隐患也终于浮出水面。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年 11 月 15 日</span>，SA:MP 官方论坛上出现了一篇由用户 Kshishtof 发起的帖子，标题是《SA-MP 源代码泄漏》。帖子指向一个名为 <span style="font-weight: bold;" class="mycode_b">rw-mp.net</span> 的项目，该项目被认为是基于泄漏的 SA:MP 源代码构建的独立多人联机分支。<br />
<br />
帖子引发了社区的激烈讨论。一部分人对 rw-mp 持同情甚至欣赏的态度，认为它至少在做 SA:MP 不再愿意做的事；另一部分人则斥之为对原作的窃取与侮辱。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年 11 月 16 日</span>，Kalcor 亲自在帖子中出现，发表了两段回应。第一段揭示了这批泄漏源码的来历：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"SA:MP 的源代码于 2010 年被一名法国人从我们的服务器上黑掉，目的是为 IV:MP 这个 mod 服务。我记录并上报了这次入侵。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">GitHub 上大约有十个副本。我一直没有把它们下架，是因为提交 DMCA 申诉需要将我的真实姓名录入 GitHub 的公开 DMCA 数据库，否则就得花钱请律师。"</span></blockquote>
<br />
第二段话语气更为强硬，是一封事实上的法律警告：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"0.2.5 的源代码是通过计算机入侵从我们的服务器上盗取的。任何基于该代码发布软件的人，都涉嫌与我们作对的刑事共谋。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">SA:MP 所使用的 RakNet 版本并非开源，而是通过付费许可证使用的。BASS 音频库同样是付费许可证使用的。整个游戏 mod 社区正在被那些删除原始版权信息、将他人成果冒充自己作品重新发布的蠢货所伤害。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我给他们几天时间关闭并停止任何与 SA:MP 相关的活动。"</span></blockquote>
<br />
——Kalcor，SA:MP 官方论坛，2018 年 11 月 16 日 原帖：https://sampforum.blast.hk/showthread.php?tid=660866<br />
<br />
这段声明揭示了几个此前从未公开过的重要事实：<br />
<br />
其一，SA:MP 源码泄漏的根源远早于 2018 年——<span style="font-weight: bold;" class="mycode_b">2010 年</span>就已经发生了一次有据可查的服务器入侵事件，是一名法国黑客为了支持 IV:MP（GTA IV 的多人 mod）而实施的。这与 Kalcor 在 2019 年 pawn.wiki 文章中所说的"R* 给 MTA 的代码被用于攻击 SA:MP"形成了完整的脉络——他所遭受的代码安全威胁，来自不止一个方向。<br />
<br />
其二，Kalcor 之所以始终不对 GitHub 上的泄漏副本提交 DMCA，并非不知情或不在意，而是出于一个极具讽刺意味的现实顾虑：提交 DMCA 需要将他的真实姓名公开录入数据库，而他不愿意这样做。源码在网上流传的同时，他本人却因为隐私顾虑而放任不管。<br />
<br />
这次事件在社区中引发了新一轮关于"Kalcor 应不应该直接将 SA:MP 开源"的讨论。部分社区成员认为，既然源码已经通过非法途径广泛流传，不如主动开源，至少可以让社区以合法的方式参与改进。这个声音 Kalcor 听到了，但他的答案，在两年后的 pawn.wiki 那篇文章里已经说得很清楚。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第九章  Kalcor 眼中的历史：MTA 的旧账、R\* 的源码，与闭源的真实理由</h4><br />
<br />
编年史至此已经写了许多关于 Kalcor 的事——他的决策、他的封号、他的沉默——却始终没有给他一个真正完整的出场。他是从哪里来的？他为什么那样做？他拒绝开源的理由究竟是什么？<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2019 年 10 月 25 日</span>，就在 Kalcor 于 SA:MP 官方论坛发布某条帖子后不久，俄语 Pawn 开发者社区 pawn.wiki 上出现了一篇由用户 <span style="font-weight: bold;" class="mycode_b">m1n1vv</span> 整理、转述并翻译的长文，标题是《SA-MP 0.3.9 与 Kalcor 的新故事》。这篇文章完整记录了 Kalcor 这篇帖子的核心内容——那是迄今为止他对自己技术履历与闭源立场最完整、最直接的一次亲口陈述。<br />
<br />
以下是 Kalcor 在那篇帖子中所说的全部内容，经 m1n1vv 翻译并整理，原文以俄文发布于 pawn.wiki：<br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">那么，请允许我给你们讲一段历史。结论由你们自己得出。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2003 年，在 MTA 的 IRC 频道上待了一周之后，我被邀请加入 MTA:VC（Vice City Multiplayer）的开发。几个月后，我晋升为 MTA 的首席开发者。以下是一张截图，记录了我和 Si|ent 一起尝试让 MTA:VC 中的船只同步正常工作的画面，日期是 2003年12月31日。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我是 MTA:Blue 的少数开发者之一——这是 MTA 针对罪恶都市的新版本。那时候除我之外，大多数人都被现实生活拖住了。我开发了玩家上下文切换同步系统，并引入了 RakNet 库。同样的系统至今仍被 SA-MP 和 MTA:SA 所使用。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">这种处境让我感到沮丧——一周又一周过去，只有我一个人在提交代码，而论坛上却有一堆"开发者"在大谈特谈一切将会如何运作。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">于是我离开了 MTA 的开发。在我离开期间，另一个叫 eAi 的人加入了项目，开始研究我的代码，试图弄清楚它是怎么工作的。至少有人在做事了——他的方式是去主动联系各方，于是他通过 ICQ 找到了我，还找到了 R</span>（Rockstar Games）开发者的电子邮件地址，并与他们取得了联系。*<br />
<br />
<span style="font-style: italic;" class="mycode_i">那时候我对 GTA 多人联机并不感兴趣。我有一个乐队，还参与了 ipodlinux 等项目，但 eAi 似乎非常热衷于推动 MTA:Blue 取得进展。于是我重新加入了项目，持续了几个月。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">以下是 2004年底 MTA:Blue 的公开宣传页面存档。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">正是这件事导致了我和 MTA 其他开发者之间的决裂：我想要构建一个服务端系统——就像 VC-MP 的 ini 脚本系统，以及 SA-MP 中基于 Pawn 脚本的服务端系统；而 MTA 的开发者们则想要客户端扩展，就像那个宣传页面上描述的那样。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2005年初，我再次离开了 MTA。就在那段时间，R</span> North 在 PS2 上发布了 GTA:SA，并正在开发 PC 版本。eAi 与 R<span style="font-style: italic;" class="mycode_i"> 的技术总监有联系，还通过 ICQ 向我炫耀说，他拿到了大量 GTA:SA 源代码的头文件。我注意到，MTA 的开发者们似乎打算放弃罪恶都市版的 MTA:Blue，转战 GTA:SA。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不相信 MTA 及其开发能力，2005年中，我开始独立开发自己的多人联机。我发布了 VC-MP，基于玩家上下文切换和 RakNet。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">随后，我与 jax、spooky 以及其他一些人一起开发了 SA-MP。它远比之前的 mod 庞大得多。我们与 GTANet/GTAForums——最大的 GTA 非官方粉丝站——有着较为密切的联系，这使我们获得了更大的知名度。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">到 2008 年，SA-MP 的玩家数量是 MTA 的 10 到 20 倍。MTA 的开发者们感到在这种竞争环境下已无法与之抗衡，于是他们公开了自己的源代码。MTA 的开发者们从未询问过我或任何前任开发者，是否可以公开这些源代码。他们声称所有东西都已经被重写了，但事实并非完全如此。时至今日，MTA:SA 中仍然有我的代码。我没有费心去追究他们，因为他们看起来太蠢了——但我猜，这里那些呼吁公开 SA-MP 源代码的人，很可能是受到了 MTA 的启发，尽管他们或许不应该这样。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">而这就是现在正在发生的事：我为 MTA 开发的"游戏"代码，以及 R\</span> 给 MTA 的源代码，正在被移植进 mod\<span style="font-style: italic;" class="mycode_i">so\</span>beit——一款流行的 SA-MP 外挂工具。*<br />
<br />
<span style="font-style: italic;" class="mycode_i">你们知道这意味着什么吗？R\</span> 给 MTA 的那部分源代码，有相当大一部分被用来——攻击 SA-MP！*<br />
<br />
<span style="font-style: italic;" class="mycode_i">从一小批相当专业的 MTA 开发者起步，这件事已经演变成了极度肮脏的东西。那些想要摧毁 SA-MP 的人，对于是否违法毫不在意。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">看起来，任何被公开的源代码都可能被用来攻击 SA-MP——尽管它本可以被用于提供有价值的更新。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">公开 SA-MP 源代码这个决定，归根结底取决于：我们是否仍然处于这种充满敌意的环境中——人们在攻击我、想要攻击 SA-MP——还是这一切已经成为过去。我想说，这取决于 mod 的规模以及对外挂工具的需求程度。封闭源代码让我可以在每次发布时重新洗牌所有内部结构，使大量外挂工具失效。SA-MP 的许多"安全"更新，实质上就是我在重新排列数据，以清除现有的外挂工具。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">最终，SA-MP 将会走到这样一个时刻：所有人都彼此友善和尊重，外挂与欺诈变得罕见——但届时玩家数量将极为稀少，我们中的大多数人也已不在了。</span></blockquote>
<br />
——Kalcor，2019年10月，SA:MP 官方论坛<br />
（由 m1n1vv 转述并整理，经 Типичный Скриптер 译为俄文，发布于 pawn.wiki，2019年10月25日）<br />
<br />
<hr class="mycode_hr" />
<br />
这篇陈述，是理解 Kalcor 其人与其决策的关键文献。<br />
<br />
它第一次完整地揭示了他的来历：他不是凭空出现的 SA:MP 创始人，而是一个从 MTA 内部出走的人。<span style="font-weight: bold;" class="mycode_b">2003 年至 2005 年间，他在 MTA 团队中担任首席开发者</span>，亲手构建了玩家同步系统与 RakNet 架构——而他愤而离开，正是因为他坚持的"服务端脚本系统"方向遭到其他成员的反对。SA:MP 的诞生，某种程度上是一次对 MTA 的报复性创业。<br />
<br />
它也第一次给出了 Kalcor 拒绝开源的真实逻辑：他不是在藏私，也不是单纯的控制欲作祟——在他看来，<span style="font-weight: bold;" class="mycode_b">闭源是他对抗外挂工具的核心武器</span>。他承认 SA:MP 的许多所谓"安全更新"，实质只是重新排列内部数据结构，使依赖固定内存地址的外挂工具在新版本中失效。一旦开源，这条防线便彻底坍塌。<br />
<br />
而他与 MTA 之间的积怨，在这篇文章里也首次有了完整呈现：他认为 MTA 在开源自己的代码库时，从未征得他这位最初作者的同意；更令他愤怒的是，他随后发现，R\* 曾向 MTA 提供的部分 GTA:SA 源代码头文件，辗转流入了 SA:MP 外挂工具的制作者手中——成为攻击 SA:MP 的武器。这份偏执与防御，贯穿了他此后对待社区和开源请求的所有态度。<br />
<br />
这篇发布于 2019 年 10 月的文章，距 Kalcor 宣告放弃 SA:MP 仅剩不到一个月。这是他在离开之前，最后一次试图解释自己。<br />
<br />
<hr class="mycode_hr" />]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">圣安地列斯联机二十年：SA:MP 与 open.mp 历史</h2><br />
<br />
2026 年。GTA6 即将在今年 11 月发售，新的时代正在敲门。<br />
<br />
也是在这一年，《侠盗猎车手：圣安地列斯》PC 版上市整整二十年，SA:MP 的第一个可玩版本也已走过二十个年头。<br />
<br />
一座从未被设计为联机游戏的城市，有人在这里认识了一辈子的朋友。有人在这里第一次学会了写代码。有人在角色扮演服务器里扮演一个JC或一个黑帮头目。有人在一个无聊的下午打开了游戏，然后就再也没有那个下午了。<br />
<br />
SA:MP 从来不是一个精致的产品。它是一群人强行塞进一款单人游戏里的多人世界。它有数不清的 bug，有争议不断的管理者，有过漫长的停滞与分裂——它也有 open.mp，有一批不肯让它消失的开发者，有如今可以在手机上随时上线的客户端，不管你还记不记得服务器的 IP，不管你当年是服主、脚本开发者，还是只是一个普通的玩家——你在这里的时间是真实的。<br />
<br />
GTA6 会带来它的世界。但圣安地列斯的街道，还在。服务器还在跑，玩家还在上线，有人还在第一次输入 /register。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">前言</h3><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>本文以客观事实为准绳。所有关键事件、人物声明、原始帖文，均完整收录于正文之中，不以外部链接替代实质内容。链接仅作考证索引，供读者溯源查验，不构成叙述本身的一部分。<br />
<br />
凡引用原文处，均以引用块标注，并注明来源与时间。凡转述处，均忠实于原意，不加渲染，不作价值评判。<br />
<br />
这是一部关于热爱、控制、背叛与重建的故事，也是一个游戏社区在二十年间走过的记录。</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">卷首语：一个不该有多人模式的游戏</h3><br />
<br />
2004 年 10 月 26 日，《侠盗猎车手：圣安地列斯》（Grand Theft Auto: San Andreas）在 PlayStation 2 平台正式发售。2005 年 6 月 10 日，PC 版本上市。<br />
<br />
这款游戏从未被设计为多人联机。Rockstar Games 为它设计了一个宏大的单人故事——主角 CJ 在帮派、JC与腐败之间挣扎求生，横跨三座城市、一片乡野。游戏没有联机大厅，没有服务器浏览器，没有任何供多人游玩的接口。<br />
<br />
然而在 GTA 模组社区里，有一批人从不接受"这不可能"这个答案。<br />
<br />
他们是一群来自世界各地的年轻人，大多数有着普通的日间生活——学生、程序员、上班族——他们一点一点地撬开这款游戏的外壳，试图将它改造成一个可以容纳数百人同时在线的多人世界。<br />
<br />
这便是 SA:MP 的起点。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第一卷：诞生（2004–2006）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第一章　从 Vice City 到 San Andreas</h4><br />
<br />
在《圣安地列斯》PC 版尚未发售之前，GTA 模组社区已经有人在为《GTA 罪恶都市》（Vice City）制作多人联机改造，这个项目被命名为 <span style="font-weight: bold;" class="mycode_b">VC:MP（Vice City Multiplayer）</span>。<br />
<br />
领导这支早期团队的，是一个网名叫 <span style="font-weight: bold;" class="mycode_b">kyeman</span> 的开发者，真名 <span style="font-weight: bold;" class="mycode_b">Kye Bitossi</span>。他在 GTA 模组社区中颇有声望，是公认的技术核心人物。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2005 年 4 月初</span>，kyeman 在全球最大的 GTA 社区论坛 <span style="font-weight: bold;" class="mycode_b">GTAForums</span> 上发布了一篇帖子，正式宣布 SA:MP 项目的存在。帖子标题是：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"[WIP] SA-MP: Multiplayer for San Andreas PC"</span><br />
——kyeman，GTAForums，2005年4月3日</blockquote>
<br />
消息一出，社区立刻沸腾。预告视频和截图开始在各大 GTA 论坛流传，项目的小型社区论坛在尚未开放任何测试的情况下，已吸引了约 <span style="font-weight: bold;" class="mycode_b">120 名注册用户</span>。<br />
<br />
公开 beta 测试期间，服务器承载能力远不及涌入的测试者数量，进入测试服务器需要排队等候，等待时间往往很长。这种盛况，是对整个项目最好的背书。<br />
<br />
进入开发团队的成员，来自 GTA 模组社区的各个方向，过去的SA-MP 0.2开发者和测试者包括：kyeman、spookie、Y_Less、mike、jax、Mike、Cam、adamcs、bakasan、Born Acorn、Dalpura、Damian、Delfi、dexx、DrAke&#36;、Drift、ECLiPSE、f3llah1n、him selfe、illspirit、littlewhitey、MrJax、njr1489、Posty、PsYcHoGoD、Shizz、Simon、sockx、squiddy、Static、steve-m、The Azer、Trix、Wacko、XcR、[ULK]Crack，其中许多人既是开发者也是测试员。<br />
<br />
他们大多是业余爱好者，利用业余时间共同推进这个无人出资的项目。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第二章　合作模式的争议与团队第一次动荡</h4><br />
<br />
然而，SA:MP 从一开始便并非一片和谐。<br />
<br />
开发团队内部，关于游戏核心玩法的方向，爆发了一场至今仍被一些老玩家提起的根本性争论：<br />
<br />
一部分人主张将 SA:MP 建设为一款<span style="font-weight: bold;" class="mycode_b">合作模式（Co-op）</span>游戏，设想最多 6 名玩家共同游玩，保留完整的 NPC 行为、警察追捕系统与任务流程，让多人体验尽可能接近单人游戏的质感；<br />
<br />
另一方，以 kyeman 为首，坚持将其建设为一个能够容纳大量玩家同时在线的<span style="font-weight: bold;" class="mycode_b">大规模死亡竞技（Deathmatch）</span>式多人服务器。<br />
<br />
这场分歧并未在内部平息，而是溢出到了 GTANet 社区论坛，引发了玩家的大量公开讨论与批评，负面声音之多，令整个项目团队承受了巨大压力。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2005 年 9 月 18 日</span>，kyeman 在持续的内外压力下，宣布因个人事务无暇继续领导项目，将主导权移交给团队二号核心开发者 <span style="font-weight: bold;" class="mycode_b">spooky</span>。<br />
<br />
spooky 接手后，将项目更名为 <span style="font-weight: bold;" class="mycode_b">GTA:Multiplayer（GTA:M）</span>，以示风格与管理方式的转变。<br />
<br />
然而，约一个月后，kyeman 重新归队。合作模式方案在此期间被彻底搁置，项目名称最终改回 <span style="font-weight: bold;" class="mycode_b">San Andreas Multiplayer（SA:MP）</span>，方向确定为大规模多人在线游戏。<br />
<br />
关于"Grand Theft Auto"字样是否应出现在项目名称中，团队在命名时也有过考量——使用 Rockstar 的商标可能引发法律风险，最终以缩写"SA:MP"作为正式名称，在一定程度上规避了这一问题。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第三章　2006 年：第一个可玩版本</h4><br />
<br />
在经历了那段动荡之后，SA:MP 于 <span style="font-weight: bold;" class="mycode_b">2006 年</span> 发布了第一个向公众开放的可玩版本。<br />
<br />
从技术层面看，这是一项相当可观的成就：开发者们在完全没有官方支持的前提下，用逆向工程的方式强行将联机功能"嵌入"进一款从未被设计为多人联机的作品，使其能够支持最多 <span style="font-weight: bold;" class="mycode_b">1000 名玩家</span>同时在线，在同一片虚拟的圣安地列斯地图中驾车、射击、竞速。<br />
<br />
服务器使用 <span style="font-weight: bold;" class="mycode_b">Pawn</span> 作为脚本语言，服务器主可以自行编写游戏模式（GameMode）与过滤脚本（FilterScript）。这一设计赋予了整个生态极高的开放性——任何人只要学会 Pawn，就可以在圣安地列斯的地图上建造出属于自己的世界。<br />
<br />
0.2.2 版本是这一阶段的代表版本，也是现存有据可查的最早可玩 SA:MP 版本记录之一。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第二卷：黄金时代与暗流（2006–2009）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第四章　版本迭代与社区的兴盛</h4><br />
<br />
2006 年至 2014 年，是 SA:MP 最活跃的开发阶段。Kalcor（此时 kyeman 已开始使用这个网名）陆续发布了一系列重要版本：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">0.2 系列</span>（2006–2008）期间，SA:MP 奠定了基本架构，确立了 Pawn 脚本语言作为游戏模式开发的标准。这段时间并非全然顺利——一次大规模安全漏洞爆发，险些让整个团队就此放弃。而最终让他们坚持下来的，是一份在线请愿：短短时间内，数以千计的玩家签名支持 SA:MP 继续存在。这份来自社区的温度，让开发者重新燃起了动力。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">0.3a</span>（约 2010 年）是 SA:MP 历史上最具里程碑意义的版本之一。单服务器玩家上限从原来的数百人扩展至 <span style="font-weight: bold;" class="mycode_b">500 人</span>（后续版本更高），引入了鼠标驱动的记分板与聊天界面，增加了可编程的 NPC 机器人系统（允许服务器创建可驾驶火车、飞机的脚本机器人），网络同步质量大幅改善。<br />
<br />
此后数年，<span style="font-weight: bold;" class="mycode_b">0.3c、0.3d、0.3e、0.3x、0.3z</span> 相继发布，带来了音频流媒体支持、延迟补偿模式、自定义对象渲染距离、新的安全更新等功能。每一个版本的发布，都在 SA:MP 官方论坛的"新闻与更新"板块留下了一条由 Kalcor 亲自发布的公告。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2015 年 5 月 1 日</span>，Kalcor 发布了 SA:MP <span style="font-weight: bold;" class="mycode_b">0.3.7</span>，这是 SA:MP 有史以来最后一个带有实质性新功能的正式版本。0.3.7 新增了超过 500 个物体 ID（含特技物件与地形物件）、界面字体大小调整选项、若干新版警察皮肤、服务端对车门与车窗的控制权、为未标记警车添加警报灯的能力，以及一个简单的静态 NPC actor 系统。<br />
<br />
这个版本在此后数年间成为整个 SA:MP 生态的事实标准，直至今日仍是服务器主最常使用的版本。<br />
<br />
与此同时，这个社区在技术之外也在野蛮生长。<span style="font-weight: bold;" class="mycode_b">角色扮演（RP）服务器</span>在这段时期走向成熟，玩家们在 SA:MP 的世界中建构起了拥有经济系统、帮派政治、法律体系的虚拟社会。来自世界各地大型服务器先后崛起。SA:MP 不再只是一个小众模组，它已经成为一个真实的、活跃的、跨越语言与国境的国际社区。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第五章　Y_Less 的双重身份与 YSI 的诞生</h4><br />
<br />
在 SA:MP 的所有社区开发者中，有一个人的名字几乎是无可回避的：<span style="font-weight: bold;" class="mycode_b">Y_Less</span>，真名 Alex Cole。<br />
<br />
Y_Less 最初以 beta 测试员的身份加入 SA:MP 团队，随后正式成为开发团队成员，主要负责 Pawn 脚本语言相关的功能开发。然而，他与 Kalcor 之间的分歧，从他正式入队的第一天起便已埋下。<br />
<br />
用 Y_Less 自己后来的话说：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"加入开发团队之后，我开始开发 Pawn，但我发现自己能做的事被 Kye 严重限制。我们之间存在重大的意见分歧：他认为 90% 的开发精力应该投入同步（sync）工作，Pawn 几乎只是顺手提供一点额外功能的附属品。而我认为，虽然同步很重要，但他已经把同步覆盖得很好了，我更想专注于 Pawn 的功能与函数。然而他是老板，说了算，严重限制了我被允许做的事。此外，他有个坏习惯——每次版本迭代之后，只要在某个细枝末节的测试中有任何不稳定，就要来指责我，尽管测试本来就是我们有 beta 测试团队的原因。不用说，这不是一个好的工作环境，但我仍然喜欢 SA:MP 这个产品本身。"</span></blockquote>
<br />
在这种压抑的工作环境中，Y<span style="font-style: italic;" class="mycode_i">Less 于 <span style="font-weight: bold;" class="mycode_b">2007 年</span> 开始独立开发 <span style="font-weight: bold;" class="mycode_b">YSI（Y</span>Less' Server/Script Includes）</span>。<br />
<br />
YSI 最初是他此前若干工具的整合与升级，同时也是他在 Kalcor 的管控边界之外，以纯 Pawn 脚本的方式，实现他认为 SA:MP 脚本系统应当具备的扩展能力。他在这个过程中也加入了一些辅助性的函数，例如 player objects 功能，最初是专门为了支撑他的对象流式传输器 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">e_objects</code> 而写的。<br />
<br />
用 Y_Less 自己的话说：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"2007 年，我开始开发 YSI。这部分是对若干早期工具的更新与整合，部分也是在 Kye 的控制之外，以 Pawn 能力范围内的方式带来我认为 Pawn 所需的扩展功能——尽管以纯 Pawn 来做，能实现的事情自然有其上限。YSI 成为我的主要项目这一事实惹恼了 Kye，因为他认为这说明我没有把时间花在 SA:MP 上，尽管我实际上一直都在。"</span></blockquote>
<br />
YSI 涵盖了命令处理（y<span style="font-style: italic;" class="mycode_i">commands）、玩家迭代器（y</span>iterate）、钩子机制（y<span style="font-style: italic;" class="mycode_i">hooks）、INI 文件读写（y</span>ini）、多语言支持（y_languages）等数十个子模块，是当时 SA:MP 社区功能最全面、使用最广泛的第三方脚本库。<br />
<br />
至于"YSI"到底代表什么，连 Y_Less 本人也说不清：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"最初的想法是'Y[i]Less' Server Includes'，但 Server 和 Script 经常被混用，而且现在参与的开发者不止 Y</span>Less 一人，所以'Y'就变成了一个递归缩写，代表'YSI'本身。"[/i]</blockquote>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第六章　2008 年底：GTANet 风波与团队大出走</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2008 年底</span>，SA:MP 开发团队内部爆发了一场与 GTANet 社区相关的严重矛盾。关于这场风波的具体细节，现有的公开资料已难以完整还原，但其结果是清晰且影响深远的：<span style="font-weight: bold;" class="mycode_b">Mike、aru 和 Peter</span> 等多名核心开发者相继以此为由宣布离队。<br />
<br />
Y_Less 在日后的声明中这样描述这段经历：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"2008 年底，GTANet 风波爆发，Mike、aru 和 Peter 因此离开，我也因为团队氛围实在太差，加之大家都在走，便也一同离开了。"</span></blockquote>
<br />
这一波出走之后，SA:MP 的开发工作几乎完全落回 Kalcor 一人肩上，这进一步强化了整个项目对他个人的高度依赖，也使得社区的任何集体意见都更加难以产生实质影响。<br />
<br />
然而事情并未就此平息。Y_Less 出走后，出于他自己也说不清的原因，重新回归了团队。他在后来的声明中写道：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"不知为何，真的记不清了，我之后又重新加入了团队。那时候 Kye 想要关闭 SA:MP，我提出愿意接手，他拒绝了。然后我再次退出——不是因为我没接手到，这一点需要说明——于是 Kye 决定封禁我的论坛账号，而且不只是封号，而是彻底抹除——删掉了我所有的帖子。这意味着原版《实用函数》帖没了，旧版 FAQ 帖没了，大量迷你教程没了，《Pawn 关键词》帖也没了——我只有在非常必要的时候才发帖，那些帖子都有其存在的价值，它们的消失被大量用户注意到并提出了强烈抗议。"</span></blockquote>
<br />
这便是 2008 年底那次"第一次封号"事件的始末——相对低调，但已经是一个信号。真正震动整个社区的风波，还在后面。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第七章　2009 年 1 月：YSF 封号事件</h4><br />
<br />
从团队再度离开之后，Y<span style="font-style: italic;" class="mycode_i">Less 没有停止为社区创作工具。他开发了 <span style="font-weight: bold;" class="mycode_b">YSF（Y</span>Less' Server Fixes）</span>——一个以服务端插件形式存在的 bug 修复集合。<br />
<br />
YSF 的设计理念很简单：SA:MP 有很多 Kalcor 长期忽略或拒绝修复的 bug，既然拿不到源代码，那就通过内存操作（memory patching）的方式，在运行时强行修正这些行为。这个方法技术上相当复杂，但效果立竿见影。<br />
<br />
Y_Less 事后这样形容 YSF：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"YSF 是我最成功的项目，因为它做到了所有人都想要的事。它本质上是一个更新版的服务端——人们总是渴望新版本带来修复和新功能，功能方面已经有其他插件（包括 YSI 插件）覆盖了，所以我选择了修复这条路（以及一些小功能——显然正是这些小功能引发了麻烦）。"</span></blockquote>
<br />
YSF 在社区中广泛流传，大量服务器安装并使用它。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">2009 年 1 月 19 日</span>，事件的直接导火索被点燃。<br />
<br />
当天，Kalcor 私信给 Y_Less，表达了对 YSF 的不满。他的顾虑有两项：<br />
<br />
第一，他认为 YSF 可能与 SA:MP 未来版本产生脚本兼容性问题；第二，他认为 YSF 代码中存在与 SA:MP 服务端源代码相似的内容，以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">functions.cpp</code> 中的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">IsNickInvalid</code> 函数为例。<br />
<br />
Y_Less 对此逐一作出回应。关于兼容性问题，他指出 YSF 恰恰是在让脚本对未来版本<span style="font-weight: bold;" class="mycode_b">更加</span>兼容，而非相反；关于源代码问题，他坦言：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"这实际上并非盗用，但我承认看起来非常相似，因为它做的事情完全一样，而且也不是什么复杂的函数，我懒得争，就直接把它彻底重写了。"</span></blockquote>
<br />
他还顺带提到，Kalcor 自己曾主导过一些令他反对的修改决策——比如改变服务端的默认运行风格，以及在 0.3 版本中移除对象（最后改为以 IPL 文件形式替代，而非完全移除）——当初他的反对意见被 Kalcor 直接否决。<br />
<br />
双方讨论的最终结果，表面上是达成了共识：Kalcor 表示接受了 Y_Less 的解释，YSF 可以继续存在。<br />
<br />
然而，Y_Less 第二天登录论坛，发现自己已经被封号。<br />
<br />
他在后来的声明中还原了这段过程：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"就在我们讨论同意 YSF 可以继续存在，之后，他发现了 SetServerRule，并意识到它可以用来修改只读控制台变量——比如服务器版本号——从而让人们能够违反 SA:MP 服务条款第（g）条：'你不得人为地增加玩家数量，或向 SA:MP 查询机制提供虚假信息。'"</span></blockquote>
<br />
Kalcor 认为，Y_Less 在 YSF 中提供了这样一个功能，就等同于为违规行为提供了手段，因此必须承担责任。<br />
<br />
封号通知的原文如下（Y_Less 在声明中直接引用）：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>*"抱歉 ssǝן‾ʎ，你已被禁止使用本论坛！  <br />
滥用前开发者身份。入侵服务器，并为他人违反服务条款提供手段。"*</blockquote>
<br />
封号的同时，Kalcor 再次<span style="font-weight: bold;" class="mycode_b">删除了 Y_Less 在 SA:MP 官方论坛上的全部历史帖子</span>。大量教程、工具发布帖、FAQ 就此永久消失，众多用户注意到这些帖子的蒸发，并提出了强烈抗议。<br />
<br />
Y_Less 随即在社区发布了一篇完整声明，以下是他原文的核心段落：<br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"基本上，我因为 YSF 被 SA:MP 官方论坛封号了！</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">历史：</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">200x 年（实在记不清了），在与 Spookie 讨论之后，我以 beta 测试员的身份加入了 SA:MP 团队——那还是第一次公开 beta 之前的事——并开始编写 Pawn 相关的代码。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">没过多久，我正式加入了开发团队，专注于 Pawn 的开发，但我很快发现自己受到 Kye 的诸多限制，做不了想做的事。我们之间存在重大分歧：他认为 90% 的开发精力应该用于同步（sync），Pawn 只是顺手提供一点额外功能的附属品；而我认为，虽然同步很重要，但他已经把同步做得很好了，我更想把时间花在 Pawn 的功能扩展上。然而他是老板，说了算，严重限制了我能做的事。更让人受不了的是，他有个习惯——每次版本迭代后，只要在某个犄角旮旯的测试里出了任何小问题，就要来责怪我，哪怕我们有 beta 测试团队本来就是为了发现这些问题的。说实话那不是一个好的工作环境，但我还是喜欢 SA:MP 这个产品本身。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2007 年，我开始开发 YSI。这一方面是对此前一批旧项目的整合升级，另一方面也是想在 Kye 的管控之外，以纯 Pawn 脚本的方式实现我认为 Pawn 所需要的扩展功能——尽管能做到的事情有限，毕竟纯 Pawn 本身有其局限（我确实额外添加了一些辅助函数，比如 player objects 功能完全是为了写我最初的对象流式传输器 e\_objects 而专门实现的）。YSI 成为我的主要项目这件事惹恼了 Kye，因为他觉得我没有把时间花在 SA:MP 上——尽管我实际上一直都在。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2008 年底，GTANet 社区风波爆发，Mike、aru 和 Peter 因此离队。我也因为团队氛围实在太差，加上大家都在走，便也跟着离开了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不知为何（真的记不清了），我之后又重新回归了团队。那时候 Kye 想要关闭 SA:MP，我主动提出愿意接手，他拒绝了。然后我再次退出——不是因为没接手到，这一点需要说清楚——于是 Kye 决定封禁我的论坛账号，而且不只是封号，而是彻底抹除，删掉了我所有的帖子。这意味着原版《实用函数》帖没了，旧版 FAQ 帖没了，大量迷你教程没了，《Pawn 关键词》帖也没了——我只有在非常必要的时候才会发帖，那些帖子都有其价值，它们的消失被大量用户注意到并提出了抗议。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不管怎样，我还是喜欢 SA:MP 和这个社区本身（至少喜欢其中的一部分），所以我还是留了下来（现在回想起来真不知道当时为什么，深感后悔），并继续努力让 SA:MP 变得更好——尽管 Kye 的存在让这件事很难。我继续开发 YSI、写教程和帮助帖，后来又创作了 YSF。YSF 大概是我最成功的项目了，因为它做到了所有人都想要的事。它本质上就是一个改进版的服务端——人们总是渴望新版本带来修复和新功能，功能方面已经有其他插件（包括 YSI 插件）覆盖了，所以我选择了专注于修复这条路（以及一些小功能——显然正是这些小功能引发了这次麻烦）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">总之，Kye 和我一般都各自行事、互不干扰（至少我是这么以为的），有一段时间相安无事。直到 2009 年 1 月 19 日，我收到了 Kye 的消息，说他不太喜欢我在 YSF 里做的事。经过一番交涉，才明白他的顾虑在于：YSF 可能与未来版本的脚本产生兼容性问题（这话从他嘴里说出来真是讽刺——我当初就反对过他把默认运行方式改掉，以及 0.3 版本里删除对象的决定，但他否决了我；对象最后是改成了 IPL 文件的形式，而非完全删除，但也没有了 per-player objects，至少我最后听到的消息是这样）。此外，他还质疑 YSF 里有 SA:MP 服务端的源代码——他举的例子是 functions.cpp 里的 IsNickInvalid 函数。这个函数其实不是照抄的，但我承认看起来确实很像，毕竟它做的事完全一样，而且也不是什么复杂的函数，我懒得争，就直接把它彻底重写了。在我指出 YSF 并不会造成兼容性问题（恰恰相反，它让脚本对未来版本的兼容性更好），并同意日后不再使用 SA:MP 源代码（尽管我此前一直在刻意避免这样做）之后，他让步了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">第二天我上论坛，发现自己已经被封了……</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">原来在我们达成共识之后，他又发现了 SetServerRule 这个功能，意识到它可以用来修改只读控制台变量（比如服务器版本号），从而让人能够违反 SA:MP 服务条款第（g）条：'你不得人为地增加玩家数量，或向 SA:MP 查询机制提供虚假信息。'</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我解释说，我本人根本没有这样做，这个功能的设计初衷是好的，只是不幸被人滥用了。我甚至想过反问他：他提供论坛和 IRC 频道，同样也给人们提供了违反条款（c）（d）条的方式，按他的逻辑，他也应该被封号——但我懒得说了。封号通知的原文是：</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">'抱歉 ssǝן‾ʎ，你已被禁止使用本论坛！滥用前开发者身份。入侵服务器，并为他人违反服务条款提供手段。'</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">所谓'滥用'，是指我用它改善了所有人的游戏体验；所谓'入侵服务器'，是指我修复了它；所谓'提供手段'，意思是人们可以拿我提供的工具做坏事——但这不代表我支持或认可这种行为，这只是一个有用工具所带来的无奈副作用。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">Kye 说 YSF 的事已经覆水难收，他只能发布新版本来屏蔽它，伤害已经造成，它已经广泛传播，人们正在用它黑自己的服务器，没有人能阻止，所以我必须被封。我回应说，如果我没被封，我本来可以发布最新版本，在修复拾取物 bug 的同时，加入对规则的只读标志检查——虽然这无法彻底解决问题，但能大幅减少滥用，因为几乎没有人会主动把它改回旧方式，大多数人会为了这个重要修复而升级。说到这里，他就不再回复我了（我觉得他是意识到自己断掉了快速、高效解决这件事的唯一合理途径，然后不想认账了——如果不是这样，我欢迎他来回应）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">总之，我决定把当时正在写的那段代码（YSI 的示例脚本）收个尾，毕竟我还是喜欢使用 YSI 的那些人，上传最终版本，然后就此结束。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">所以，截至目前：YSI 1.0、YSF 1.0、YSI2 1.0、YPI 1.0，到此为止，我不干了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言：Kye 正在研究一种过滤"修改版本服务端"并将其列入黑名单的机制——我可能会发布一个不自动修改版本号的 YSF 版本，这样用它的人就不会因为我的失误被连坐；请留意这里的动态（我可能也会顺带加入拾取物修复，但不会保留只读变量相关的功能）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言二：IRC 才是王道，我还活跃在 GTANet 的大量频道里，包括 #YSI 和 #Y_Less，欢迎来找我。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言三：不知道 MTA 的源代码长什么样……</span>"</blockquote>
<br />
——Y_Less，2009年1月，TMS Forums<br />
<br />
<hr class="mycode_hr" />
<br />
这篇声明在社区引发了强烈反响。数日后，经社区压力，Y_Less 得以解封，YSF 在不修改只读变量的前提下被允许继续使用。从表面上看，风波平息了。<br />
<br />
但那句"附言三"——"不知道 MTA 的源代码长什么样"——如今读来，已不再只是一句无心之语。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第三卷：停滞、管控与分歧（2014–2019）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第八章　0.3.7 之后的沉寂（含源码泄漏事件）</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2015 年 5 月 1 日</span>，SA:MP <span style="font-weight: bold;" class="mycode_b">0.3.7</span> 发布。此后，Kalcor 在新功能层面的开发近乎陷入停滞。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年前后</span>，Kalcor 发布了 <span style="font-weight: bold;" class="mycode_b">SA-MP 0.3.DL</span>——一个支持服务端向玩家客户端推送自定义模型（Download Content）的版本。这是社区长期以来最渴望的功能之一，玩家们可以在 SA:MP 服务器上看到服务器自定义的车辆、皮肤、物件模型，而不再局限于原版游戏资产。<br />
<br />
然而 0.3.DL 的推出并不顺利：安全问题（恶意服务器可能推送损坏的模型文件危害客户端）和与旧版 0.3.7 的兼容性问题，使得相当一部分服务器拒绝迁移。SA:MP 社区自此一分为二，0.3.7 阵营与 0.3.DL 阵营长期并存。<br />
<br />
这种分裂令社区感到困惑与沮丧。有人多次在论坛呼吁将两个版本合并，但得不到任何回应。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">源码泄漏事件（2010 年起源，2018 年爆发）</h4><br />
<br />
在 0.3.DL 引发社区分裂的同一时期，另一条隐患也终于浮出水面。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年 11 月 15 日</span>，SA:MP 官方论坛上出现了一篇由用户 Kshishtof 发起的帖子，标题是《SA-MP 源代码泄漏》。帖子指向一个名为 <span style="font-weight: bold;" class="mycode_b">rw-mp.net</span> 的项目，该项目被认为是基于泄漏的 SA:MP 源代码构建的独立多人联机分支。<br />
<br />
帖子引发了社区的激烈讨论。一部分人对 rw-mp 持同情甚至欣赏的态度，认为它至少在做 SA:MP 不再愿意做的事；另一部分人则斥之为对原作的窃取与侮辱。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年 11 月 16 日</span>，Kalcor 亲自在帖子中出现，发表了两段回应。第一段揭示了这批泄漏源码的来历：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"SA:MP 的源代码于 2010 年被一名法国人从我们的服务器上黑掉，目的是为 IV:MP 这个 mod 服务。我记录并上报了这次入侵。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">GitHub 上大约有十个副本。我一直没有把它们下架，是因为提交 DMCA 申诉需要将我的真实姓名录入 GitHub 的公开 DMCA 数据库，否则就得花钱请律师。"</span></blockquote>
<br />
第二段话语气更为强硬，是一封事实上的法律警告：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"0.2.5 的源代码是通过计算机入侵从我们的服务器上盗取的。任何基于该代码发布软件的人，都涉嫌与我们作对的刑事共谋。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">SA:MP 所使用的 RakNet 版本并非开源，而是通过付费许可证使用的。BASS 音频库同样是付费许可证使用的。整个游戏 mod 社区正在被那些删除原始版权信息、将他人成果冒充自己作品重新发布的蠢货所伤害。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我给他们几天时间关闭并停止任何与 SA:MP 相关的活动。"</span></blockquote>
<br />
——Kalcor，SA:MP 官方论坛，2018 年 11 月 16 日 原帖：https://sampforum.blast.hk/showthread.php?tid=660866<br />
<br />
这段声明揭示了几个此前从未公开过的重要事实：<br />
<br />
其一，SA:MP 源码泄漏的根源远早于 2018 年——<span style="font-weight: bold;" class="mycode_b">2010 年</span>就已经发生了一次有据可查的服务器入侵事件，是一名法国黑客为了支持 IV:MP（GTA IV 的多人 mod）而实施的。这与 Kalcor 在 2019 年 pawn.wiki 文章中所说的"R* 给 MTA 的代码被用于攻击 SA:MP"形成了完整的脉络——他所遭受的代码安全威胁，来自不止一个方向。<br />
<br />
其二，Kalcor 之所以始终不对 GitHub 上的泄漏副本提交 DMCA，并非不知情或不在意，而是出于一个极具讽刺意味的现实顾虑：提交 DMCA 需要将他的真实姓名公开录入数据库，而他不愿意这样做。源码在网上流传的同时，他本人却因为隐私顾虑而放任不管。<br />
<br />
这次事件在社区中引发了新一轮关于"Kalcor 应不应该直接将 SA:MP 开源"的讨论。部分社区成员认为，既然源码已经通过非法途径广泛流传，不如主动开源，至少可以让社区以合法的方式参与改进。这个声音 Kalcor 听到了，但他的答案，在两年后的 pawn.wiki 那篇文章里已经说得很清楚。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第九章  Kalcor 眼中的历史：MTA 的旧账、R\* 的源码，与闭源的真实理由</h4><br />
<br />
编年史至此已经写了许多关于 Kalcor 的事——他的决策、他的封号、他的沉默——却始终没有给他一个真正完整的出场。他是从哪里来的？他为什么那样做？他拒绝开源的理由究竟是什么？<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2019 年 10 月 25 日</span>，就在 Kalcor 于 SA:MP 官方论坛发布某条帖子后不久，俄语 Pawn 开发者社区 pawn.wiki 上出现了一篇由用户 <span style="font-weight: bold;" class="mycode_b">m1n1vv</span> 整理、转述并翻译的长文，标题是《SA-MP 0.3.9 与 Kalcor 的新故事》。这篇文章完整记录了 Kalcor 这篇帖子的核心内容——那是迄今为止他对自己技术履历与闭源立场最完整、最直接的一次亲口陈述。<br />
<br />
以下是 Kalcor 在那篇帖子中所说的全部内容，经 m1n1vv 翻译并整理，原文以俄文发布于 pawn.wiki：<br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">那么，请允许我给你们讲一段历史。结论由你们自己得出。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2003 年，在 MTA 的 IRC 频道上待了一周之后，我被邀请加入 MTA:VC（Vice City Multiplayer）的开发。几个月后，我晋升为 MTA 的首席开发者。以下是一张截图，记录了我和 Si|ent 一起尝试让 MTA:VC 中的船只同步正常工作的画面，日期是 2003年12月31日。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我是 MTA:Blue 的少数开发者之一——这是 MTA 针对罪恶都市的新版本。那时候除我之外，大多数人都被现实生活拖住了。我开发了玩家上下文切换同步系统，并引入了 RakNet 库。同样的系统至今仍被 SA-MP 和 MTA:SA 所使用。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">这种处境让我感到沮丧——一周又一周过去，只有我一个人在提交代码，而论坛上却有一堆"开发者"在大谈特谈一切将会如何运作。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">于是我离开了 MTA 的开发。在我离开期间，另一个叫 eAi 的人加入了项目，开始研究我的代码，试图弄清楚它是怎么工作的。至少有人在做事了——他的方式是去主动联系各方，于是他通过 ICQ 找到了我，还找到了 R</span>（Rockstar Games）开发者的电子邮件地址，并与他们取得了联系。*<br />
<br />
<span style="font-style: italic;" class="mycode_i">那时候我对 GTA 多人联机并不感兴趣。我有一个乐队，还参与了 ipodlinux 等项目，但 eAi 似乎非常热衷于推动 MTA:Blue 取得进展。于是我重新加入了项目，持续了几个月。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">以下是 2004年底 MTA:Blue 的公开宣传页面存档。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">正是这件事导致了我和 MTA 其他开发者之间的决裂：我想要构建一个服务端系统——就像 VC-MP 的 ini 脚本系统，以及 SA-MP 中基于 Pawn 脚本的服务端系统；而 MTA 的开发者们则想要客户端扩展，就像那个宣传页面上描述的那样。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2005年初，我再次离开了 MTA。就在那段时间，R</span> North 在 PS2 上发布了 GTA:SA，并正在开发 PC 版本。eAi 与 R<span style="font-style: italic;" class="mycode_i"> 的技术总监有联系，还通过 ICQ 向我炫耀说，他拿到了大量 GTA:SA 源代码的头文件。我注意到，MTA 的开发者们似乎打算放弃罪恶都市版的 MTA:Blue，转战 GTA:SA。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不相信 MTA 及其开发能力，2005年中，我开始独立开发自己的多人联机。我发布了 VC-MP，基于玩家上下文切换和 RakNet。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">随后，我与 jax、spooky 以及其他一些人一起开发了 SA-MP。它远比之前的 mod 庞大得多。我们与 GTANet/GTAForums——最大的 GTA 非官方粉丝站——有着较为密切的联系，这使我们获得了更大的知名度。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">到 2008 年，SA-MP 的玩家数量是 MTA 的 10 到 20 倍。MTA 的开发者们感到在这种竞争环境下已无法与之抗衡，于是他们公开了自己的源代码。MTA 的开发者们从未询问过我或任何前任开发者，是否可以公开这些源代码。他们声称所有东西都已经被重写了，但事实并非完全如此。时至今日，MTA:SA 中仍然有我的代码。我没有费心去追究他们，因为他们看起来太蠢了——但我猜，这里那些呼吁公开 SA-MP 源代码的人，很可能是受到了 MTA 的启发，尽管他们或许不应该这样。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">而这就是现在正在发生的事：我为 MTA 开发的"游戏"代码，以及 R\</span> 给 MTA 的源代码，正在被移植进 mod\<span style="font-style: italic;" class="mycode_i">so\</span>beit——一款流行的 SA-MP 外挂工具。*<br />
<br />
<span style="font-style: italic;" class="mycode_i">你们知道这意味着什么吗？R\</span> 给 MTA 的那部分源代码，有相当大一部分被用来——攻击 SA-MP！*<br />
<br />
<span style="font-style: italic;" class="mycode_i">从一小批相当专业的 MTA 开发者起步，这件事已经演变成了极度肮脏的东西。那些想要摧毁 SA-MP 的人，对于是否违法毫不在意。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">看起来，任何被公开的源代码都可能被用来攻击 SA-MP——尽管它本可以被用于提供有价值的更新。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">公开 SA-MP 源代码这个决定，归根结底取决于：我们是否仍然处于这种充满敌意的环境中——人们在攻击我、想要攻击 SA-MP——还是这一切已经成为过去。我想说，这取决于 mod 的规模以及对外挂工具的需求程度。封闭源代码让我可以在每次发布时重新洗牌所有内部结构，使大量外挂工具失效。SA-MP 的许多"安全"更新，实质上就是我在重新排列数据，以清除现有的外挂工具。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">最终，SA-MP 将会走到这样一个时刻：所有人都彼此友善和尊重，外挂与欺诈变得罕见——但届时玩家数量将极为稀少，我们中的大多数人也已不在了。</span></blockquote>
<br />
——Kalcor，2019年10月，SA:MP 官方论坛<br />
（由 m1n1vv 转述并整理，经 Типичный Скриптер 译为俄文，发布于 pawn.wiki，2019年10月25日）<br />
<br />
<hr class="mycode_hr" />
<br />
这篇陈述，是理解 Kalcor 其人与其决策的关键文献。<br />
<br />
它第一次完整地揭示了他的来历：他不是凭空出现的 SA:MP 创始人，而是一个从 MTA 内部出走的人。<span style="font-weight: bold;" class="mycode_b">2003 年至 2005 年间，他在 MTA 团队中担任首席开发者</span>，亲手构建了玩家同步系统与 RakNet 架构——而他愤而离开，正是因为他坚持的"服务端脚本系统"方向遭到其他成员的反对。SA:MP 的诞生，某种程度上是一次对 MTA 的报复性创业。<br />
<br />
它也第一次给出了 Kalcor 拒绝开源的真实逻辑：他不是在藏私，也不是单纯的控制欲作祟——在他看来，<span style="font-weight: bold;" class="mycode_b">闭源是他对抗外挂工具的核心武器</span>。他承认 SA:MP 的许多所谓"安全更新"，实质只是重新排列内部数据结构，使依赖固定内存地址的外挂工具在新版本中失效。一旦开源，这条防线便彻底坍塌。<br />
<br />
而他与 MTA 之间的积怨，在这篇文章里也首次有了完整呈现：他认为 MTA 在开源自己的代码库时，从未征得他这位最初作者的同意；更令他愤怒的是，他随后发现，R\* 曾向 MTA 提供的部分 GTA:SA 源代码头文件，辗转流入了 SA:MP 外挂工具的制作者手中——成为攻击 SA:MP 的武器。这份偏执与防御，贯穿了他此后对待社区和开源请求的所有态度。<br />
<br />
这篇发布于 2019 年 10 月的文章，距 Kalcor 宣告放弃 SA:MP 仅剩不到一个月。这是他在离开之前，最后一次试图解释自己。<br />
<br />
<hr class="mycode_hr" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[考古] openmp 常见问题解答 | 2020年4月]]></title>
			<link>https://open-mp.cn/showthread.php?tid=29</link>
			<pubDate>Tue, 24 Mar 2026 16:55:00 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=29</guid>
			<description><![CDATA[<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">GTA SA 和 SA:MP 中的漏洞会被修复吗？</span><br />
<br />
会的！<br />
你也可以向我们反馈我们尚未知晓的 bug：github.com/openmultiplayer/samp-bugs/<br />
或在论坛提交：burgershot.gg/showthread.php?tid=99<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 会支持哪些 SA:MP 版本？包括 0.3DL 吗？</span><br />
<br />
我们不会支持 0.3.7 以下的版本，但你可以自行实现（这正是开源的魅力所在）。<br />
如果大多数服务器都尝试使用 0.3DL，我们会跟进支持。我们也做过调查，多数人支持 0.3DL，所以这件事大概率会做，但不会出现在客户端的前几个版本中。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 客户端会有固定的更新周期吗？</span><br />
<br />
不会。固定周期需要一支流程成熟的大型团队，而我们目前是一支志愿者队伍。<br />
也许情况将来会有所改变，我们不敢打包票。代码开源之后，你们可以随时关注项目进展。我们会尽一切努力在版本更新之间保持与社区的沟通。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">我们可以提交新功能建议吗？</span><br />
<br />
我们非常欢迎社区参与，你可以在这里留下你的建议：burgershot.gg/forumdisplay.php?fid=42&amp;page=6<br />
<br />
当然，我们无法保证每个想法都会被采纳和实现。但由于代码是开源的，你随时可以自己动手实现。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">会有反作弊系统吗？</span><br />
<br />
会有。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 会继续使用 Pawn 吗？可以使用其他语言吗？</span><br />
<br />
所有的开发工作、测试和文档均以 Pawn 为基础完成。不过，我们提供了 C API，允许任何人在此之上实现其他语言的支持。<br />
<br />
我们也讨论过引入一些半官方的语言模块，但 Pawn 依然是主要且受官方支持的脚本语言。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">SA:MP 的插件能在 open.mp 中使用吗？</span><br />
<br />
"插件"这个词目前用来指代旧式插件——即那些为 SA-MP 编写的插件（例如 sscanf、MySQL 等）。open.mp 提供了加载这些现有插件的 API。<br />
<br />
我们对新式插件的称呼是"模块"——无论是外部插件还是内部代码，只要使用 open.mp 更新、更强大的 API，统称为模块。<br />
<br />
旧式插件仍然可以正常运行，并会持续得到支持，除非它们依赖内存黑客手段（例如 YSF），因为那类插件依赖特定的内存地址和数据结构，而这些在 open.mp 服务端上是完全不同的。不过，大多数老式内存黑客当初存在的意义，恰恰是为了补全一些功能——而这些功能将直接内置于 open.mp，所以那些插件本来也就用不着了。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">数据库功能只能用 SQLite，还是也可以用 MySQL？</span><br />
<br />
默认的数据库功能与以前一样，仍然是 SQLite。但如前所述，open.mp 提供了加载现有插件的 API，因此数据库方面无需在内部做任何改动——通过现有插件依然可以实现。<br />
<br />
第三方模块在 open.mp 中是完全受支持的"一等公民"——无论是回调还是原生函数，其可用性与内部代码完全一致，因此将功能放入外部模块不存在任何劣势。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">HUD、体力值、小游戏（台球、健身房等）、车辆选项、路线指示、SA:MP+ 功能等会有更多自定义选项吗？会支持更灵活的图形界面，而不是像 SA:MP 那样只能用有限的文字绘制吗？CEF 呢？这些内容会如何保障安全？</span><br />
<br />
关于这个话题我们收到了太多提问，请先去泡杯茶——这个回答会有点长。<br />
<br />
我们的开发团队里有 Hual（SA:MP+ 的作者），未来会带来什么，谁知道呢？?<br />
<br />
SA:MP 与 MTA 最本质的区别，其实在名字里就说得很清楚了——SA:MP 就是字面意思上的"圣安地列斯多人游戏"，是 GTA 圣安地列斯这款游戏的多人版本；而 MTA 则是一个架设在这个世界观之上、更偏向通用平台的存在。<br />
<br />
SA:MP 在加入新功能时，始终紧扣原版游戏的体验感，尽管走出框架并非不可能，但整体风格一直非常保守。<br />
<br />
我们之所以长期坚守 SA:MP，正是因为认同这种态度。但我们希望拥有更多一点的自由度（这也是我们另起炉灶的原因），同时又不想走得太远。我们会引入一些新功能，其中有些在原版游戏中并不存在，但我们仍然会审慎地权衡每个功能带来的影响。<br />
<br />
让对话框稍微宽一点，算是突破 GTA 正统边界的疯狂改动吗？大概不算。<br />
<br />
加入 CEF 是否走得太远了？是的，这不会发生。?‍♂️<br />
<br />
平衡点就在两者之间。<br />
<br />
话虽如此，玩家们向来能在有限的支持下迸发出令人惊叹的创造力，我们相信这一点不会改变。我们会始终鼓励玩家和开发者尽情发挥创意——这也是我们选择开源的原因之一，我们甚至会在这方面提供帮助，但这不会是我们的核心任务。<br />
<br />
我们最主要的顾虑集中在客户端层面。我们不希望服务器主可以向玩家分发任何具有潜在危害的内容。圣安地列斯本身并非为多人游戏或 mod 而设计，许多文件加载器对损坏或恶意文件缺乏防护——当初根本没有这方面的需求。这正是 SA:MP 在引入自定义模型时遇到的难题，对我们来说同样如此。<br />
<br />
每当我们要对游戏的某个部分进行自定义，都必须先确保对应的文件格式和加载器不存在可利用的漏洞。我们可以确认，模型和脚本已经出现过被攻击的案例，其他部分可能也已经被攻击，而一旦我们开始允许服务器上传任意文件，被攻击几乎是必然的。<br />
<br />
至于资源保护——坦率地说，这在根本上是无法实现的。要让客户端显示一个自定义模型，就必须把这个模型文件传给它。文件一旦传到客户端，它就在对方的电脑上了，对方拿它怎么做，我们管不了。有些方法可以让盗取变得麻烦一些，但没有哪种方法是绝对可靠的。网络上虽然存在 DRM、安全隔离区等手段，但要使用这些技术，就必须牺牲开源原则。可以参考一下 EME 标准以及 Firefox 中内嵌闭源二进制文件所引发的争议。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">NPC 会有更好的支持吗？</span><br />
<br />
这不是我们当前的优先事项，但从客户端角度来看，NPC 本质上与普通玩家没有区别。我们至少希望 open.mp 的 NPC 功能能够对标 FCNPC 插件的水平，这是未来版本中我们可以认真考虑的方向。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">你们说 open.mp 移除了所有限制——这具体是怎么实现的？它像 streamer 插件一样吗？</span><br />
<br />
原理类似，但与 streamer 相比集成度更高，因此我们同样可以对载具和玩家进行流式处理，并能以远超插件能力的方式操作本地 ID。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">玩家可以被附加到物体上吗？</span><br />
<br />
可以，我们已经实现了这个功能。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 完成 SA:MP 功能的复现之后，接下来会新增什么？</span><br />
<br />
我们很喜欢聊未来的计划——持续关注我们就好，你们会看到的。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">可以用 SA:MP 客户端连接 open.mp 服务器吗？</span><br />
<br />
SA:MP 是通过逆向工程对第三方程序进行交互的 mod，open.mp 也是如此，我们的法律立场与 SA:MP 完全相同。我们没有使用任何 SA:MP 的泄露源代码——这一点已经反复强调，代码开源之后，社区自然会看得清清楚楚。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">新版 open.mp 客户端最大的挑战是什么？</span><br />
<br />
把它写出来！<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">五年后，你们认为 open.mp 会是什么样子？</span><br />
<br />
不必担心这个，我们有很多长远的想法。?<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">五年后，你们认为 SA-MP 会是什么样子？</span><br />
<br />
那是 SA-MP 团队的事，不是我们该操心的——在这个问题上我们没有立场去猜测。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">你们有没有想过放弃 open.mp？</span><br />
<br />
有过，因为我们也是普通人。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">最后，也是被问得最多的问题：</span><br />
<span style="font-weight: bold;" class="mycode_b">我们什么时候才能看到 open.mp？</span><br />
<br />
等它准备好了。???<br />
<br />
<hr class="mycode_hr" />
<br />
祝大家接下来的一周愉快！<br />
<br />
带着满满的爱，<br />
open.mp 团队 ?]]></description>
			<content:encoded><![CDATA[<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">GTA SA 和 SA:MP 中的漏洞会被修复吗？</span><br />
<br />
会的！<br />
你也可以向我们反馈我们尚未知晓的 bug：github.com/openmultiplayer/samp-bugs/<br />
或在论坛提交：burgershot.gg/showthread.php?tid=99<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 会支持哪些 SA:MP 版本？包括 0.3DL 吗？</span><br />
<br />
我们不会支持 0.3.7 以下的版本，但你可以自行实现（这正是开源的魅力所在）。<br />
如果大多数服务器都尝试使用 0.3DL，我们会跟进支持。我们也做过调查，多数人支持 0.3DL，所以这件事大概率会做，但不会出现在客户端的前几个版本中。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 客户端会有固定的更新周期吗？</span><br />
<br />
不会。固定周期需要一支流程成熟的大型团队，而我们目前是一支志愿者队伍。<br />
也许情况将来会有所改变，我们不敢打包票。代码开源之后，你们可以随时关注项目进展。我们会尽一切努力在版本更新之间保持与社区的沟通。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">我们可以提交新功能建议吗？</span><br />
<br />
我们非常欢迎社区参与，你可以在这里留下你的建议：burgershot.gg/forumdisplay.php?fid=42&amp;page=6<br />
<br />
当然，我们无法保证每个想法都会被采纳和实现。但由于代码是开源的，你随时可以自己动手实现。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">会有反作弊系统吗？</span><br />
<br />
会有。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 会继续使用 Pawn 吗？可以使用其他语言吗？</span><br />
<br />
所有的开发工作、测试和文档均以 Pawn 为基础完成。不过，我们提供了 C API，允许任何人在此之上实现其他语言的支持。<br />
<br />
我们也讨论过引入一些半官方的语言模块，但 Pawn 依然是主要且受官方支持的脚本语言。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">SA:MP 的插件能在 open.mp 中使用吗？</span><br />
<br />
"插件"这个词目前用来指代旧式插件——即那些为 SA-MP 编写的插件（例如 sscanf、MySQL 等）。open.mp 提供了加载这些现有插件的 API。<br />
<br />
我们对新式插件的称呼是"模块"——无论是外部插件还是内部代码，只要使用 open.mp 更新、更强大的 API，统称为模块。<br />
<br />
旧式插件仍然可以正常运行，并会持续得到支持，除非它们依赖内存黑客手段（例如 YSF），因为那类插件依赖特定的内存地址和数据结构，而这些在 open.mp 服务端上是完全不同的。不过，大多数老式内存黑客当初存在的意义，恰恰是为了补全一些功能——而这些功能将直接内置于 open.mp，所以那些插件本来也就用不着了。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">数据库功能只能用 SQLite，还是也可以用 MySQL？</span><br />
<br />
默认的数据库功能与以前一样，仍然是 SQLite。但如前所述，open.mp 提供了加载现有插件的 API，因此数据库方面无需在内部做任何改动——通过现有插件依然可以实现。<br />
<br />
第三方模块在 open.mp 中是完全受支持的"一等公民"——无论是回调还是原生函数，其可用性与内部代码完全一致，因此将功能放入外部模块不存在任何劣势。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">HUD、体力值、小游戏（台球、健身房等）、车辆选项、路线指示、SA:MP+ 功能等会有更多自定义选项吗？会支持更灵活的图形界面，而不是像 SA:MP 那样只能用有限的文字绘制吗？CEF 呢？这些内容会如何保障安全？</span><br />
<br />
关于这个话题我们收到了太多提问，请先去泡杯茶——这个回答会有点长。<br />
<br />
我们的开发团队里有 Hual（SA:MP+ 的作者），未来会带来什么，谁知道呢？?<br />
<br />
SA:MP 与 MTA 最本质的区别，其实在名字里就说得很清楚了——SA:MP 就是字面意思上的"圣安地列斯多人游戏"，是 GTA 圣安地列斯这款游戏的多人版本；而 MTA 则是一个架设在这个世界观之上、更偏向通用平台的存在。<br />
<br />
SA:MP 在加入新功能时，始终紧扣原版游戏的体验感，尽管走出框架并非不可能，但整体风格一直非常保守。<br />
<br />
我们之所以长期坚守 SA:MP，正是因为认同这种态度。但我们希望拥有更多一点的自由度（这也是我们另起炉灶的原因），同时又不想走得太远。我们会引入一些新功能，其中有些在原版游戏中并不存在，但我们仍然会审慎地权衡每个功能带来的影响。<br />
<br />
让对话框稍微宽一点，算是突破 GTA 正统边界的疯狂改动吗？大概不算。<br />
<br />
加入 CEF 是否走得太远了？是的，这不会发生。?‍♂️<br />
<br />
平衡点就在两者之间。<br />
<br />
话虽如此，玩家们向来能在有限的支持下迸发出令人惊叹的创造力，我们相信这一点不会改变。我们会始终鼓励玩家和开发者尽情发挥创意——这也是我们选择开源的原因之一，我们甚至会在这方面提供帮助，但这不会是我们的核心任务。<br />
<br />
我们最主要的顾虑集中在客户端层面。我们不希望服务器主可以向玩家分发任何具有潜在危害的内容。圣安地列斯本身并非为多人游戏或 mod 而设计，许多文件加载器对损坏或恶意文件缺乏防护——当初根本没有这方面的需求。这正是 SA:MP 在引入自定义模型时遇到的难题，对我们来说同样如此。<br />
<br />
每当我们要对游戏的某个部分进行自定义，都必须先确保对应的文件格式和加载器不存在可利用的漏洞。我们可以确认，模型和脚本已经出现过被攻击的案例，其他部分可能也已经被攻击，而一旦我们开始允许服务器上传任意文件，被攻击几乎是必然的。<br />
<br />
至于资源保护——坦率地说，这在根本上是无法实现的。要让客户端显示一个自定义模型，就必须把这个模型文件传给它。文件一旦传到客户端，它就在对方的电脑上了，对方拿它怎么做，我们管不了。有些方法可以让盗取变得麻烦一些，但没有哪种方法是绝对可靠的。网络上虽然存在 DRM、安全隔离区等手段，但要使用这些技术，就必须牺牲开源原则。可以参考一下 EME 标准以及 Firefox 中内嵌闭源二进制文件所引发的争议。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">NPC 会有更好的支持吗？</span><br />
<br />
这不是我们当前的优先事项，但从客户端角度来看，NPC 本质上与普通玩家没有区别。我们至少希望 open.mp 的 NPC 功能能够对标 FCNPC 插件的水平，这是未来版本中我们可以认真考虑的方向。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">你们说 open.mp 移除了所有限制——这具体是怎么实现的？它像 streamer 插件一样吗？</span><br />
<br />
原理类似，但与 streamer 相比集成度更高，因此我们同样可以对载具和玩家进行流式处理，并能以远超插件能力的方式操作本地 ID。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">玩家可以被附加到物体上吗？</span><br />
<br />
可以，我们已经实现了这个功能。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 完成 SA:MP 功能的复现之后，接下来会新增什么？</span><br />
<br />
我们很喜欢聊未来的计划——持续关注我们就好，你们会看到的。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">可以用 SA:MP 客户端连接 open.mp 服务器吗？</span><br />
<br />
SA:MP 是通过逆向工程对第三方程序进行交互的 mod，open.mp 也是如此，我们的法律立场与 SA:MP 完全相同。我们没有使用任何 SA:MP 的泄露源代码——这一点已经反复强调，代码开源之后，社区自然会看得清清楚楚。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">新版 open.mp 客户端最大的挑战是什么？</span><br />
<br />
把它写出来！<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">五年后，你们认为 open.mp 会是什么样子？</span><br />
<br />
不必担心这个，我们有很多长远的想法。?<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">五年后，你们认为 SA-MP 会是什么样子？</span><br />
<br />
那是 SA-MP 团队的事，不是我们该操心的——在这个问题上我们没有立场去猜测。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">你们有没有想过放弃 open.mp？</span><br />
<br />
有过，因为我们也是普通人。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">最后，也是被问得最多的问题：</span><br />
<span style="font-weight: bold;" class="mycode_b">我们什么时候才能看到 open.mp？</span><br />
<br />
等它准备好了。???<br />
<br />
<hr class="mycode_hr" />
<br />
祝大家接下来的一周愉快！<br />
<br />
带着满满的爱，<br />
open.mp 团队 ?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[考古]MTA 团队与 open.mp 团队早期就潜在合作可能性展开的公开对话 | 2019年5月]]></title>
			<link>https://open-mp.cn/showthread.php?tid=28</link>
			<pubDate>Tue, 24 Mar 2026 16:53:51 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=28</guid>
			<description><![CDATA[<hr class="mycode_hr" />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表：</span><br />
<br />
你好，<br />
<br />
在正式开始之前，先允许我做个自我介绍。我是 MTA 团队的成员，长期深度参与多人游戏模组的开发工作。本帖内容也已获得团队其他成员的认可。<br />
<br />
过去这几天，我们一直在默默关注 SA-MP 的近况，以及你们测试团队的动向。我们刻意等待了一段时间，让局势稍微平息，这也是我们迟迟没有表态的原因。<br />
<br />
在我们看来，眼下的局面对 MTA:SA 和 SA-MP 来说，恰恰是一次难得的相互靠拢的机会。我们理解你们对现状的不满，但我们认为，为《GTA 圣安地列斯》这款已有相当历史的游戏再从零搭建一个多人游戏项目，似乎并不是最明智的选择。我们对圣安地列斯的热爱，与你们一样深厚。尽管近来在线玩家数量基本保持稳定，但不可否认的是，吸引新玩家的难度正在与日俱增——尤其考虑到玩家群体结构的变化。<br />
<br />
因此，我们诚邀你们加入 MTA 社区。从技术层面来看，我们认为最务实的方案是实现从 SA-MP 到 MTA 的兼容层，这样也能帮助你们更快推进前期更新的发布。<br />
<br />
说几个数据：过去三年，我们发布了四个新版本，并持续推出大量迭代更新和反作弊升级；而 SA-MP 的最后一次官方发布，距今已超过四年（依据 sa-mp.com 官方数据）。<br />
<br />
除少数例外情况，MTA 在技术上已基本能够"模拟"SA-MP 的全部功能。我们相信，凭借你们作为资深开发者的经验，双方完全可以共同实现客户端兼容。<br />
<br />
此外，我们已有一个名为 <span style="font-weight: bold;" class="mycode_b">amx</span> 的资源（https://github.com/multitheftauto/mtasa-resources/tree/master/%5Bgamemodes%5D/%5Bamx%5D），可在 MTA 内部运行 Pawn 虚拟机。该资源目前版本较旧，可能需要重构，但核心功能依然可用。<br />
<br />
我们相信这将是一个对双方都有利的合作，也是两个社区难得的机遇——不仅能汇聚各自优秀的开发者和新鲜想法，还能为玩家带来真正丰富的游戏体验，甚至可能吸引新玩家（例如 MTA 的粉丝群体）加入，并催生一批概念全新的脚本功能。<br />
<br />
如果你们对潜在问题有任何顾虑，欢迎随时与我们深入探讨。<br />
<br />
谨致问候，代表 MTA 团队。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">JustMichael，论坛跟进者：</span><br />
<br />
我们需要在团队内部充分讨论之后，才能就该提案给出正式回应。这绝非一个小提案，我们需要时间消化并核实帖子中提及的所有信息。因此，请不要将这条回复理解为拒绝——我们绝对没有在拖延，会尽快给出正式答复。另外，请始终将 J0sh 的名字写作"J0sh……"。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表：</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>BloodMaster 写道：「SA-MP 保留了圣安地列斯原汁原味的氛围和外观，而 MTA 则是一个可以高度自定义的引擎——这正是 SA-MP 吸引更多玩家的根本原因。」</blockquote>
这个观点我之前也看到过几次，确实触及了一个重要方面。MTA 确实拥有某种"可自由改造的自定义引擎"，但我个人并不认为这是一个负面特质。毕竟，没有人强迫任何人把游戏做成与原版圣安地列斯截然不同的样子——这完全是开发者自己的选择。况且，随着功能的不断叠加，你们迟早也会面临类似的情况。<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>iReal Worlds 写道：「Lua……认真的吗？」</blockquote>
依我个人之见，Lua 是一门非常出色的多范式语言，同时支持命令式、面向对象乃至部分函数式编程风格。更重要的是，它在设计之初就以"嵌入其他应用程序"为核心目标，这在客户端脚本的安全执行方面具有显著优势，是其他语言难以比拟的。<br />
<br />
此外，我还想提一个近期由 MTA 社区打造的有趣项目：https://mta-slipe.com/。它本质上是将 C# 引入到 Lua 环境中。<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>michael@belgium 写道：「想象一下所有人都切换到 Lua……」</blockquote>
这并不是我的提议。我们谈论的是兼容性方案——让 SA-MP 的模组和插件（用 Pawn 编写）无需任何修改，即可直接在 MTA 中运行。如果 open.mp 的开发者计划支持更多脚本语言，我们也可以将 Pawn 作为 MTA 的附加语言引入（包括对 SA-MP API 脚本的支持）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">MyU，open.mp 开发者：</span><br />
<br />
首先声明：以下内容纯属个人观点，与 open.mp 项目及团队立场无关。<br />
<br />
事实上，已经有一些人指出，MTA 和 SA-MP 本质上是两种完全不同的东西——确实如此，差异相当显著。MTA 走的是不断创新的路线，而 SA-MP 则始终"守着老传统"；正因为长期没有更新、也不理会社区的功能需求，才会是今天这个局面。<br />
<br />
我个人两款都玩过（MTA 是大约两三年前，当时 OOP Lua 刚加入不久，玩了一两个月）。玩了一段时间后，MTA 对我来说变得有些"吃不消"——那时候我的电脑配置比较低，加上遇到了一些 CEF 相关的问题，虽然我相信这些问题现在应该都已经解决了。<br />
<br />
SA-MP 相当"轻量"：一个压缩包、一个 samp.dll、一个启动器，再加一两个文件，就全了。而 MTA:SA 则捆绑了 CEF 文件、CGUI 文件、本地化文件等一大堆内容。我个人认为，把这两个多人游戏合并在一起是行不通的——它们太不一样了，目标也各不相同。SA-MP 里安装 mod 极其简单，丢进游戏文件夹就能用；MTA:SA 则更像是一个经过精心打磨、功能完整的多人游戏模组，但玩家有自己的偏好，这无可厚非。<br />
<br />
简单总结一下：<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">SA-MP</span> → 轻量、易上手，但在某些方面存在局限；<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">MTA:SA</span> → 体量较重，但功能全面，有时略显复杂，稳定性却强于 SA-MP（玩家们甚至会利用 MTA:SA 的崩溃报告来排查问题——这本身就说明很多问题）。<br />
</li>
</ul>
<br />
不过我认为，玩家并不希望社区就此一分为二、各走各的路。竞争本身，以及由此带来的优胜劣汰，对整体发展是有益的。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表（回复 MyU）：</span><br />
<br />
性能问题在绝大多数情况下都源于脚本编写质量低下（尤其是客户端脚本写得糟糕）。"能力越大，责任越大"这句话在这里再合适不过了，虽然这听起来有点无奈。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Sasino97，open.mp 软件开发者：</span><br />
<br />
我认为加入 MTA 最大的好处，是可以直接接触到庞大的现有玩家群体，以及 MTA 客户端本身极为强大的功能上限。至于缺点嘛……他们的论坛实在是太丑了，抱歉直说。<br />
<br />
不过，我个人很认可 open.mp 这个项目的理念，所以我觉得两边（MTA 和 open.mp）还是应该作为独立项目，各自继续发展下去。<br />
<br />
<hr class="mycode_hr" />]]></description>
			<content:encoded><![CDATA[<hr class="mycode_hr" />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表：</span><br />
<br />
你好，<br />
<br />
在正式开始之前，先允许我做个自我介绍。我是 MTA 团队的成员，长期深度参与多人游戏模组的开发工作。本帖内容也已获得团队其他成员的认可。<br />
<br />
过去这几天，我们一直在默默关注 SA-MP 的近况，以及你们测试团队的动向。我们刻意等待了一段时间，让局势稍微平息，这也是我们迟迟没有表态的原因。<br />
<br />
在我们看来，眼下的局面对 MTA:SA 和 SA-MP 来说，恰恰是一次难得的相互靠拢的机会。我们理解你们对现状的不满，但我们认为，为《GTA 圣安地列斯》这款已有相当历史的游戏再从零搭建一个多人游戏项目，似乎并不是最明智的选择。我们对圣安地列斯的热爱，与你们一样深厚。尽管近来在线玩家数量基本保持稳定，但不可否认的是，吸引新玩家的难度正在与日俱增——尤其考虑到玩家群体结构的变化。<br />
<br />
因此，我们诚邀你们加入 MTA 社区。从技术层面来看，我们认为最务实的方案是实现从 SA-MP 到 MTA 的兼容层，这样也能帮助你们更快推进前期更新的发布。<br />
<br />
说几个数据：过去三年，我们发布了四个新版本，并持续推出大量迭代更新和反作弊升级；而 SA-MP 的最后一次官方发布，距今已超过四年（依据 sa-mp.com 官方数据）。<br />
<br />
除少数例外情况，MTA 在技术上已基本能够"模拟"SA-MP 的全部功能。我们相信，凭借你们作为资深开发者的经验，双方完全可以共同实现客户端兼容。<br />
<br />
此外，我们已有一个名为 <span style="font-weight: bold;" class="mycode_b">amx</span> 的资源（https://github.com/multitheftauto/mtasa-resources/tree/master/%5Bgamemodes%5D/%5Bamx%5D），可在 MTA 内部运行 Pawn 虚拟机。该资源目前版本较旧，可能需要重构，但核心功能依然可用。<br />
<br />
我们相信这将是一个对双方都有利的合作，也是两个社区难得的机遇——不仅能汇聚各自优秀的开发者和新鲜想法，还能为玩家带来真正丰富的游戏体验，甚至可能吸引新玩家（例如 MTA 的粉丝群体）加入，并催生一批概念全新的脚本功能。<br />
<br />
如果你们对潜在问题有任何顾虑，欢迎随时与我们深入探讨。<br />
<br />
谨致问候，代表 MTA 团队。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">JustMichael，论坛跟进者：</span><br />
<br />
我们需要在团队内部充分讨论之后，才能就该提案给出正式回应。这绝非一个小提案，我们需要时间消化并核实帖子中提及的所有信息。因此，请不要将这条回复理解为拒绝——我们绝对没有在拖延，会尽快给出正式答复。另外，请始终将 J0sh 的名字写作"J0sh……"。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表：</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>BloodMaster 写道：「SA-MP 保留了圣安地列斯原汁原味的氛围和外观，而 MTA 则是一个可以高度自定义的引擎——这正是 SA-MP 吸引更多玩家的根本原因。」</blockquote>
这个观点我之前也看到过几次，确实触及了一个重要方面。MTA 确实拥有某种"可自由改造的自定义引擎"，但我个人并不认为这是一个负面特质。毕竟，没有人强迫任何人把游戏做成与原版圣安地列斯截然不同的样子——这完全是开发者自己的选择。况且，随着功能的不断叠加，你们迟早也会面临类似的情况。<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>iReal Worlds 写道：「Lua……认真的吗？」</blockquote>
依我个人之见，Lua 是一门非常出色的多范式语言，同时支持命令式、面向对象乃至部分函数式编程风格。更重要的是，它在设计之初就以"嵌入其他应用程序"为核心目标，这在客户端脚本的安全执行方面具有显著优势，是其他语言难以比拟的。<br />
<br />
此外，我还想提一个近期由 MTA 社区打造的有趣项目：https://mta-slipe.com/。它本质上是将 C# 引入到 Lua 环境中。<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>michael@belgium 写道：「想象一下所有人都切换到 Lua……」</blockquote>
这并不是我的提议。我们谈论的是兼容性方案——让 SA-MP 的模组和插件（用 Pawn 编写）无需任何修改，即可直接在 MTA 中运行。如果 open.mp 的开发者计划支持更多脚本语言，我们也可以将 Pawn 作为 MTA 的附加语言引入（包括对 SA-MP API 脚本的支持）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">MyU，open.mp 开发者：</span><br />
<br />
首先声明：以下内容纯属个人观点，与 open.mp 项目及团队立场无关。<br />
<br />
事实上，已经有一些人指出，MTA 和 SA-MP 本质上是两种完全不同的东西——确实如此，差异相当显著。MTA 走的是不断创新的路线，而 SA-MP 则始终"守着老传统"；正因为长期没有更新、也不理会社区的功能需求，才会是今天这个局面。<br />
<br />
我个人两款都玩过（MTA 是大约两三年前，当时 OOP Lua 刚加入不久，玩了一两个月）。玩了一段时间后，MTA 对我来说变得有些"吃不消"——那时候我的电脑配置比较低，加上遇到了一些 CEF 相关的问题，虽然我相信这些问题现在应该都已经解决了。<br />
<br />
SA-MP 相当"轻量"：一个压缩包、一个 samp.dll、一个启动器，再加一两个文件，就全了。而 MTA:SA 则捆绑了 CEF 文件、CGUI 文件、本地化文件等一大堆内容。我个人认为，把这两个多人游戏合并在一起是行不通的——它们太不一样了，目标也各不相同。SA-MP 里安装 mod 极其简单，丢进游戏文件夹就能用；MTA:SA 则更像是一个经过精心打磨、功能完整的多人游戏模组，但玩家有自己的偏好，这无可厚非。<br />
<br />
简单总结一下：<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">SA-MP</span> → 轻量、易上手，但在某些方面存在局限；<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">MTA:SA</span> → 体量较重，但功能全面，有时略显复杂，稳定性却强于 SA-MP（玩家们甚至会利用 MTA:SA 的崩溃报告来排查问题——这本身就说明很多问题）。<br />
</li>
</ul>
<br />
不过我认为，玩家并不希望社区就此一分为二、各走各的路。竞争本身，以及由此带来的优胜劣汰，对整体发展是有益的。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表（回复 MyU）：</span><br />
<br />
性能问题在绝大多数情况下都源于脚本编写质量低下（尤其是客户端脚本写得糟糕）。"能力越大，责任越大"这句话在这里再合适不过了，虽然这听起来有点无奈。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Sasino97，open.mp 软件开发者：</span><br />
<br />
我认为加入 MTA 最大的好处，是可以直接接触到庞大的现有玩家群体，以及 MTA 客户端本身极为强大的功能上限。至于缺点嘛……他们的论坛实在是太丑了，抱歉直说。<br />
<br />
不过，我个人很认可 open.mp 这个项目的理念，所以我觉得两边（MTA 和 open.mp）还是应该作为独立项目，各自继续发展下去。<br />
<br />
<hr class="mycode_hr" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[服务器开发 精选资源清单]]></title>
			<link>https://open-mp.cn/showthread.php?tid=27</link>
			<pubDate>Sun, 22 Mar 2026 00:24:28 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=27</guid>
			<description><![CDATA[<hr class="mycode_hr" />
为 SA-MP 开发精选的实用工具、库、游戏模式、滤镜脚本和插件列表。<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">工具</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/compiler" target="_blank" rel="noopener" class="mycode_url">Community Compiler</a></span> - 一个大幅更新的编译器版本，包含众多修复和增强功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/sampctl" target="_blank" rel="noopener" class="mycode_url">sampctl</a></span> - 用于安装库和运行服务器的包管理器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Zeex/samp-plugin-runner" target="_blank" rel="noopener" class="mycode_url">Plugin Runner</a></span> - 用于直接从命令行运行轻量级服务器版本（无需 server.cfg）以测试插件的工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-plugin-boilerplate" target="_blank" rel="noopener" class="mycode_url">Plugin Boilerplate</a></span> - 通过样板代码简化插件的创建。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/samp-ptl" target="_blank" rel="noopener" class="mycode_url">SA:MP Plugin Template Library</a></span> - 使用此模板库，可以非常轻松快速地制作自己的插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://fiddle.sa-mp.dev" target="_blank" rel="noopener" class="mycode_url">SA-MP Fiddle</a></span> - 一个测试脚本（代码片段、概念验证、调试等）并分享给其他人的地方。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://packagecontrol.io/packages/Pawn%20syntax" target="_blank" rel="noopener" class="mycode_url">Pawn Syntax - Sublime</a></span> - 为 Sublime Text 提供的 Pawn 自动补全。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://marketplace.visualstudio.com/items?itemName=southclaws.vscode-pawn" target="_blank" rel="noopener" class="mycode_url">Pawn Syntax - Visual Marketplace</a></span> - 为 Visual Studio Code 提供的 Pawn 自动补全。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://bitbucket.org/Grimrandomer/samp-zone-editor/downloads" target="_blank" rel="noopener" class="mycode_url">SA-MP Zone Editor</a></span> - 用于制作区域等的区域编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/tools/Map%20Editor.zip" target="_blank" rel="noopener" class="mycode_url">SA-MP Map Editor</a></span> - 流行的 SA:MP 地图编辑器。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">库</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/samp-stdlib" target="_blank" rel="noopener" class="mycode_url">samp-stdlib</a></span> - 默认包含文件的更新版本。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 正确、文档齐全且完整。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/sa-mp-fixes" target="_blank" rel="noopener" class="mycode_url">fixes.inc</a></span> - 针对大量 SA:MP 服务器错误的高度优化修复。即插即用。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/YSI-Includes" target="_blank" rel="noopener" class="mycode_url">YSI-Includes</a></span> - 为 SA:MP/pawn 开发的最古老、最大、经过最充分测试且支持最完善的库，提供了大量新的游戏和语言特性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Open-GTO/foreach" target="_blank" rel="noopener" class="mycode_url">foreach</a></span> - 独立的 foreach 包含文件（非 y_iterate 版本）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/amx_assembly" target="_blank" rel="noopener" class="mycode_url">amx_assembly</a></span> - 对 pawn 脚本本身的底层访问。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/md-sort" target="_blank" rel="noopener" class="mycode_url">md-sort</a></span> - 在 Pawn 中对多维数组进行排序。修改数组的内部指针，而不是复制数据。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/indirection" target="_blank" rel="noopener" class="mycode_url">indirection</a></span> - 用于传递指针和间接调用函数的系统，并提供了自定义调用的抽象方法。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/code-parse.inc" target="_blank" rel="noopener" class="mycode_url">code-parse.inc</a></span> - 在编译时解析和自定义 pawn 代码。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Vince0789/sa-mp-extended-vehicle-information" target="_blank" rel="noopener" class="mycode_url">Extended Vehicle Information</a></span> - 将单人游戏中的大量车辆标志导入 SQLite 数据库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/sqlitei" target="_blank" rel="noopener" class="mycode_url">sqlitei</a></span> - 为 SA-MP SQLite 函数提供的高级 API。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/samp-weapon-config" target="_blank" rel="noopener" class="mycode_url">weapon-config</a></span> - 更一致、响应更快的伤害系统，并包含许多新特性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/SAMP-geoip" target="_blank" rel="noopener" class="mycode_url">samp-geoip</a></span> - 基于 IP 地址的地理位置信息。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/progress2" target="_blank" rel="noopener" class="mycode_url">progress2</a></span> - 将时间、生命值、车辆燃料等内容显示为进度条。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/itsneufox/GameText-Plus" target="_blank" rel="noopener" class="mycode_url">GameText+</a></span> - 一个为 SA-MP 和 open.mp 改进原生 GameText 的包含文件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-weapon-data" target="_blank" rel="noopener" class="mycode_url">weapon-data</a></span> - 精细调校、可自定义的武器数据。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/MichaelBelgium/MV_Youtube" target="_blank" rel="noopener" class="mycode_url">MV_Youtube</a></span> - 用于音频流的 YouTube 转换器 API。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/MySQL-Prepared-Statements" target="_blank" rel="noopener" class="mycode_url">MySQL Prepared Statements</a></span> - 为 PAWN MySQL 插件模拟预处理语句。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Brunoo16/samp-server-weapons" target="_blank" rel="noopener" class="mycode_url">samp-server-weapons</a></span> - 完全由服务器控制的武器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/actor_robbery" target="_blank" rel="noopener" class="mycode_url">actor_robbery</a></span> - 灵感来自 GTA V 的商店抢劫。actor_robbery.inc 模仿了该功能！<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-aviation" target="_blank" rel="noopener" class="mycode_url">samp-aviation</a></span> - 一个基于俯仰角的高度自动控制和基于横滚角的航向自动控制的基础系统。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-logger" target="_blank" rel="noopener" class="mycode_url">samp-logger</a></span> - 简单的结构化日志记录器，提供了一组简单的日志记录和调试函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/tdworg/samp-include-rscan" target="_blank" rel="noopener" class="mycode_url">TDW Recursion Scanner</a></span> - 一个查找代码中递归的库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Awsomedude/easyDialog" target="_blank" rel="noopener" class="mycode_url">easyDialog</a></span> - 简化对话框的通用使用方法。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Open-GTO/mdialog" target="_blank" rel="noopener" class="mycode_url">mdialog</a></span> - 现代化的对话框系统，类似于 easyDialog。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Crayder/Model-Sizes-Plus" target="_blank" rel="noopener" class="mycode_url">Model Sizes Plus</a></span> - 更新、更高级、更精确的旧版 modelsizes 包含文件版本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/uPeppe/physics.inc" target="_blank" rel="noopener" class="mycode_url">physics.inc</a></span> - 模拟 2D 和 3D 物理效果（真实运动、碰撞等）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AGraber/samp-async-dialogs" target="_blank" rel="noopener" class="mycode_url">samp-async-dialogs</a></span> - 使用 PawnPlus 任务的异步对话框处理。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/blob/master/includes/speedcap.inc" target="_blank" rel="noopener" class="mycode_url">speedcap.inc</a></span> - 一个控制车辆速度的包含文件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Kirima2nd/samp-command-guess" target="_blank" rel="noopener" class="mycode_url">SA:MP Command Guess</a></span> - 使用莱文斯坦距离函数为 SA:MP 实现的命令猜测器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/wuzi/vending" target="_blank" rel="noopener" class="mycode_url">vending</a></span> - SA-MP 的服务器端自动售货机。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/strlib" target="_blank" rel="noopener" class="mycode_url">strlib</a></span> - 一系列实用的字符串函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ScavengeSurvive/mathutil" target="_blank" rel="noopener" class="mycode_url">mathutil</a></span> - 一系列实用的数学函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/sampctl/rotations.inc" target="_blank" rel="noopener" class="mycode_url">rotations.inc</a></span> - 一系列实用的旋转函数，来源于 Nero_3D 的 rotations.inc。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/samp-distance" target="_blank" rel="noopener" class="mycode_url">SA-MP Distance Functions</a></span> - 一系列实用的距离检测函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/emmet-jones/New-SA-MP-callbacks" target="_blank" rel="noopener" class="mycode_url">New SA-MP callbacks</a></span> - 一系列实用的新回调函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/Alternative-Dialogs" target="_blank" rel="noopener" class="mycode_url">Alternative Dialogs</a></span> - 具有全新设计的文本绘图对话框。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/TommyB123/eSelection" target="_blank" rel="noopener" class="mycode_url">eSelection</a></span> - 增加在 SA-MP 游戏模式中创建动态模型选择菜单的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/alextwothousand/mSelection" target="_blank" rel="noopener" class="mycode_url">mSelection</a></span> - 与 eSelection 类似，但风格不同。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/adib-yg/SAMP-RGB-Textdraw" target="_blank" rel="noopener" class="mycode_url">RGB-Textdraw</a></span> - 为文本绘图添加 RGB 颜色支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/mysy00/LangPlus" target="_blank" rel="noopener" class="mycode_url">LangPlus</a></span> - 为 open.mp 服务器提供的多语言库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://beckzy.net/index.php?action=downloads;sa=view;id=41" target="_blank" rel="noopener" class="mycode_url">beckzy's mod shops</a></span> - 一个用于服务器端改装店的包含文件。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">命令处理器</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/YashasSamaga/I-ZCMD" target="_blank" rel="noopener" class="mycode_url">I-ZCMD</a></span> - ZCMD 的改进版本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.CMD" target="_blank" rel="noopener" class="mycode_url">Pawn.CMD</a></span> - 比任何其他命令处理器都快。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/YSI-Includes/blob/5.x/YSI_Visual/y_commands.md" target="_blank" rel="noopener" class="mycode_url">y_commands</a></span> - 来自 YSI Includes 的命令处理器。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/samp-plugin-jit-backup" target="_blank" rel="noopener" class="mycode_url">JIT</a></span> - 代码稳定后，使用此插件可以显著提高速度。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-plugin-crashdetect" target="_blank" rel="noopener" class="mycode_url">CrashDetect</a></span> - 在测试期间用于查找错误的开发工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/samp-plugin-profiler-backup" target="_blank" rel="noopener" class="mycode_url">Profiler</a></span> - SA-MP 服务器的性能分析器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/sscanf" target="_blank" rel="noopener" class="mycode_url">sscanf</a></span> - 将字符串转换为多个值、整数、浮点数、玩家等。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pBlueG/SA-MP-MySQL" target="_blank" rel="noopener" class="mycode_url">MySQL Plugin</a></span> - 将服务器连接到 MySQL 数据库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-streamer-plugin" target="_blank" rel="noopener" class="mycode_url">Streamer Plugin</a></span> - 绕过许多 SA:MP 限制，例如物体和拾取物的数量限制。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/plugins/nativechecker.zip" target="_blank" rel="noopener" class="mycode_url">nativechecker</a></span> - 在服务器启动时检查原生函数。在 open.mp 中不需要，因为 open.mp 自带原生函数检查机制。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ziggi/FCNPC" target="_blank" rel="noopener" class="mycode_url">FCNPC</a></span> - 一个为 SA-MP 服务器添加大量功能给现有标准 NPC 的插件。它在 open.mp 中无法使用，但你可以改用官方的 NPC 组件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/JaTochNietDan/SA-MP-FileManager" target="_blank" rel="noopener" class="mycode_url">FileManager</a></span> - 允许你管理根文件夹中的文件和文件夹（通过此插件，不局限于 scriptfiles 服务器目录）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.RakNet" target="_blank" rel="noopener" class="mycode_url">Pawn.Raknet</a></span> - 允许你分析 RakNet 流量。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/bmisiak/samp-precise-timers" target="_blank" rel="noopener" class="mycode_url">samp-precise-timers</a></span> - 一个用 Rust 编写的 SA-MP 插件，提供精确计时器。在 open.mp 中不需要，因为 open.mp 自带精确计时器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/PawnPlus" target="_blank" rel="noopener" class="mycode_url">PawnPlus</a></span> - 通过新的结构、数据类型和编程技术扩展 Pawn 脚本语言的可能性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/BigETI/pawn-memory" target="_blank" rel="noopener" class="mycode_url">PAWN memory access</a></span> - 允许在 PAWN 中从堆中分配和释放内存。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/NativeFallback" target="_blank" rel="noopener" class="mycode_url">Native Fallback</a></span> - SA-MP 插件，为未注册的原生函数提供回退实现。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/YSF" target="_blank" rel="noopener" class="mycode_url">YSF</a></span> - 一个旨在从服务器中挖掘最大可能性的插件，主要通过内存编辑和钩子实现。它的许多功能现在已经内置在 open.mp 中。请参阅 <a href="https://github.com/openmultiplayer/open.mp/issues/189" target="_blank" rel="noopener" class="mycode_url">这个 github issue</a> 了解功能列表。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/SKY" target="_blank" rel="noopener" class="mycode_url">SKY</a></span> - 该插件提供底层函数，让 Pawn 脚本能够执行强大的操作。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.Regex" target="_blank" rel="noopener" class="mycode_url">Pawn.Regex</a></span> - 为 Pawn 添加正则表达式支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/pawn-scraper" target="_blank" rel="noopener" class="mycode_url">pawn-scraper</a></span> - 一个强大的爬虫插件，提供了在 pawn 中使用 html 解析器和 css 选择器的接口。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/philip1337/samp-plugin-totp" target="_blank" rel="noopener" class="mycode_url">TOTP</a></span> - 允许在 sa-mp 游戏模式中使用 TOTP 身份验证。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-dns-plugin" target="_blank" rel="noopener" class="mycode_url">DNS Plugin</a></span> - 该插件提供 DNS 查找和反向 DNS 查找的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-plugin-mapandreas" target="_blank" rel="noopener" class="mycode_url">MapAndreas</a></span> - 允许你加载不同的高度图并检查 x, y 坐标处的最低高度。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Pottus/ColAndreas" target="_blank" rel="noopener" class="mycode_url">ColAndreas</a></span> - 创建一个圣安地列斯世界的模拟。使用 Bullet Physics 库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://bitbucket.org/Pamdex/pathfinder/src/master" target="_blank" rel="noopener" class="mycode_url">PathFinder</a></span> - 允许你计算圣安地列斯地图上从 A 点到 B 点的路线。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/spmn/samp-custom-query-flood-check" target="_blank" rel="noopener" class="mycode_url">Custom Query Flood Check</a></span> - 编写针对查询洪水攻击的自定义保护措施。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/YashasSamaga/sampml" target="_blank" rel="noopener" class="mycode_url">sampml</a></span> - 简化的机器学习工具包及相关 SAMP 项目（如自瞄检测）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/tgconnector" target="_blank" rel="noopener" class="mycode_url">TgConnector</a></span> - 一个电报连接器插件，帮助通过 SA-MP 与电报机器人交互。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-discord-connector" target="_blank" rel="noopener" class="mycode_url">Discord connector</a></span> - 允许你从 PAWN 脚本中控制 Discord 机器人。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-tsconnector" target="_blank" rel="noopener" class="mycode_url">TSConnector</a></span> - 允许你从 PAWN 脚本中控制 Teamspeak3 服务器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-irc-plugin" target="_blank" rel="noopener" class="mycode_url">IRC Plugin</a></span> - 允许通过 SA-MP 服务器创建和管理 IRC 机器人。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-requests" target="_blank" rel="noopener" class="mycode_url">pawn-requests</a></span> - 提供了一个与 HTTP(S) API 交互的 API，支持文本和 JSON 数据类型。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-redis" target="_blank" rel="noopener" class="mycode_url">pawn-redis</a></span> - 授予对快速内存数据库的访问权限，以及与其他程序之间的异步消息通道。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-chrono" target="_blank" rel="noopener" class="mycode_url">Chrono</a></span> - 一个用于处理日期和时间的现代 Pawn 库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ziggi/rustext" target="_blank" rel="noopener" class="mycode_url">rustext</a></span> - SA-MP 的俄文文本修复插件：修复 GameText、TextDraw 和 Menu。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/KrYpToDeN/Advanced-SA-NickName" target="_blank" rel="noopener" class="mycode_url">Advanced SA NickName</a></span> - 支持昵称中的任何符号。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Hual/SAMPSON" target="_blank" rel="noopener" class="mycode_url">SAMPSON</a></span> - 一个 SA-MP 的 JSON 插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/SimoSbara/samp-chatbot" target="_blank" rel="noopener" class="mycode_url">samp-chatbot</a></span> - 一个用于在游戏内进行 AI 聊天机器人通信的 GTA SAMP 插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-bscrashfix" target="_blank" rel="noopener" class="mycode_url">SAMP BitStream Crash Fix</a></span> - 修复了 BitStream 读取溢出的问题。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-json" target="_blank" rel="noopener" class="mycode_url">pawn-json</a></span> - 为 Pawn 提供的 JSON 支持。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">客户端-服务器插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Hual/SA-MP-Plus" target="_blank" rel="noopener" class="mycode_url">SA-MP+</a></span> - 一个客户端修改，利用 SA-MP 的插件 SDK 与服务器交互并添加新功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/dotSILENT/chandling" target="_blank" rel="noopener" class="mycode_url">CHandling</a></span> - 通过修改游戏的默认行为，为单个车辆分配车辆操控数据的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/CyberMor/sampvoice" target="_blank" rel="noopener" class="mycode_url">SAMPVOICE</a></span> - 在 SA:MP 服务器的 Pawn 语言中实现语音通信系统。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/CyberMor/keylistener" target="_blank" rel="noopener" class="mycode_url">KeyListener</a></span> - 用于跟踪任何按键的客户端-服务器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ZOTTCE/samp-cef" target="_blank" rel="noopener" class="mycode_url">SAMP CEF</a></span> - 为 SA:MP 嵌入 CEF 的客户端和服务器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Whitetigerswt/SAMP_AC_v2" target="_blank" rel="noopener" class="mycode_url">SAMP_AC_v2</a></span> - SA:MP 客户端反作弊。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">加密插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-whirlpool" target="_blank" rel="noopener" class="mycode_url">whirlpool</a></span> - SA:MP 的 Whirlpool 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/samp-bcrypt" target="_blank" rel="noopener" class="mycode_url">SyS' bcrypt Plugin</a></span> - 由 Sreyas Sreelal 为 SA:MP 制作的 Bcrypt 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/lassir/bcrypt-samp" target="_blank" rel="noopener" class="mycode_url">lassir's bcrypt Plugin</a></span> - 由 lassir 为 SA:MP 制作的 Bcrypt 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/alextwothousand/samp-crypto" target="_blank" rel="noopener" class="mycode_url">samp-crypto</a></span> - 为 SA:MP 提供的一系列加密函数，如 Argon2、Scrypt 和 Bcrypt。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/plugins/SHA512.zip" target="_blank" rel="noopener" class="mycode_url">SHA512</a></span> - SA:MP 的 SHA512 加密插件。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">GDK/SDK</h3><br />
<br />
现在，你可以使用 open.mp 在不借助任何插件的情况下，用 Pawn 以外的语言编写脚本。请参阅 <a href="https://www.open.mp/blog/release-candidate-1" target="_blank" rel="noopener" class="mycode_url">这篇博客文章</a>。<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-plugin-sdk" target="_blank" rel="noopener" class="mycode_url">sampsdk</a></span> - 这是开发插件所需的最基本内容。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/sampgdk-backup" target="_blank" rel="noopener" class="mycode_url">sampgdk</a></span> - 为 SA:MP 编写游戏模式的 C/C++ 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ikkentim/SampSharp" target="_blank" rel="noopener" class="mycode_url">SampSharp</a></span> - 为 SA:MP 编写游戏模式的 C# 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Seregamil/.NET-plugin" target="_blank" rel="noopener" class="mycode_url">.NET Plugin</a></span> - 为 SA:MP 编写插件的 C# 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/sampgo/sampgo" target="_blank" rel="noopener" class="mycode_url">sampgo</a></span> - 为 SA:MP 编写游戏模式/插件的 Go 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-node" target="_blank" rel="noopener" class="mycode_url">samp-node</a></span> - 为 SA:MP 编写游戏模式的 Javascript/Typescript 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Shoebill/ShoebillPlugin" target="_blank" rel="noopener" class="mycode_url">Shoebill Project</a></span> - 为 SA:MP 编写游戏模式的 Java 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/habecker/PySAMP" target="_blank" rel="noopener" class="mycode_url">pySAMP</a></span> - 为 SA:MP 编写游戏模式的 Python 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ZOTTCE/samp-rs" target="_blank" rel="noopener" class="mycode_url">samp-rs</a></span> - 为 SA:MP 编写插件的 Rust 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/YALP" target="_blank" rel="noopener" class="mycode_url">Yet Another Lua Plugin</a></span> - 为 SA:MP 编写游戏模式的 Lua 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Lapayo/SAMPHP" target="_blank" rel="noopener" class="mycode_url">SAMPHP</a></span> - 为 SA:MP 编写游戏模式的 PHP 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">[SA-MP S[D]K](<a href="https://github.com/Hual/SA-MP-S-D-K" target="_blank" rel="noopener" class="mycode_url">https://github.com/Hual/SA-MP-S-D-K</a>)</span> - 为 SA:MP 编写游戏模式的 D 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Double-O-Seven/kamp" target="_blank" rel="noopener" class="mycode_url">Kamp</a></span> - 为 SA:MP 编写游戏模式的 Kotlin 语言支持。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">游戏模式</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/midosvt/omp-base-script" target="_blank" rel="noopener" class="mycode_url">Simple base script</a></span> - 一个帮助初学者入门的简单基础脚本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/ScavengeSurvive" target="_blank" rel="noopener" class="mycode_url">ScavengeSurvive</a></span> - 基于 PvP 的生存游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/gta-open" target="_blank" rel="noopener" class="mycode_url">gta-open</a></span> - 一个以洛圣都为背景的警察与匪徒模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/zeelorenc/sf-cnr" target="_blank" rel="noopener" class="mycode_url">SF-CnR</a></span> - 为 SA-MP 开发的圣费耶罗警察与匪徒游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NextGenerationGamingLLC/SA-MP-Development" target="_blank" rel="noopener" class="mycode_url">Next Generation Roleplay</a></span> - Next Generation Gaming, LLC 的 SA:MP 游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/seanny/SC-RP" target="_blank" rel="noopener" class="mycode_url">SC-RP</a></span> - 一个支持 MySQL 的角色扮演游戏模式。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">滤镜脚本</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/MapFix" target="_blank" rel="noopener" class="mycode_url">MapFix</a></span> - 修复 GTA 圣安地列斯地图的纹理错误。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-animbrowse" target="_blank" rel="noopener" class="mycode_url">SA:MP Animbrowse</a></span> - SA:MP 的动画浏览器工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Fairuz-Afdhal/IsPlayerUsingAndroid" target="_blank" rel="noopener" class="mycode_url">IsPlayerUsingAndroid</a></span> - 检查玩家是否为安卓用户。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Nickk888SAMP/TextDraw-Editor" target="_blank" rel="noopener" class="mycode_url">Nickk's TextDraw Editor</a></span> - 一个具有丰富功能的文本绘图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/nexquery/samp-textdraw-editor" target="_blank" rel="noopener" class="mycode_url">Nexor's Textdraw Editor</a></span> - 此编辑器提供许多功能，如分组、恢复删除的文本、撤销更改、从文件导入文本绘图等。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/Ultimate-Creator" target="_blank" rel="noopener" class="mycode_url">Ultimate Creator</a></span> - 具有众多功能的高级地图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/fusez/Map-Editor-V3" target="_blank" rel="noopener" class="mycode_url">Fusez's Map Editor</a></span> - SA:MP 的游戏内地图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Pottus/Texture-Studio" target="_blank" rel="noopener" class="mycode_url">Texture Studio</a></span> - 这是一个游戏内地图编辑器，允许你为物体贴图，最多支持材质索引 15（16 种材质），并可为该材质索引设置颜色。<br />
</li>
</ul>
]]></description>
			<content:encoded><![CDATA[<hr class="mycode_hr" />
为 SA-MP 开发精选的实用工具、库、游戏模式、滤镜脚本和插件列表。<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">工具</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/compiler" target="_blank" rel="noopener" class="mycode_url">Community Compiler</a></span> - 一个大幅更新的编译器版本，包含众多修复和增强功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/sampctl" target="_blank" rel="noopener" class="mycode_url">sampctl</a></span> - 用于安装库和运行服务器的包管理器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Zeex/samp-plugin-runner" target="_blank" rel="noopener" class="mycode_url">Plugin Runner</a></span> - 用于直接从命令行运行轻量级服务器版本（无需 server.cfg）以测试插件的工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-plugin-boilerplate" target="_blank" rel="noopener" class="mycode_url">Plugin Boilerplate</a></span> - 通过样板代码简化插件的创建。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/samp-ptl" target="_blank" rel="noopener" class="mycode_url">SA:MP Plugin Template Library</a></span> - 使用此模板库，可以非常轻松快速地制作自己的插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://fiddle.sa-mp.dev" target="_blank" rel="noopener" class="mycode_url">SA-MP Fiddle</a></span> - 一个测试脚本（代码片段、概念验证、调试等）并分享给其他人的地方。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://packagecontrol.io/packages/Pawn%20syntax" target="_blank" rel="noopener" class="mycode_url">Pawn Syntax - Sublime</a></span> - 为 Sublime Text 提供的 Pawn 自动补全。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://marketplace.visualstudio.com/items?itemName=southclaws.vscode-pawn" target="_blank" rel="noopener" class="mycode_url">Pawn Syntax - Visual Marketplace</a></span> - 为 Visual Studio Code 提供的 Pawn 自动补全。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://bitbucket.org/Grimrandomer/samp-zone-editor/downloads" target="_blank" rel="noopener" class="mycode_url">SA-MP Zone Editor</a></span> - 用于制作区域等的区域编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/tools/Map%20Editor.zip" target="_blank" rel="noopener" class="mycode_url">SA-MP Map Editor</a></span> - 流行的 SA:MP 地图编辑器。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">库</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/samp-stdlib" target="_blank" rel="noopener" class="mycode_url">samp-stdlib</a></span> - 默认包含文件的更新版本。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 正确、文档齐全且完整。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/sa-mp-fixes" target="_blank" rel="noopener" class="mycode_url">fixes.inc</a></span> - 针对大量 SA:MP 服务器错误的高度优化修复。即插即用。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/YSI-Includes" target="_blank" rel="noopener" class="mycode_url">YSI-Includes</a></span> - 为 SA:MP/pawn 开发的最古老、最大、经过最充分测试且支持最完善的库，提供了大量新的游戏和语言特性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Open-GTO/foreach" target="_blank" rel="noopener" class="mycode_url">foreach</a></span> - 独立的 foreach 包含文件（非 y_iterate 版本）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/amx_assembly" target="_blank" rel="noopener" class="mycode_url">amx_assembly</a></span> - 对 pawn 脚本本身的底层访问。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/md-sort" target="_blank" rel="noopener" class="mycode_url">md-sort</a></span> - 在 Pawn 中对多维数组进行排序。修改数组的内部指针，而不是复制数据。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/indirection" target="_blank" rel="noopener" class="mycode_url">indirection</a></span> - 用于传递指针和间接调用函数的系统，并提供了自定义调用的抽象方法。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/code-parse.inc" target="_blank" rel="noopener" class="mycode_url">code-parse.inc</a></span> - 在编译时解析和自定义 pawn 代码。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Vince0789/sa-mp-extended-vehicle-information" target="_blank" rel="noopener" class="mycode_url">Extended Vehicle Information</a></span> - 将单人游戏中的大量车辆标志导入 SQLite 数据库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/sqlitei" target="_blank" rel="noopener" class="mycode_url">sqlitei</a></span> - 为 SA-MP SQLite 函数提供的高级 API。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/samp-weapon-config" target="_blank" rel="noopener" class="mycode_url">weapon-config</a></span> - 更一致、响应更快的伤害系统，并包含许多新特性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/SAMP-geoip" target="_blank" rel="noopener" class="mycode_url">samp-geoip</a></span> - 基于 IP 地址的地理位置信息。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/progress2" target="_blank" rel="noopener" class="mycode_url">progress2</a></span> - 将时间、生命值、车辆燃料等内容显示为进度条。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/itsneufox/GameText-Plus" target="_blank" rel="noopener" class="mycode_url">GameText+</a></span> - 一个为 SA-MP 和 open.mp 改进原生 GameText 的包含文件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-weapon-data" target="_blank" rel="noopener" class="mycode_url">weapon-data</a></span> - 精细调校、可自定义的武器数据。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/MichaelBelgium/MV_Youtube" target="_blank" rel="noopener" class="mycode_url">MV_Youtube</a></span> - 用于音频流的 YouTube 转换器 API。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/MySQL-Prepared-Statements" target="_blank" rel="noopener" class="mycode_url">MySQL Prepared Statements</a></span> - 为 PAWN MySQL 插件模拟预处理语句。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Brunoo16/samp-server-weapons" target="_blank" rel="noopener" class="mycode_url">samp-server-weapons</a></span> - 完全由服务器控制的武器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/actor_robbery" target="_blank" rel="noopener" class="mycode_url">actor_robbery</a></span> - 灵感来自 GTA V 的商店抢劫。actor_robbery.inc 模仿了该功能！<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-aviation" target="_blank" rel="noopener" class="mycode_url">samp-aviation</a></span> - 一个基于俯仰角的高度自动控制和基于横滚角的航向自动控制的基础系统。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-logger" target="_blank" rel="noopener" class="mycode_url">samp-logger</a></span> - 简单的结构化日志记录器，提供了一组简单的日志记录和调试函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/tdworg/samp-include-rscan" target="_blank" rel="noopener" class="mycode_url">TDW Recursion Scanner</a></span> - 一个查找代码中递归的库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Awsomedude/easyDialog" target="_blank" rel="noopener" class="mycode_url">easyDialog</a></span> - 简化对话框的通用使用方法。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Open-GTO/mdialog" target="_blank" rel="noopener" class="mycode_url">mdialog</a></span> - 现代化的对话框系统，类似于 easyDialog。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Crayder/Model-Sizes-Plus" target="_blank" rel="noopener" class="mycode_url">Model Sizes Plus</a></span> - 更新、更高级、更精确的旧版 modelsizes 包含文件版本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/uPeppe/physics.inc" target="_blank" rel="noopener" class="mycode_url">physics.inc</a></span> - 模拟 2D 和 3D 物理效果（真实运动、碰撞等）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AGraber/samp-async-dialogs" target="_blank" rel="noopener" class="mycode_url">samp-async-dialogs</a></span> - 使用 PawnPlus 任务的异步对话框处理。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/blob/master/includes/speedcap.inc" target="_blank" rel="noopener" class="mycode_url">speedcap.inc</a></span> - 一个控制车辆速度的包含文件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Kirima2nd/samp-command-guess" target="_blank" rel="noopener" class="mycode_url">SA:MP Command Guess</a></span> - 使用莱文斯坦距离函数为 SA:MP 实现的命令猜测器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/wuzi/vending" target="_blank" rel="noopener" class="mycode_url">vending</a></span> - SA-MP 的服务器端自动售货机。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/strlib" target="_blank" rel="noopener" class="mycode_url">strlib</a></span> - 一系列实用的字符串函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ScavengeSurvive/mathutil" target="_blank" rel="noopener" class="mycode_url">mathutil</a></span> - 一系列实用的数学函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/sampctl/rotations.inc" target="_blank" rel="noopener" class="mycode_url">rotations.inc</a></span> - 一系列实用的旋转函数，来源于 Nero_3D 的 rotations.inc。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/samp-distance" target="_blank" rel="noopener" class="mycode_url">SA-MP Distance Functions</a></span> - 一系列实用的距离检测函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/emmet-jones/New-SA-MP-callbacks" target="_blank" rel="noopener" class="mycode_url">New SA-MP callbacks</a></span> - 一系列实用的新回调函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/Alternative-Dialogs" target="_blank" rel="noopener" class="mycode_url">Alternative Dialogs</a></span> - 具有全新设计的文本绘图对话框。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/TommyB123/eSelection" target="_blank" rel="noopener" class="mycode_url">eSelection</a></span> - 增加在 SA-MP 游戏模式中创建动态模型选择菜单的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/alextwothousand/mSelection" target="_blank" rel="noopener" class="mycode_url">mSelection</a></span> - 与 eSelection 类似，但风格不同。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/adib-yg/SAMP-RGB-Textdraw" target="_blank" rel="noopener" class="mycode_url">RGB-Textdraw</a></span> - 为文本绘图添加 RGB 颜色支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/mysy00/LangPlus" target="_blank" rel="noopener" class="mycode_url">LangPlus</a></span> - 为 open.mp 服务器提供的多语言库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://beckzy.net/index.php?action=downloads;sa=view;id=41" target="_blank" rel="noopener" class="mycode_url">beckzy's mod shops</a></span> - 一个用于服务器端改装店的包含文件。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">命令处理器</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/YashasSamaga/I-ZCMD" target="_blank" rel="noopener" class="mycode_url">I-ZCMD</a></span> - ZCMD 的改进版本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.CMD" target="_blank" rel="noopener" class="mycode_url">Pawn.CMD</a></span> - 比任何其他命令处理器都快。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/YSI-Includes/blob/5.x/YSI_Visual/y_commands.md" target="_blank" rel="noopener" class="mycode_url">y_commands</a></span> - 来自 YSI Includes 的命令处理器。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/samp-plugin-jit-backup" target="_blank" rel="noopener" class="mycode_url">JIT</a></span> - 代码稳定后，使用此插件可以显著提高速度。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-plugin-crashdetect" target="_blank" rel="noopener" class="mycode_url">CrashDetect</a></span> - 在测试期间用于查找错误的开发工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/samp-plugin-profiler-backup" target="_blank" rel="noopener" class="mycode_url">Profiler</a></span> - SA-MP 服务器的性能分析器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/sscanf" target="_blank" rel="noopener" class="mycode_url">sscanf</a></span> - 将字符串转换为多个值、整数、浮点数、玩家等。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pBlueG/SA-MP-MySQL" target="_blank" rel="noopener" class="mycode_url">MySQL Plugin</a></span> - 将服务器连接到 MySQL 数据库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-streamer-plugin" target="_blank" rel="noopener" class="mycode_url">Streamer Plugin</a></span> - 绕过许多 SA:MP 限制，例如物体和拾取物的数量限制。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/plugins/nativechecker.zip" target="_blank" rel="noopener" class="mycode_url">nativechecker</a></span> - 在服务器启动时检查原生函数。在 open.mp 中不需要，因为 open.mp 自带原生函数检查机制。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ziggi/FCNPC" target="_blank" rel="noopener" class="mycode_url">FCNPC</a></span> - 一个为 SA-MP 服务器添加大量功能给现有标准 NPC 的插件。它在 open.mp 中无法使用，但你可以改用官方的 NPC 组件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/JaTochNietDan/SA-MP-FileManager" target="_blank" rel="noopener" class="mycode_url">FileManager</a></span> - 允许你管理根文件夹中的文件和文件夹（通过此插件，不局限于 scriptfiles 服务器目录）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.RakNet" target="_blank" rel="noopener" class="mycode_url">Pawn.Raknet</a></span> - 允许你分析 RakNet 流量。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/bmisiak/samp-precise-timers" target="_blank" rel="noopener" class="mycode_url">samp-precise-timers</a></span> - 一个用 Rust 编写的 SA-MP 插件，提供精确计时器。在 open.mp 中不需要，因为 open.mp 自带精确计时器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/PawnPlus" target="_blank" rel="noopener" class="mycode_url">PawnPlus</a></span> - 通过新的结构、数据类型和编程技术扩展 Pawn 脚本语言的可能性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/BigETI/pawn-memory" target="_blank" rel="noopener" class="mycode_url">PAWN memory access</a></span> - 允许在 PAWN 中从堆中分配和释放内存。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/NativeFallback" target="_blank" rel="noopener" class="mycode_url">Native Fallback</a></span> - SA-MP 插件，为未注册的原生函数提供回退实现。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/YSF" target="_blank" rel="noopener" class="mycode_url">YSF</a></span> - 一个旨在从服务器中挖掘最大可能性的插件，主要通过内存编辑和钩子实现。它的许多功能现在已经内置在 open.mp 中。请参阅 <a href="https://github.com/openmultiplayer/open.mp/issues/189" target="_blank" rel="noopener" class="mycode_url">这个 github issue</a> 了解功能列表。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/SKY" target="_blank" rel="noopener" class="mycode_url">SKY</a></span> - 该插件提供底层函数，让 Pawn 脚本能够执行强大的操作。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.Regex" target="_blank" rel="noopener" class="mycode_url">Pawn.Regex</a></span> - 为 Pawn 添加正则表达式支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/pawn-scraper" target="_blank" rel="noopener" class="mycode_url">pawn-scraper</a></span> - 一个强大的爬虫插件，提供了在 pawn 中使用 html 解析器和 css 选择器的接口。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/philip1337/samp-plugin-totp" target="_blank" rel="noopener" class="mycode_url">TOTP</a></span> - 允许在 sa-mp 游戏模式中使用 TOTP 身份验证。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-dns-plugin" target="_blank" rel="noopener" class="mycode_url">DNS Plugin</a></span> - 该插件提供 DNS 查找和反向 DNS 查找的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-plugin-mapandreas" target="_blank" rel="noopener" class="mycode_url">MapAndreas</a></span> - 允许你加载不同的高度图并检查 x, y 坐标处的最低高度。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Pottus/ColAndreas" target="_blank" rel="noopener" class="mycode_url">ColAndreas</a></span> - 创建一个圣安地列斯世界的模拟。使用 Bullet Physics 库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://bitbucket.org/Pamdex/pathfinder/src/master" target="_blank" rel="noopener" class="mycode_url">PathFinder</a></span> - 允许你计算圣安地列斯地图上从 A 点到 B 点的路线。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/spmn/samp-custom-query-flood-check" target="_blank" rel="noopener" class="mycode_url">Custom Query Flood Check</a></span> - 编写针对查询洪水攻击的自定义保护措施。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/YashasSamaga/sampml" target="_blank" rel="noopener" class="mycode_url">sampml</a></span> - 简化的机器学习工具包及相关 SAMP 项目（如自瞄检测）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/tgconnector" target="_blank" rel="noopener" class="mycode_url">TgConnector</a></span> - 一个电报连接器插件，帮助通过 SA-MP 与电报机器人交互。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-discord-connector" target="_blank" rel="noopener" class="mycode_url">Discord connector</a></span> - 允许你从 PAWN 脚本中控制 Discord 机器人。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-tsconnector" target="_blank" rel="noopener" class="mycode_url">TSConnector</a></span> - 允许你从 PAWN 脚本中控制 Teamspeak3 服务器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-irc-plugin" target="_blank" rel="noopener" class="mycode_url">IRC Plugin</a></span> - 允许通过 SA-MP 服务器创建和管理 IRC 机器人。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-requests" target="_blank" rel="noopener" class="mycode_url">pawn-requests</a></span> - 提供了一个与 HTTP(S) API 交互的 API，支持文本和 JSON 数据类型。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-redis" target="_blank" rel="noopener" class="mycode_url">pawn-redis</a></span> - 授予对快速内存数据库的访问权限，以及与其他程序之间的异步消息通道。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-chrono" target="_blank" rel="noopener" class="mycode_url">Chrono</a></span> - 一个用于处理日期和时间的现代 Pawn 库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ziggi/rustext" target="_blank" rel="noopener" class="mycode_url">rustext</a></span> - SA-MP 的俄文文本修复插件：修复 GameText、TextDraw 和 Menu。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/KrYpToDeN/Advanced-SA-NickName" target="_blank" rel="noopener" class="mycode_url">Advanced SA NickName</a></span> - 支持昵称中的任何符号。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Hual/SAMPSON" target="_blank" rel="noopener" class="mycode_url">SAMPSON</a></span> - 一个 SA-MP 的 JSON 插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/SimoSbara/samp-chatbot" target="_blank" rel="noopener" class="mycode_url">samp-chatbot</a></span> - 一个用于在游戏内进行 AI 聊天机器人通信的 GTA SAMP 插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-bscrashfix" target="_blank" rel="noopener" class="mycode_url">SAMP BitStream Crash Fix</a></span> - 修复了 BitStream 读取溢出的问题。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-json" target="_blank" rel="noopener" class="mycode_url">pawn-json</a></span> - 为 Pawn 提供的 JSON 支持。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">客户端-服务器插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Hual/SA-MP-Plus" target="_blank" rel="noopener" class="mycode_url">SA-MP+</a></span> - 一个客户端修改，利用 SA-MP 的插件 SDK 与服务器交互并添加新功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/dotSILENT/chandling" target="_blank" rel="noopener" class="mycode_url">CHandling</a></span> - 通过修改游戏的默认行为，为单个车辆分配车辆操控数据的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/CyberMor/sampvoice" target="_blank" rel="noopener" class="mycode_url">SAMPVOICE</a></span> - 在 SA:MP 服务器的 Pawn 语言中实现语音通信系统。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/CyberMor/keylistener" target="_blank" rel="noopener" class="mycode_url">KeyListener</a></span> - 用于跟踪任何按键的客户端-服务器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ZOTTCE/samp-cef" target="_blank" rel="noopener" class="mycode_url">SAMP CEF</a></span> - 为 SA:MP 嵌入 CEF 的客户端和服务器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Whitetigerswt/SAMP_AC_v2" target="_blank" rel="noopener" class="mycode_url">SAMP_AC_v2</a></span> - SA:MP 客户端反作弊。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">加密插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-whirlpool" target="_blank" rel="noopener" class="mycode_url">whirlpool</a></span> - SA:MP 的 Whirlpool 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/samp-bcrypt" target="_blank" rel="noopener" class="mycode_url">SyS' bcrypt Plugin</a></span> - 由 Sreyas Sreelal 为 SA:MP 制作的 Bcrypt 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/lassir/bcrypt-samp" target="_blank" rel="noopener" class="mycode_url">lassir's bcrypt Plugin</a></span> - 由 lassir 为 SA:MP 制作的 Bcrypt 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/alextwothousand/samp-crypto" target="_blank" rel="noopener" class="mycode_url">samp-crypto</a></span> - 为 SA:MP 提供的一系列加密函数，如 Argon2、Scrypt 和 Bcrypt。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/plugins/SHA512.zip" target="_blank" rel="noopener" class="mycode_url">SHA512</a></span> - SA:MP 的 SHA512 加密插件。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">GDK/SDK</h3><br />
<br />
现在，你可以使用 open.mp 在不借助任何插件的情况下，用 Pawn 以外的语言编写脚本。请参阅 <a href="https://www.open.mp/blog/release-candidate-1" target="_blank" rel="noopener" class="mycode_url">这篇博客文章</a>。<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-plugin-sdk" target="_blank" rel="noopener" class="mycode_url">sampsdk</a></span> - 这是开发插件所需的最基本内容。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/sampgdk-backup" target="_blank" rel="noopener" class="mycode_url">sampgdk</a></span> - 为 SA:MP 编写游戏模式的 C/C++ 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ikkentim/SampSharp" target="_blank" rel="noopener" class="mycode_url">SampSharp</a></span> - 为 SA:MP 编写游戏模式的 C# 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Seregamil/.NET-plugin" target="_blank" rel="noopener" class="mycode_url">.NET Plugin</a></span> - 为 SA:MP 编写插件的 C# 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/sampgo/sampgo" target="_blank" rel="noopener" class="mycode_url">sampgo</a></span> - 为 SA:MP 编写游戏模式/插件的 Go 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-node" target="_blank" rel="noopener" class="mycode_url">samp-node</a></span> - 为 SA:MP 编写游戏模式的 Javascript/Typescript 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Shoebill/ShoebillPlugin" target="_blank" rel="noopener" class="mycode_url">Shoebill Project</a></span> - 为 SA:MP 编写游戏模式的 Java 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/habecker/PySAMP" target="_blank" rel="noopener" class="mycode_url">pySAMP</a></span> - 为 SA:MP 编写游戏模式的 Python 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ZOTTCE/samp-rs" target="_blank" rel="noopener" class="mycode_url">samp-rs</a></span> - 为 SA:MP 编写插件的 Rust 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/YALP" target="_blank" rel="noopener" class="mycode_url">Yet Another Lua Plugin</a></span> - 为 SA:MP 编写游戏模式的 Lua 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Lapayo/SAMPHP" target="_blank" rel="noopener" class="mycode_url">SAMPHP</a></span> - 为 SA:MP 编写游戏模式的 PHP 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">[SA-MP S[D]K](<a href="https://github.com/Hual/SA-MP-S-D-K" target="_blank" rel="noopener" class="mycode_url">https://github.com/Hual/SA-MP-S-D-K</a>)</span> - 为 SA:MP 编写游戏模式的 D 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Double-O-Seven/kamp" target="_blank" rel="noopener" class="mycode_url">Kamp</a></span> - 为 SA:MP 编写游戏模式的 Kotlin 语言支持。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">游戏模式</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/midosvt/omp-base-script" target="_blank" rel="noopener" class="mycode_url">Simple base script</a></span> - 一个帮助初学者入门的简单基础脚本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/ScavengeSurvive" target="_blank" rel="noopener" class="mycode_url">ScavengeSurvive</a></span> - 基于 PvP 的生存游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/gta-open" target="_blank" rel="noopener" class="mycode_url">gta-open</a></span> - 一个以洛圣都为背景的警察与匪徒模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/zeelorenc/sf-cnr" target="_blank" rel="noopener" class="mycode_url">SF-CnR</a></span> - 为 SA-MP 开发的圣费耶罗警察与匪徒游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NextGenerationGamingLLC/SA-MP-Development" target="_blank" rel="noopener" class="mycode_url">Next Generation Roleplay</a></span> - Next Generation Gaming, LLC 的 SA:MP 游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/seanny/SC-RP" target="_blank" rel="noopener" class="mycode_url">SC-RP</a></span> - 一个支持 MySQL 的角色扮演游戏模式。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">滤镜脚本</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/MapFix" target="_blank" rel="noopener" class="mycode_url">MapFix</a></span> - 修复 GTA 圣安地列斯地图的纹理错误。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-animbrowse" target="_blank" rel="noopener" class="mycode_url">SA:MP Animbrowse</a></span> - SA:MP 的动画浏览器工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Fairuz-Afdhal/IsPlayerUsingAndroid" target="_blank" rel="noopener" class="mycode_url">IsPlayerUsingAndroid</a></span> - 检查玩家是否为安卓用户。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Nickk888SAMP/TextDraw-Editor" target="_blank" rel="noopener" class="mycode_url">Nickk's TextDraw Editor</a></span> - 一个具有丰富功能的文本绘图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/nexquery/samp-textdraw-editor" target="_blank" rel="noopener" class="mycode_url">Nexor's Textdraw Editor</a></span> - 此编辑器提供许多功能，如分组、恢复删除的文本、撤销更改、从文件导入文本绘图等。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/Ultimate-Creator" target="_blank" rel="noopener" class="mycode_url">Ultimate Creator</a></span> - 具有众多功能的高级地图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/fusez/Map-Editor-V3" target="_blank" rel="noopener" class="mycode_url">Fusez's Map Editor</a></span> - SA:MP 的游戏内地图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Pottus/Texture-Studio" target="_blank" rel="noopener" class="mycode_url">Texture Studio</a></span> - 这是一个游戏内地图编辑器，允许你为物体贴图，最多支持材质索引 15（16 种材质），并可为该材质索引设置颜色。<br />
</li>
</ul>
]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[教程] 枚举器 enum 详细讲解 原文作者: iPLEOMAX]]></title>
			<link>https://open-mp.cn/showthread.php?tid=26</link>
			<pubDate>Sun, 22 Mar 2026 00:11:14 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=26</guid>
			<description><![CDATA[<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">枚举器</h3><br />
<br />
原文作者: iPLEOMAX<br />
<br />
关于枚举，有些细节很多脚本作者并不清楚。<br />
<br />
很多人都喜欢在脚本里用枚举来存玩家数据、车辆数据、房屋数据之类的，尤其是用户信息这块。<br />
<br />
一个很典型的写法是这样的：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_PLAYER_INFO<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SCORE,<br />
&nbsp;&nbsp;&nbsp;&nbsp;MONEY,<br />
&nbsp;&nbsp;&nbsp;&nbsp;KILLS,<br />
&nbsp;&nbsp;&nbsp;&nbsp;DEATHS<br />
};<br />
<br />
new pInfo[MAX_PLAYERS][E_PLAYER_INFO];</code></div></div><br />
用起来大概是这样：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
public OnPlayerDeath(playerid, killerid, reason)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;pInfo[playerid][DEATHS]++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(IsPlayerConnected(killerid) &amp;&amp; killerid != playerid)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pInfo[killerid][KILLS]++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
这段应该不难理解。<br />
<br />
现在我们看另一个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_PLAYER_INFO<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SCORE,<br />
&nbsp;&nbsp;&nbsp;&nbsp;MONEY = 9,<br />
&nbsp;&nbsp;&nbsp;&nbsp;KILLS = 5,<br />
&nbsp;&nbsp;&nbsp;&nbsp;DEATHS = 56<br />
};<br />
<br />
new pInfo[MAX_PLAYERS][E_PLAYER_INFO];<br />
<br />
printf("%i | %i | %i | %i", pInfo[0][SCORE], pInfo[0][MONEY], pInfo[0][KILLS], pInfo[0][DEATHS]);</code></div></div><br />
你可能会觉得输出是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0 | 9 | 5 | 56</code>，对吧？<br />
<br />
如果你这么想，那就错了。实际上输出是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0 | 0 | 0 | 0</code>。<br />
<br />
你可能会以为枚举是用来存储数据的，但事实并非如此。我在枚举里写了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MONEY = 9</code>，然后在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 里用了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pInfo[0][MONEY]</code>，但编译器其实把它当成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pInfo[0][9]</code> 来处理，而不是什么 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_PLAYER_INFO:MONEY</code>。也就是说，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MONEY</code> 在这里只是作为一个<span style="font-weight: bold;" class="mycode_b">索引</span>来用的。<br />
<br />
所以枚举本质上<span style="font-weight: bold;" class="mycode_b">根本不是变量</span>，它其实就是一组<span style="font-weight: bold;" class="mycode_b">常量</span>，只不过帮你的数组索引起了个好记的名字罢了。<br />
<br />
好，我们再来深入一点，应该能让你理解得更清楚。<br />
<br />
举个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
const e_CAR1 = 0;<br />
const e_CAR2 = 1;<br />
const e_CAR3 = 2;<br />
<br />
new MyCars[3];<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR1] = 520;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR2] = 458;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR3] = 411;<br />
}</code></div></div><br />
现在我们用枚举重写一下：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum e_TEST<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR1,<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR2,<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR3<br />
};<br />
<br />
new MyCars[e_TEST];<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR1] = 520;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR2] = 458;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR3] = 411;<br />
}</code></div></div><br />
这两段代码都能正常编译，做的事情也完全一样。你看出区别了吗？其实就只是代码写法不同而已。<br />
<br />
这个例子告诉我们，枚举干的事情和常量是一样的。不过枚举有些地方比常量或者宏定义（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const e_CAR1 = 0;</code> 或者 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define e_CAR1 0</code>）更好用，具体差异我们后面再说。<br />
<br />
首先你需要明白枚举的结构：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp; Abc,<br />
&nbsp;&nbsp; Def,<br />
&nbsp;&nbsp; Ghi,<br />
};</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Abc</code> 是一个值为 0 的常量（差不多等于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const Abc = 0;</code> 或 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define Abc 0</code>），<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Def</code> 是值为 1 的常量，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Ghi</code> 是值为 2 的常量。<br />
<br />
预编译器会自动给这些常量赋值，从 0 开始一直往上排。而用常量的时候，你得自己手动赋值。枚举则是自动帮你排好的。<br />
<br />
再看个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp; e_ONE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 自动得到 0<br />
&nbsp;&nbsp; e_TWO,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 得到 1<br />
&nbsp;&nbsp; e_THREE,&nbsp;&nbsp;&nbsp;&nbsp;// 得到 2<br />
&nbsp;&nbsp; e_FOUR = 12,// 这里手动赋了 12，所以不再是 3 了<br />
&nbsp;&nbsp; e_FIVE,&nbsp;&nbsp;&nbsp;&nbsp; // 变成 13，因为上一个值是 12<br />
&nbsp;&nbsp; e_SIX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 变成 14，上一个值是 13<br />
}</code></div></div><br />
看到了吧，如果你手动给某个枚举项赋了值，后面的项就会在此基础上依次加 1。<br />
<br />
再来看看更复杂的情况：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum DATA<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;INT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 得到 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;STRING[10],&nbsp;&nbsp;&nbsp;&nbsp; // 得到 1，但因为是数组，一个位置不够，它会占 10 个位置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 所以实际占用的索引是 1, 2, 3, 4, 5, 6, 7, 8, 9, 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;INT2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 得到 11，因为 STRING 最后一位是 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;STRING2[10]&nbsp;&nbsp;&nbsp;&nbsp; // 从 12 开始，一直到 22，需要 10 个位置<br />
};</code></div></div><br />
运行下面的代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
printf("%i", _:DATA);</code></div></div><br />
结果输出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">22</code>。<br />
<br />
因为整个枚举的总大小是 22：<br />
INT 占 1 个 + STRING 占 10 个 + INT2 占 1 个 + STRING2 占 10 个 = 22。<br />
<br />
你可能会问，为什么我写 INT 是 1 而不是 0？因为这里我数的是<span style="font-weight: bold;" class="mycode_b">占用了多少个位置</span>，不是<span style="font-weight: bold;" class="mycode_b">从哪个位置开始</span>。如果问起始位置，那 INT 确实是 0。<br />
<br />
一个大小为 22 的块，索引范围是 0 到 21，总共 22 个位置。<br />
<br />
再试一下：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
printf("%i", _:STRING);</code></div></div><br />
输出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1</code>。因为第一个位置（索引 0）被 INT 占了，所以 STRING 从索引 1 开始。<br />
<br />
每个枚举项占用的位置是这样的：<ul class="mycode_list"><li>INT：索引 0<br />
</li>
<li>STRING：索引 1 到 10<br />
</li>
<li>INT2：索引 11<br />
</li>
<li>STRING2：索引 12 到 21<br />
</li>
</ul>
<br />
运行这段：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new Array[DATA];<br />
printf("%i", sizeof Array);</code></div></div><br />
结果也是 22，因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">DATA</code> 的大小就是 22。<br />
<br />
所以，这个数组实际上相当于：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
Array[INT + STRING + INT2 + STRING2];</code></div></div>这行代码是编译不了的，只是帮你想明白结构而已。<br />
<br />
也就是说，用枚举的时候，你其实是用这些枚举常量作为数组的索引。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">另一个例子</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SomeInteger = 124,<br />
&nbsp;&nbsp;&nbsp;&nbsp;SomeString[12],<br />
&nbsp;&nbsp;&nbsp;&nbsp;Float:SomeFloat<br />
};<br />
<br />
public OnFilterScriptInit()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new var_TEST[TEST];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var_TEST[SomeInteger] = 1337;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("1) 储存的值: %i, 常量: %i", var_TEST[SomeInteger], _:SomeInteger);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;format(var_TEST[SomeString], 12, "Hey!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("2) 储存的值: %s, 常量: %i", var_TEST[SomeString], _:SomeString);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var_TEST[SomeFloat] = 2054.124;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("3) 储存的值: %f, 常量: %i", var_TEST[SomeFloat], _:SomeFloat);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;return true;<br />
}</code></div></div><br />
输出结果：<br />
<ol type="1" class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: 1337, 常量: 124</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: Hey!, 常量: 125</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: 2054.124023, 常量: 137</code><br />
</li>
</ol>
<br />
第一行，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeInteger</code> 的常量值是 124，我把 1337 存到了索引 124 的位置。<br />
<br />
第二行，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString</code> 虽然定义了长度为 12，但输出常量值时显示的是 125。因为 125 是这个字符串的起始索引，它占了 125 到 136 这 12 个位置。<br />
<br />
第三行，浮点数正常显示，但 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeFloat</code> 的常量值是 137。你可能会想，它应该在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString</code>（125）后面，应该是 126 才对？但别忘了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString[12]</code> 是个数组，占了 12 个位置，所以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeFloat</code> 的起始索引是 125 + 12 = 137。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">一些额外的重要信息</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">枚举也可以作为标签使用：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_MY_TAG<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_FIRST = 4,<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_SECOND = 2<br />
}</code></div></div><br />
然后可以这样写：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new E_MY_TAG:SomeVar;</code></div></div>或者：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new E_MY_TAG:MyVariable = E_FIRST; // 不会报错，因为 E_FIRST 本来就是 E_MY_TAG 的一部分</code></div></div><br />
但是：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new data[E_MY_TAG];<br />
data[E_FIRST] = 7; // 编译错误，索引越界</code></div></div>因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_MY_TAG</code> 的大小是 3（枚举里最大索引是 2），而 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_FIRST</code> 的值是 4，已经超出范围了。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">匿名枚举：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum // 没有名字<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_TEST[10] = 32,<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new data[E_TEST]; // E_TEST 的值是 32，不是 10<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">强标签和弱标签：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_STRONG // 名字以大写字母开头，生成的是强标签<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR = 64<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new Test = E_STRONG:E_VAR; <br />
&nbsp;&nbsp;&nbsp;&nbsp;// 会报“标签不匹配”的警告，因为 Test 没有 E_STRONG 标签<br />
}</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum e_WEAK // 名字以小写字母开头，生成的是弱标签<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR = 64<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new Test = e_WEAK:E_VAR; <br />
&nbsp;&nbsp;&nbsp;&nbsp;// 没有警告<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
枚举的大概内容就是这些了，这也是为什么我们更喜欢用枚举而不是直接写常量的原因。<br />
<br />
<span style="font-style: italic;" class="mycode_i">感谢 Y_Less 的讲解。</span>]]></description>
			<content:encoded><![CDATA[<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">枚举器</h3><br />
<br />
原文作者: iPLEOMAX<br />
<br />
关于枚举，有些细节很多脚本作者并不清楚。<br />
<br />
很多人都喜欢在脚本里用枚举来存玩家数据、车辆数据、房屋数据之类的，尤其是用户信息这块。<br />
<br />
一个很典型的写法是这样的：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_PLAYER_INFO<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SCORE,<br />
&nbsp;&nbsp;&nbsp;&nbsp;MONEY,<br />
&nbsp;&nbsp;&nbsp;&nbsp;KILLS,<br />
&nbsp;&nbsp;&nbsp;&nbsp;DEATHS<br />
};<br />
<br />
new pInfo[MAX_PLAYERS][E_PLAYER_INFO];</code></div></div><br />
用起来大概是这样：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
public OnPlayerDeath(playerid, killerid, reason)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;pInfo[playerid][DEATHS]++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(IsPlayerConnected(killerid) &amp;&amp; killerid != playerid)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pInfo[killerid][KILLS]++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
这段应该不难理解。<br />
<br />
现在我们看另一个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_PLAYER_INFO<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SCORE,<br />
&nbsp;&nbsp;&nbsp;&nbsp;MONEY = 9,<br />
&nbsp;&nbsp;&nbsp;&nbsp;KILLS = 5,<br />
&nbsp;&nbsp;&nbsp;&nbsp;DEATHS = 56<br />
};<br />
<br />
new pInfo[MAX_PLAYERS][E_PLAYER_INFO];<br />
<br />
printf("%i | %i | %i | %i", pInfo[0][SCORE], pInfo[0][MONEY], pInfo[0][KILLS], pInfo[0][DEATHS]);</code></div></div><br />
你可能会觉得输出是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0 | 9 | 5 | 56</code>，对吧？<br />
<br />
如果你这么想，那就错了。实际上输出是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0 | 0 | 0 | 0</code>。<br />
<br />
你可能会以为枚举是用来存储数据的，但事实并非如此。我在枚举里写了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MONEY = 9</code>，然后在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 里用了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pInfo[0][MONEY]</code>，但编译器其实把它当成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pInfo[0][9]</code> 来处理，而不是什么 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_PLAYER_INFO:MONEY</code>。也就是说，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MONEY</code> 在这里只是作为一个<span style="font-weight: bold;" class="mycode_b">索引</span>来用的。<br />
<br />
所以枚举本质上<span style="font-weight: bold;" class="mycode_b">根本不是变量</span>，它其实就是一组<span style="font-weight: bold;" class="mycode_b">常量</span>，只不过帮你的数组索引起了个好记的名字罢了。<br />
<br />
好，我们再来深入一点，应该能让你理解得更清楚。<br />
<br />
举个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
const e_CAR1 = 0;<br />
const e_CAR2 = 1;<br />
const e_CAR3 = 2;<br />
<br />
new MyCars[3];<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR1] = 520;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR2] = 458;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR3] = 411;<br />
}</code></div></div><br />
现在我们用枚举重写一下：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum e_TEST<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR1,<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR2,<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR3<br />
};<br />
<br />
new MyCars[e_TEST];<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR1] = 520;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR2] = 458;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR3] = 411;<br />
}</code></div></div><br />
这两段代码都能正常编译，做的事情也完全一样。你看出区别了吗？其实就只是代码写法不同而已。<br />
<br />
这个例子告诉我们，枚举干的事情和常量是一样的。不过枚举有些地方比常量或者宏定义（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const e_CAR1 = 0;</code> 或者 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define e_CAR1 0</code>）更好用，具体差异我们后面再说。<br />
<br />
首先你需要明白枚举的结构：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp; Abc,<br />
&nbsp;&nbsp; Def,<br />
&nbsp;&nbsp; Ghi,<br />
};</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Abc</code> 是一个值为 0 的常量（差不多等于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const Abc = 0;</code> 或 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define Abc 0</code>），<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Def</code> 是值为 1 的常量，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Ghi</code> 是值为 2 的常量。<br />
<br />
预编译器会自动给这些常量赋值，从 0 开始一直往上排。而用常量的时候，你得自己手动赋值。枚举则是自动帮你排好的。<br />
<br />
再看个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp; e_ONE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 自动得到 0<br />
&nbsp;&nbsp; e_TWO,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 得到 1<br />
&nbsp;&nbsp; e_THREE,&nbsp;&nbsp;&nbsp;&nbsp;// 得到 2<br />
&nbsp;&nbsp; e_FOUR = 12,// 这里手动赋了 12，所以不再是 3 了<br />
&nbsp;&nbsp; e_FIVE,&nbsp;&nbsp;&nbsp;&nbsp; // 变成 13，因为上一个值是 12<br />
&nbsp;&nbsp; e_SIX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 变成 14，上一个值是 13<br />
}</code></div></div><br />
看到了吧，如果你手动给某个枚举项赋了值，后面的项就会在此基础上依次加 1。<br />
<br />
再来看看更复杂的情况：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum DATA<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;INT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 得到 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;STRING[10],&nbsp;&nbsp;&nbsp;&nbsp; // 得到 1，但因为是数组，一个位置不够，它会占 10 个位置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 所以实际占用的索引是 1, 2, 3, 4, 5, 6, 7, 8, 9, 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;INT2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 得到 11，因为 STRING 最后一位是 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;STRING2[10]&nbsp;&nbsp;&nbsp;&nbsp; // 从 12 开始，一直到 22，需要 10 个位置<br />
};</code></div></div><br />
运行下面的代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
printf("%i", _:DATA);</code></div></div><br />
结果输出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">22</code>。<br />
<br />
因为整个枚举的总大小是 22：<br />
INT 占 1 个 + STRING 占 10 个 + INT2 占 1 个 + STRING2 占 10 个 = 22。<br />
<br />
你可能会问，为什么我写 INT 是 1 而不是 0？因为这里我数的是<span style="font-weight: bold;" class="mycode_b">占用了多少个位置</span>，不是<span style="font-weight: bold;" class="mycode_b">从哪个位置开始</span>。如果问起始位置，那 INT 确实是 0。<br />
<br />
一个大小为 22 的块，索引范围是 0 到 21，总共 22 个位置。<br />
<br />
再试一下：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
printf("%i", _:STRING);</code></div></div><br />
输出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1</code>。因为第一个位置（索引 0）被 INT 占了，所以 STRING 从索引 1 开始。<br />
<br />
每个枚举项占用的位置是这样的：<ul class="mycode_list"><li>INT：索引 0<br />
</li>
<li>STRING：索引 1 到 10<br />
</li>
<li>INT2：索引 11<br />
</li>
<li>STRING2：索引 12 到 21<br />
</li>
</ul>
<br />
运行这段：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new Array[DATA];<br />
printf("%i", sizeof Array);</code></div></div><br />
结果也是 22，因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">DATA</code> 的大小就是 22。<br />
<br />
所以，这个数组实际上相当于：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
Array[INT + STRING + INT2 + STRING2];</code></div></div>这行代码是编译不了的，只是帮你想明白结构而已。<br />
<br />
也就是说，用枚举的时候，你其实是用这些枚举常量作为数组的索引。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">另一个例子</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SomeInteger = 124,<br />
&nbsp;&nbsp;&nbsp;&nbsp;SomeString[12],<br />
&nbsp;&nbsp;&nbsp;&nbsp;Float:SomeFloat<br />
};<br />
<br />
public OnFilterScriptInit()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new var_TEST[TEST];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var_TEST[SomeInteger] = 1337;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("1) 储存的值: %i, 常量: %i", var_TEST[SomeInteger], _:SomeInteger);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;format(var_TEST[SomeString], 12, "Hey!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("2) 储存的值: %s, 常量: %i", var_TEST[SomeString], _:SomeString);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var_TEST[SomeFloat] = 2054.124;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("3) 储存的值: %f, 常量: %i", var_TEST[SomeFloat], _:SomeFloat);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;return true;<br />
}</code></div></div><br />
输出结果：<br />
<ol type="1" class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: 1337, 常量: 124</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: Hey!, 常量: 125</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: 2054.124023, 常量: 137</code><br />
</li>
</ol>
<br />
第一行，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeInteger</code> 的常量值是 124，我把 1337 存到了索引 124 的位置。<br />
<br />
第二行，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString</code> 虽然定义了长度为 12，但输出常量值时显示的是 125。因为 125 是这个字符串的起始索引，它占了 125 到 136 这 12 个位置。<br />
<br />
第三行，浮点数正常显示，但 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeFloat</code> 的常量值是 137。你可能会想，它应该在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString</code>（125）后面，应该是 126 才对？但别忘了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString[12]</code> 是个数组，占了 12 个位置，所以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeFloat</code> 的起始索引是 125 + 12 = 137。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">一些额外的重要信息</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">枚举也可以作为标签使用：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_MY_TAG<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_FIRST = 4,<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_SECOND = 2<br />
}</code></div></div><br />
然后可以这样写：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new E_MY_TAG:SomeVar;</code></div></div>或者：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new E_MY_TAG:MyVariable = E_FIRST; // 不会报错，因为 E_FIRST 本来就是 E_MY_TAG 的一部分</code></div></div><br />
但是：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new data[E_MY_TAG];<br />
data[E_FIRST] = 7; // 编译错误，索引越界</code></div></div>因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_MY_TAG</code> 的大小是 3（枚举里最大索引是 2），而 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_FIRST</code> 的值是 4，已经超出范围了。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">匿名枚举：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum // 没有名字<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_TEST[10] = 32,<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new data[E_TEST]; // E_TEST 的值是 32，不是 10<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">强标签和弱标签：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_STRONG // 名字以大写字母开头，生成的是强标签<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR = 64<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new Test = E_STRONG:E_VAR; <br />
&nbsp;&nbsp;&nbsp;&nbsp;// 会报“标签不匹配”的警告，因为 Test 没有 E_STRONG 标签<br />
}</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum e_WEAK // 名字以小写字母开头，生成的是弱标签<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR = 64<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new Test = e_WEAK:E_VAR; <br />
&nbsp;&nbsp;&nbsp;&nbsp;// 没有警告<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
枚举的大概内容就是这些了，这也是为什么我们更喜欢用枚举而不是直接写常量的原因。<br />
<br />
<span style="font-style: italic;" class="mycode_i">感谢 Y_Less 的讲解。</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[教程] Pawn 中的压缩字符串 原文作者: Emmet_]]></title>
			<link>https://open-mp.cn/showthread.php?tid=25</link>
			<pubDate>Sat, 21 Mar 2026 23:52:50 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=25</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">Pawn 中的压缩字符串</h2><br />
<br />
原文作者: Emmet_ 本篇教程仅为翻译搬运<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">引言</h3><br />
<br />
压缩字符串自 SA-MP 和 Pawn 诞生之初就已存在。然而，很多人并不了解压缩字符串以及它能节省多少内存！本教程将教你压缩字符串的基础知识，以及如何正确操作它们。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">什么是压缩字符串？</h3><br />
<br />
压缩字符串是一种数组，它将数据存储在<span style="font-weight: bold;" class="mycode_b">每个字节</span>中，而不是像普通数组那样存储在<span style="font-weight: bold;" class="mycode_b">每个单元格</span>中。压缩字符串以小端序存储（即低位字节在前），并且只能容纳 0 到 255 的 ASCII 字符，超出这个范围的数值会绕回。<br />
<br />
看这段代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new string[5];<br />
string[0] = 'a';<br />
string[1] = 'b';<br />
string[2] = 'c';<br />
string[3] = 'd';<br />
string[4] = '&#92;0';</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'a'</code> 存储在单元格 0，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'b'</code> 存储在单元格 1，依此类推。一个单元格基本上占用 4 个字节，所以算一下，上面的字符串大约占用 20 个字节，每个字符占用 4 个字节的空间。<br />
<br />
然而，使用下面的代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new string[5 char];<br />
string{0} = 'a';<br />
string{1} = 'b';<br />
string{2} = 'c';<br />
string{3} = 'd';<br />
string{4} = '&#92;0';</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'a'</code> 存储在字节 0，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'b'</code> 存储在字节 1，依此类推。实际上，上面的字符串只占用 8 个字节，仅包含 2 个单元格！<br />
<br />
你可能在想为什么这个字符串不是 5 个字节。使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">char</code> 修饰符会自动将数组大小向上取整到最近的 4 的倍数（例如，1 变成 4，3 变成 4，5 变成 8，23 变成 24，依此类推）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 这个数组占用 5 个单元格，共 20 个字节。<br />
new string[5] = "abcd"; <br />
// 这个数组占用 2 个单元格，共 8 个字节。<br />
new string[5 char] = !"abcd";</code></div></div><br />
因此，使用压缩字符串可以节省 3 到 4 倍的内存！<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">适用场景</h3><br />
<br />
你可能认为压缩数组没什么用。如果这么想，那你就错了。压缩数组有很多用途，不仅仅是节省内存！<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">稀疏数组</h4><br />
<br />
首先，你可以阅读我关于稀疏数组的教程：<br />
<br />
<a href="https://sampforum.blast.hk/showthread.php?tid=480439" target="_blank" rel="noopener" class="mycode_url">https://sampforum.blast.hk/showthread.php?tid=480439</a><br />
<br />
稀疏数组就是那些大部分数据经常为空的数组。使用压缩数组可以轻松节省内存！<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MAX_ITEMS (64)<br />
// 8,192 个单元格 = 32,768 字节！<br />
new gData[MAX_ITEMS][128];<br />
// 2,048 个字节 = 8,192 个单元格！<br />
new gData[MAX_ITEMS][128 char];</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">不常使用的字符串</h4><br />
<br />
很多时候，你会把字符串保存到内存中，但很少使用它们（例如几乎不用）。对于这类数组，压缩数组非常适用。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">大量数据存储</h4><br />
<br />
回到上面的“稀疏数组”部分，如果你需要存储大量数据，最好使用压缩字符串。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">内存节省！</h4><br />
<br />
压缩数组能节省 4 倍的内存，既然可以用压缩数组，为什么还要用那些多占 4 倍内存的方式存储数据呢？<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">SA-MP 中的不支持情况</h3><br />
<br />
压缩字符串在纯 Pawn 中完美支持。但是，大多数 SA-MP 原生函数<span style="font-weight: bold;" class="mycode_b">不支持</span>压缩字符串，比如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">format</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetPlayerName</code> 等。<br />
<br />
如果你打算使用压缩字符串，就必须依赖 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strpack</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strunpack</code> 以及 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string.inc</code> 中的其他字符串函数。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">格式化字符串</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">format</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 函数不支持压缩字符串，因此你必须使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strpack</code>：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    string[128 char];<br />
strpack(string, "Hello world!");</code></div></div><br />
你也可以这样做：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new <br />
    string[128 char],<br />
    temp[128]<br />
;<br />
strpack(string, "Emmet");<br />
strunpack(temp, string);<br />
format(temp, sizeof(temp), "%s likes to eat %s.", temp, "Big Macs");<br />
strpack(string, temp);</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">支持压缩字符串的函数</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string.inc</code> 中的所有字符串函数都同时支持压缩数组和非压缩数组。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">fread</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">valstr</code> 函数也接受一个可选的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pack</code> 参数来支持压缩数组，因此你不用担心它们是否能与压缩数组一起工作。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">访问数据</h3><br />
<br />
在 Pawn 中，非压缩数组将数据存储在<span style="font-weight: bold;" class="mycode_b">每个单元格</span>中。而压缩数组将数据存储在<span style="font-weight: bold;" class="mycode_b">每个字节</span>中，这意味着你不能像访问非压缩数组那样使用方括号 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">[]</code> 来访问和获取压缩数组中的数据。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误。<br />
if (g_PackedString[0] != '&#92;0')<br />
{<br />
    g_PackedString[0] = 'h';<br />
    g_PackedString[1] = 'i';<br />
}<br />
// 正确！<br />
if (g_PackedString{0} != '&#92;0')<br />
{<br />
    g_PackedString{0} = 'h'; <br />
    g_PackedString{1} = 'i';<br />
}</code></div></div><br />
另外，要设置一个压缩字符串，你需要在字符串前加上感叹号，以表示这是压缩输入。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误。这会尝试将字符串按单元格存储，这不是我们想要的！<br />
g_PackedString = "Hello world.";<br />
// 正确！<br />
g_PackedString = !"Hello world.";</code></div></div>]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">Pawn 中的压缩字符串</h2><br />
<br />
原文作者: Emmet_ 本篇教程仅为翻译搬运<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">引言</h3><br />
<br />
压缩字符串自 SA-MP 和 Pawn 诞生之初就已存在。然而，很多人并不了解压缩字符串以及它能节省多少内存！本教程将教你压缩字符串的基础知识，以及如何正确操作它们。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">什么是压缩字符串？</h3><br />
<br />
压缩字符串是一种数组，它将数据存储在<span style="font-weight: bold;" class="mycode_b">每个字节</span>中，而不是像普通数组那样存储在<span style="font-weight: bold;" class="mycode_b">每个单元格</span>中。压缩字符串以小端序存储（即低位字节在前），并且只能容纳 0 到 255 的 ASCII 字符，超出这个范围的数值会绕回。<br />
<br />
看这段代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new string[5];<br />
string[0] = 'a';<br />
string[1] = 'b';<br />
string[2] = 'c';<br />
string[3] = 'd';<br />
string[4] = '&#92;0';</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'a'</code> 存储在单元格 0，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'b'</code> 存储在单元格 1，依此类推。一个单元格基本上占用 4 个字节，所以算一下，上面的字符串大约占用 20 个字节，每个字符占用 4 个字节的空间。<br />
<br />
然而，使用下面的代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new string[5 char];<br />
string{0} = 'a';<br />
string{1} = 'b';<br />
string{2} = 'c';<br />
string{3} = 'd';<br />
string{4} = '&#92;0';</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'a'</code> 存储在字节 0，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'b'</code> 存储在字节 1，依此类推。实际上，上面的字符串只占用 8 个字节，仅包含 2 个单元格！<br />
<br />
你可能在想为什么这个字符串不是 5 个字节。使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">char</code> 修饰符会自动将数组大小向上取整到最近的 4 的倍数（例如，1 变成 4，3 变成 4，5 变成 8，23 变成 24，依此类推）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 这个数组占用 5 个单元格，共 20 个字节。<br />
new string[5] = "abcd"; <br />
// 这个数组占用 2 个单元格，共 8 个字节。<br />
new string[5 char] = !"abcd";</code></div></div><br />
因此，使用压缩字符串可以节省 3 到 4 倍的内存！<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">适用场景</h3><br />
<br />
你可能认为压缩数组没什么用。如果这么想，那你就错了。压缩数组有很多用途，不仅仅是节省内存！<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">稀疏数组</h4><br />
<br />
首先，你可以阅读我关于稀疏数组的教程：<br />
<br />
<a href="https://sampforum.blast.hk/showthread.php?tid=480439" target="_blank" rel="noopener" class="mycode_url">https://sampforum.blast.hk/showthread.php?tid=480439</a><br />
<br />
稀疏数组就是那些大部分数据经常为空的数组。使用压缩数组可以轻松节省内存！<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MAX_ITEMS (64)<br />
// 8,192 个单元格 = 32,768 字节！<br />
new gData[MAX_ITEMS][128];<br />
// 2,048 个字节 = 8,192 个单元格！<br />
new gData[MAX_ITEMS][128 char];</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">不常使用的字符串</h4><br />
<br />
很多时候，你会把字符串保存到内存中，但很少使用它们（例如几乎不用）。对于这类数组，压缩数组非常适用。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">大量数据存储</h4><br />
<br />
回到上面的“稀疏数组”部分，如果你需要存储大量数据，最好使用压缩字符串。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">内存节省！</h4><br />
<br />
压缩数组能节省 4 倍的内存，既然可以用压缩数组，为什么还要用那些多占 4 倍内存的方式存储数据呢？<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">SA-MP 中的不支持情况</h3><br />
<br />
压缩字符串在纯 Pawn 中完美支持。但是，大多数 SA-MP 原生函数<span style="font-weight: bold;" class="mycode_b">不支持</span>压缩字符串，比如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">format</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetPlayerName</code> 等。<br />
<br />
如果你打算使用压缩字符串，就必须依赖 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strpack</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strunpack</code> 以及 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string.inc</code> 中的其他字符串函数。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">格式化字符串</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">format</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 函数不支持压缩字符串，因此你必须使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strpack</code>：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    string[128 char];<br />
strpack(string, "Hello world!");</code></div></div><br />
你也可以这样做：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new <br />
    string[128 char],<br />
    temp[128]<br />
;<br />
strpack(string, "Emmet");<br />
strunpack(temp, string);<br />
format(temp, sizeof(temp), "%s likes to eat %s.", temp, "Big Macs");<br />
strpack(string, temp);</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">支持压缩字符串的函数</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string.inc</code> 中的所有字符串函数都同时支持压缩数组和非压缩数组。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">fread</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">valstr</code> 函数也接受一个可选的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pack</code> 参数来支持压缩数组，因此你不用担心它们是否能与压缩数组一起工作。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">访问数据</h3><br />
<br />
在 Pawn 中，非压缩数组将数据存储在<span style="font-weight: bold;" class="mycode_b">每个单元格</span>中。而压缩数组将数据存储在<span style="font-weight: bold;" class="mycode_b">每个字节</span>中，这意味着你不能像访问非压缩数组那样使用方括号 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">[]</code> 来访问和获取压缩数组中的数据。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误。<br />
if (g_PackedString[0] != '&#92;0')<br />
{<br />
    g_PackedString[0] = 'h';<br />
    g_PackedString[1] = 'i';<br />
}<br />
// 正确！<br />
if (g_PackedString{0} != '&#92;0')<br />
{<br />
    g_PackedString{0} = 'h'; <br />
    g_PackedString{1} = 'i';<br />
}</code></div></div><br />
另外，要设置一个压缩字符串，你需要在字符串前加上感叹号，以表示这是压缩输入。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误。这会尝试将字符串按单元格存储，这不是我们想要的！<br />
g_PackedString = "Hello world.";<br />
// 正确！<br />
g_PackedString = !"Hello world.";</code></div></div>]]></content:encoded>
		</item>
	</channel>
</rss>