TShock 插件(C# / .NET 6),将 Terraria 服务器接入 AxoGC 社区平台 core。
- 长轮询:从平台拉取下行命令(踢人、广播、私信、Web 聊天回灌等),无 WebSocket
- 心跳上报:每 30s 上报在线人数与玩家列表,刷新平台侧服务器状态
- 玩家事件:加入 / 离开实时推送到平台
- 账号绑定:玩家通过
/axo bind <CODE>将游戏名与平台账号关联 - 聊天桥接:游戏内聊天 → 平台 SSE 频道;Web 端消息 → 游戏内广播
- 管理员控制台:core 后台可派发
kick / ban / raw命令
MVP 暂不实现:白名单(reply NOT_SUPPORTED)、Boss 进度上报、stats / leaderboard 排行(pull-mode metrics)。
| 依赖 | 版本 |
|---|---|
| TShock | 5.2.x(基于 net6.0) |
| .NET SDK(开发机) | 8.0+(target framework 仍是 net6.0) |
| Terraria | 1.4.4.9 |
# 一次性安装 .NET 8 SDK(Ubuntu 24.04+)
sudo apt update && sudo apt install -y dotnet-sdk-8.0
# 编译
cd /root/terraria-plugin
dotnet build -c Release
# 产物
# bin/Release/net6.0/AxoGC.TShock.dll如果 TShock 包恢复失败(罕见情况下 Pryaxis 的 NuGet 命名空间会调整),改为引用本地 DLL:
-
从 https://github.com/Pryaxis/TShock/releases 下载 TShock 5.2.x zip
-
解压后把以下 DLL 放入
libs/:TShockAPI.dllOTAPI.dllTerrariaServer.dll
-
编辑
AxoGC.TShock.csproj,把<PackageReference>段换成:<ItemGroup> <Reference Include="TShockAPI"> <HintPath>libs/TShockAPI.dll</HintPath> <Private>false</Private> </Reference> <Reference Include="OTAPI"> <HintPath>libs/OTAPI.dll</HintPath> <Private>false</Private> </Reference> <Reference Include="TerrariaServer"> <HintPath>libs/TerrariaServer.dll</HintPath> <Private>false</Private> </Reference> </ItemGroup>
<Private>false</Private> 阻止把宿主 DLL 复制进 bin(服务器自带)。
- 把
AxoGC.TShock.dll复制到 TShock 服务器的ServerPlugins/目录 - 同目录放一份
config.example.json(首启拷贝模板) - 启动服务器:插件自动生成
tshock/AxoGC.TShock/config.json - 编辑配置填入
base_url与token,重启服务器生效
tshock/AxoGC.TShock/config.json:
{
"base_url": "https://your-platform.example.com",
"token": "REPLACE_ME",
"poll_timeout_ms": 35000,
"connect_timeout_ms": 5000,
"request_timeout_ms": 10000,
"heartbeat_interval_sec": 30,
"welcome_banner": true
}| 字段 | 说明 |
|---|---|
base_url |
core 后端基础 URL(不带尾部斜杠) |
token |
由平台管理后台生成的服务器 token,明文仅在创建/重置时返回一次 |
poll_timeout_ms |
长轮询 HTTP 超时,必须 > 服务端挂起时长(28s)+ 缓冲,推荐 35000 |
connect_timeout_ms |
建连超时 |
request_timeout_ms |
非 poll 请求超时(心跳/reply/上报) |
heartbeat_interval_sec |
心跳间隔,默认 30s(必须 ≤ 60s 保住 Redis TTL) |
welcome_banner |
是否在玩家加入时显示欢迎横幅 |
未填或保持 REPLACE_ME 时插件拒绝启动,日志输出 [axogc] base_url / token not configured。
src/
├── TShockPlatformPlugin.cs # TerrariaPlugin 入口,生命周期管理
├── Config/
│ └── PluginConfig.cs # config.json 读写
├── Transport/
│ ├── ApiClient.cs # HttpClient 封装(?token=, envelope 解析)
│ ├── PollLoop.cs # 长轮询主循环
│ ├── Envelope.cs # 响应 envelope 反序列化
│ └── Event.cs # IncomingEvent / ReplyBody
├── Handlers/
│ ├── CommandRouter.cs # 下行命令路由
│ └── AdminCommandHandler.cs # admin.command.run
├── Observation/
│ ├── PlayerListener.cs # NetGreetPlayer / ServerLeave → 上行事件
│ ├── HeartbeatTask.cs # 30s 心跳定时器
│ └── ChatBridgeListener.cs # ServerChat → /chat.message
└── Commands/
├── AxoCommand.cs # /axo 主命令路由
└── BindCommand.cs # /axo bind <CODE>
实现 PLAN.md §4 协议:
| 方向 | 端点 | 说明 |
|---|---|---|
| 下行(拉) | GET /api/srv/poll?token= |
长轮询,挂起最多 28s,返回事件或 204 |
| 下行(回) | POST /api/srv/reply?token= |
回复需要响应的命令 |
| 上行 | POST /api/srv/heartbeat?token= |
心跳 + 在线人数 |
| 上行 | POST /api/srv/player.joined?token= |
玩家加入 |
| 上行 | POST /api/srv/player.left?token= |
玩家离开 |
| 上行 | POST /api/srv/binding.request?token= |
绑定验证码核验 |
| 上行 | POST /api/srv/chat.message?token= |
游戏内聊天事件 |
| command | 说明 | 需要 reply |
|---|---|---|
player.kick |
踢出玩家 | 否 |
player.notify |
私信玩家 | 否 |
server.broadcast |
全服广播 | 否 |
chat.from_web |
Web 用户消息回灌 | 否 |
player.whitelist.add |
加白名单 | 是(返回 NOT_SUPPORTED) |
player.whitelist.remove |
移出白名单 | 是(返回 NOT_SUPPORTED) |
admin.command.run |
派发 kick/ban/raw 命令 | 是 |
| 其他 | — | 回 COMMAND_UNKNOWN |