---
url: /article/mslx/beta/index.md
---
# MSLX Alpha (早期开发版本) 测试尝鲜!

## 下载 MSLX
MSLX已于2026-01-17 发布正式版本,可以直接前往下载体验啦!
[下载 MSLX](/docs/install/start/){.readmore}
::: warning 以下内容已经过时
:::
## 立即尝鲜!
::: warning 提醒
注意:目前MSLX仍处于早期开发状态,仅供尝鲜,==谨慎用于生产环境哦~=={.warning}
:::
由于测试版本具有较大的 ==不稳定性== ,故MSLX测试版本仅在下面测试群发版,直到稳定版本1.0发布才会在其他地方公开发布哦!
或者你喜欢扫码的话↓↓↓

---
---
url: /article/mslx/devlogs-1/index.md
---
# MSLX 开发日志 #1 - 基础功能开发
## 项目介绍
\==MSLX== 是由 [**MSL**](https://www.mslmc.cn) 原班团队 **MSLTeam** 倾力打造的全新一代开服工具。基于 ==.NET Core 8.0== 环境。
它传承了 MSL 经典的 UI 设计语言,旨在让操作零门槛——无论是老用户还是新伙伴,都能即刻上手,极速部署您的 MC 服务器。
MSLX 不仅 ==完美支持跨平台== (Windows / macOS / Linux) 运行,相比前代,更引入了强大的 ==远程访问== 功能,让管理更自由。
::: warning 之前的MSLX呢?
已经倒闭了!就是这个↓↓↓

:::
新版本的MSLX采用了 ==前后端分离== 的设计模式,计划有两套前端可供选择使用:网页控制台/跨平台支持的桌面客户端。当然,后端也是跨平台支持的。!!听不懂没关系,只需要知道,MSLX整体均支持跨平台使用。!!
## 开发进度
目前已完成服务器创建以及启停控制,隧道创建以及启停控制。
优先开发的是后端+网页控制台前端,桌面客户端将在前者功能较完善后开始开发。
更多基础功能还在陆续开发中......
## 开发展示
\==连接页==

\==仪表盘(首页)==

\==服务端列表==

\==服务端创建==

\==服务端控制台==

\==创建隧道== (目前已完成对MSLFrp,MSL 联机,以及自定义配置文件的支持,更多服务商将在后续接入...)

\==隧道列表==

\==隧道控制台== (普通隧道)

\==隧道控制台==(联机隧道)

目前就是这么多啦~ 更多功能还在陆续开发中~
---
---
url: /article/mslx/devlogs-2/index.md
---
# MSLX 开发日志 #2 - 实例设置 & 文件管理
## 服务端实例设置
实例设置部分依照MSL服务器运行窗口的设计逻辑,简单易懂。
(部分功能如备份,外置登录,尚未实现。)

## 文件管理功能
目前已完成文件查看,下载,压缩,解压,权限修改等基础功能。(压缩解压暂时仅支持zip)。


---
---
url: /article/mslx/devlogs-3/index.md
---
# MSLX 开发日志 #3 - 定时任务 & 实例设置功能增强
## v0.1.1 - alpha
::: tip 加入测试
目前MSLX正在内测,欢迎加入体验哦~
[>>>加入测试 **MSLX官网**](https://mslx.mslmc.cn){.read-more}
:::
### Feat - 定时任务



### Feat - 模组/插件管理页面


### Feat - 服务器配置文件可视化编辑

### Perfect - 一些优化
* 更新了首页公告的接口,现采用MSLX独立公告内容。
* 文件管理页面补充支持新建文件夹。
---
---
url: /article/mslx/devlogs-4/index.md
---
# MSLX 开发日志 #4 - 用户系统 & 本地部署
## v0.2.0-alpha
::: tip 加入测试
目前MSLX正在内测,欢迎加入体验哦~
[>>>加入测试 **MSLX官网**](https://mslx.mslmc.cn){.read-more}
:::
### Dependency - 升级框架到 .NET Core 10.0 LTS
在 ==v0.2.0-alpha== 版本中,我们将框架版本从 .NET Core 8.0 升级到了 .NET Core 10.0。
内测用户可能需要重新安装环境才能运行新的测试版本。
[>>>查阅文档 **MSLX官网**](https://mslx.mslmc.cn/docs/install/start/){.read-more}
### Feat - 用户系统
在此版本,网页控制台 ==不再支持APIKey== 的登录方式,换用全新的 ==用户系统== 。
!!不过,接口仍然支持APIKey的鉴权方式,目前留作客户端连接使用。!!


::: tip 初始账户
首次启动时,会生成一个初始账户。
用户名:`mslx`
密码:`随机`

:::
::: warning WIP
目前用户系统仅完成初步的登录和管理设计,==暂未支持给普通用户分配资源=={.warning} ,所以也请暂时不要创建普通用户使用。
:::
### Feat - 实现Web控制台的本地化部署
目前发布的 ==v0.2.0-alpha== 版本已嵌入前端资源,可以直接访问软件监听地址打开Web控制台。
若需要外网访问,可以使用 ==反向代理== 或者 ==内网穿透== 实现,仅需映射`MSLX.Daemon`的服务端口即可。
\==外网访问**强烈建议**使用SSL连接。==
::: tip 在线控制台
以前的控制台仍会继续按照发布版本更新。
若您觉得外网访问您的控制台较慢,您可以继续使用在线控制台远程连接。(在线控制台采用全球加速CDN)
(不同的是,使用本在线控制台您需要额外输入连接地址,并且如果连接的不是本地地址,您需要给守护进程套 ==SSL==)

:::
### Feat & Fix - 一些优化 & Bug修复
* 修复了编码错误导致的无法正常关闭服务端的问题
* 新增了文件编辑器的编码设置
* 对于在Windows系统下,创建服务端默认编码均使用 ==GBK==
---
---
url: /article/mslx/devlogs-5/index.md
---
# MSLX 开发日志 #5 - 服务端功能完善 & 资源监控
## v0.2.2-alpha
此版本对部分预留的功能进行了完善,网页控制台和守护进程端完成度大概在 ==90%==,预计下一个版本将进入 ==beta== 版本状态。
### Feat - 资源状态监控
* 在仪表盘页面(首页)新增了资源监控图表
* 在服务端实例控制台页面新增当前服务端进程的资源监控图表
### Feat - 完成存档备份功能
备份操作逻辑与MSL软件内一致,支持手动备份和自动备份
!!这项MSL鸽了4年的功能,在MSLX的alpha版本就实装了!!!

可以在 ==定时任务== 中直接设置备份计划

### Feat - 实例控制升级
已完成对 ==崩溃自动重启== 和 ==随守护进程自启动== 的功能

### Feat - 外置登录支持
已完成与MSL内一致的 ==自动配置外置登录== 功能,仅需要设置外置登录的API地址,即可一键开启外置登录支持。

### Feat & Fix - 优化和功能修复
* 网页控制台UI优化 - 在服务端控制台页面新增一些MC配置的显示,以及新增更好看的命令输入框
* 优化了PC端横向菜单布局的显示效果,修复部分子菜单项错位问题
* 修复了部分ANSI日志染色出错的问题
---
---
url: /article/mslx/devlogs-6/index.md
---
# MSLX 开发日志 #6 - 控制台UI优化 & 细节完善
## v0.3.1/v0.3.0-alpha
这两个版本主要完成了对 ==网页控制台== 自定义主题的支持,以及一些细节的完善和bug修复。
### Feat - 自定义主题
\==启用背景图是一定会造成可阅读性下降的,请自行斟酌是否启用。== !!好看才是第一对吧!!!



### Feat - 细节完善
* \==文件管理器== 内新增复制和移动文件的功能
* 更新Java版本选择提示(26.1+版本需要Java25)
* 第一次启动时添加了更直观的账号密码提示
* 修复切换页面可能错误弹出错误信息(v0.2.3-alpha)
* 优化文件管理器在手机端的样式(v0.2.3-alpha)
* 内存调整支持GB单位(v0.2.2.1-alpha)
* 更新Frp隧道列表排序规则(v0.2.2.1-alpha)
* 添加了一只应急食品,猜猜她在哪?(v0.2.2.1-alpha)
### Fix - Bug修复
* 修复面板样式设置点击一次后立马退出的问题
* 修复了自动重启的熔断功能无效的问题
* 修复切换实例控制台可能导致的配置弹窗货不对版(v0.2.2.1-alpha)
---
---
url: /article/mslx/devlogs-7/index.md
---
# MSLX 开发日志 #7 - Beta版本发布
## v0.5.1-beta
经过一个星期的 ==alpha== 版本迭代,目前MSLX的 ==网页面板+守护进程== 功能已经基本完成,基本上可以正常使用了。
现在 ==alpha → beta== 版本。我们预计在 ==2026年1月== 发布 ==MSLX正式版本==(不含客户端版本)。
欢迎大家提供更多的反馈!

### Fix - 问题修复
* 修复开启背景美化后服务端核心选择组件变成透明的问题
* 修复创建服务器页面在自定义背景模式下丢失容器背景色的问题
* 修复在Windows下Java选择Java Path和环境变量时无法正确监控资源的问题
* 修复一些循环任务在退出时报错
* 修复文件管理器无法下载大文件的问题
::: warning 关于文件资源
由于目前文件下载功能做的比较的 ==质朴=={.warning}
\==请不要向他人分享您的文件的下载地址和服务器图标的资源地址=={.warning}
否则可能会导致他人可以盗用您的账户
:::
### Perfect - 优化
* 调整服务端选择组件的高度和宽度,在PC端更容易选择服务端核心
* 配置默认日志级别,防止过多日志的输出
* 减少启动任务等待时间
---
---
url: /article/mslx/release/index.md
---
# MSLX 正式版本发布!
## 下载 MSLX
MSLX已于2026-01-17 发布正式版本,可以直接前往下载体验啦!
(本次发布的版本不含客户端版本,仅限网页控制台版本哦)
[下载 MSLX](/docs/install/start/){.readmore}
@[bilibili](BV13NkWBxEwg)
---
---
url: /article/mslx/v1.1/index.md
---
# MSLX v1.1 版本开发结束
## 下载 MSLX
MSLX已于2026-02-18 结束v1.1版本的开发,更新内容可以查看以下视频哦~
[下载 MSLX](/docs/install/start/){.readmore}
@[bilibili](BV1sHFZzWENW)
---
---
url: /article/mslx/v1.2/index.md
---
# MSLX v1.2 版本开发结束
## 下载 MSLX
MSLX已于2026-03-06 结束v1.2版本的开发,更新内容可以查看以下视频哦~
[下载 MSLX](/docs/install/start/){.readmore}
@[bilibili](BV13ZPpz2ErB)
---
---
url: /article/mslx/v1.4/index.md
---
# MSLX V1.4 版本更新总结 & V1.5 版本开发计划
## V1.4 版本更新总结
**V1.4** 版本于 **2026-05-01 17:41:43** 发布,经过10个小版本迭代后于 **2026-07-08 12:41:16** 正式发布 **v1.4.10.1** 版本结束了整个 **v1.4** 版本的开发。
此大版本着重对\*\*「插件系统」\*\*进行了支持与完善。
@[bilibili](BV1caN36UEK7)
### 插件系统
全新的插件系统可以为您的MSLX安装额外的功能,提供更丰富的开服管理体验。

### 插件生态
插件开发平台 & 插件开发文档,欢迎开发新的插件~


### SSL配置功能
启用HTTPS访问,保护您的数据安全。

### MCDR 服务端支持
新增对MCDR托管服务端支持(感谢@alright-qwq 对本功能的贡献)。

### 功能优化 & Bug修复······
* refactor(webpanel): 重构样式设置组件
* feat(webpanel): 实例控制台输入框新增历史记录功能 (上下方向键切换) #129
* chore(webpanel & daemon): 可设置强制最大退出时间又120s增加到300s
* fix(daemon): 修复部分压缩包在添加时jar包检测错误的问题
* fix(webpanel): 修复地图渲染器功能遇到未知方块颜色污染后续渲染的问题 #132
* feat(daemon): 游戏玩家列表新增中文匹配支持 #133
* fix(webpanel): 修复网页控制台登录页面在黑暗模式下背景图不正常缩放的问题
* fix(webpanel): 修复上传失败进度条回退0的问题
* perf(webpanel): 优化弱网状态下的上传文件成功率
* fix(daemon): 修复Linux自动更新失败
* fix(daemon): 修复针对部分特定服务端(如Youer端的首次启动)会产生子进程运行的情况导致状态错误判断为关闭的问题(此类情况只能监听日志输出,没办法输入命令了)
* style(webpanel): 优化终端的滚动效果 #142
* fix(webpanel): 修复创建实例上传文件的进度条进度由于小数导致的宽度乱跳问题 #141
* feat(daemon & webpanel): 初始化/重置默认账户时,会生成一个包含默认账户密码信息的文本文件在数据目录
* feat(webpanel): 文件编辑器新增保存不关闭的功能 #147
* feat(webpanel): 在非本地/局域网环境下新增HTTP协议访问的安全警告
* feat(webpanel): 服务端选择组件新增服务端简短描述介绍
* 等等等等······ | 详情可见:
## V1.5 版本开发计划
V1.5 版本主要支持内容为「**容器化部署服务端实例**」,目前已更新到 **v1.5.2** 版本,已完成对容器启动的初步支持,欢迎体验!

---
---
url: /article/mslx/v1.7-breaking-changes/index.md
---
# MSLX SDK v1.7 接口变更
::: tip 这是什么?
这东西与插件开发相关,如果你发现你看不懂这条信息一点,忽略就行。
:::
## 变更原因
由于原来的 `IMCServerService` DI依赖注入接口混杂了过多进程管理方法,导致代码维护难度升高,故在本版本对原有接口进行了拆分,细分到了不同的依赖注入接口中。由于宿主接口变化,`SDK` 接口方法也需要变动,对于插件开发者来说需要进行更新适配。
## 变更说明
* `IMCServerService` 在 `v1.7` 版本将仍然保留,但将标记为 `待废弃`(提供一个大版本过渡期),并会在 `v1.8` 版本中 ==完全删除== 相关接口。若您的插件调用了相关服务,请尽快完成新接口的适配。
* 在已发布的 `SDK v1.6.4` 版本中新增了 ==事件和生命周期钩子== ,插件可以通过监听生命周期钩子被动获取数据和处理事件,而不需要主动向 `IMCServerService` 依赖注入接口进行查询。
## 一些有用的文档
* `v1.7` 版本主要变动请见:[SDK 完整接口与核心服务](/plugin-dev/backend/api/)
* `v1.6.4` 新增的接口:[事件系统与生命周期钩子](/plugin-dev/backend/events/)
* 不是给人类阅读的:[llms.txt](/llms.txt) | [llms-full.txt](/llms-full.txt)
---
---
url: /article/qq/index.md
---
# MSLX QQ交流群
---
---
url: /community-resources/index.md
description: 这里是MSLX的社区资源页面鸭~
---
# 社区资源
::: tip 这里是一些 MSLX 的社区开发者做的一些衍生项目。如果您也对 MSLX 做了一些二次开发的项目,欢迎PR提交到本页面!
:::
::: important 在使用第三方项目时,请务必保护您的API密钥。
:::
## AstrBot Plugin - MSLX 服务器管理
对接 [MSLX](https://github.com/MSLTeam/MSLX) Minecraft 服务器管理面板的 AstrBot 插件,通过聊天指令远程管理并控制您的 MC 服务器。
开发者:[@LotusGoddes](https://github.com/LotusGoddes)
---
---
url: /docs/config/msl-oauth/index.md
---
# 配置MSL账号登录面板
::: tip
配置此内容后可以在您的MSLX中直接使用您的MSL用户中心的账号进行快捷登录,方便&安全!

:::
## 注册MSL OAuth 2.0 APP
进入MSL用户中心的OAuth App管理页面,点击添加应用。
[MSL OAuth App管理](https://user.mslmc.net/user/oauth){.readmore}
配置好应用名称(随便写),logo地址(可选),回调地址(需要在MSLX设置中复制),权限选择用户信息即可。


注册成功后,请保存显示的 ==ID和Secret信息== 。
注意:您需要 ==联系管理员== 对App信息进行审核方可正式启用。

## 在MSLX配置 MSL OAuth 2.0
进入设置页面,将获取到的ID和密钥信息进行填入即可。


\==记得点击保存哦~==
## 绑定和登录
保存配置后,即可在上方用户信息处进行绑定MSL账号。

绑定成功后就可以使用MSL账号一键登录您的MSLX面板啦~

---
---
url: /docs/config/multi-nodes/index.md
---
# 连接多个节点
## 简介
MSLX自`v1.5.4`版本起试验性的支持在面板端连接多个子节点。主节点和子节点均需要大于等于此版本才支持连接。
::: warning 分布式子节点管理涉及较为复杂的远程通信与网络鉴权,目前 ==仍处于开发及测试阶段=={.warning}。此功能仅供测试体验,请==切勿将其直接部署于商业化或关键性生产业务环境=={.warning},以规避可能出现的不稳定风险。
:::

## 前置条件
需要连接子节点需要满足如下条件:
* 主节点与子节点之间可以完全 ==互相访问==
* 操作者面板可以与主节点和子节点间直接访问
* 子节点如果配置了SSL,必须是 ==有效证书== (不然浏览器会连不上的)
* 如果您的主节点面板配置了SSL,您的全部子节点均需要配置 ==有效证书==
## 子节点
子节点需要配置为`子节点模式`才可以被其他节点连接。
### 方法1:启动参数法
使用参数 `--slave` 和 `--linkkey` 。其中 --slave 代表启动子节点模式,--linkkey 为指定子节点连接密钥(非必需)。
最简子节点启动方式:(此方式会随机一个子节点连接密钥)
```shell
MSLX-Daemon --slave
```
指定连接密钥方式:(请确保连接密钥足够复杂)
```shell
MSLX-Daemon --slave --linkkey my-mslx-key-xxxxx-xxxxx
```
启动成功后,软件会在日志和初始信息文件显示当前连接密钥。
### 方法2:手动修改配置文件
找到文件:`DaemonData/Configs/Config.json`。
手动添加配置项,如:
```json
"IsSlaveMode": true,
"SlaveLinkKey": "mslx-slave-secret-key-2026",
```
---
---
url: /docs/config/remote-access/index.md
---
# 配置远程访问MSLX
由于MSLX的设计架构,您很容易配置远程访问。
注意:当前MSLX桌面版客户端尚在研发中,所以这里暂时只介绍如何配置面板的远程访问。
## 环境要求
强烈建议您的环境需要 ==支持Websocket== 。
!!其实没有WS也能跑的,前端会自动切换到长轮询的模式,就是性能......!!
::: important 安全须知
我们强烈建议您在部署远程访问的时候添加 ==SSL=={.important} 支持。(用nginx之类的反向代理一下)。
否则,直接暴露出去就是完全不加密的。
:::
## 放行公网访问
::: tip 这需要公网IP
如果你没有公网IP,可以直接看下一个段落的。
:::
::: important 更建议的方案
我们更建议使用nginx等软件,进行本地反向代理并添加 ==SSL证书=={.important},然后通过其访问 ,以增强安全性。
:::
由于安全考虑,MSLX守护进程默认监听`localhost`,若需要公网访问,您需要把监听地址修改为`0.0.0.0`,或者是您的网卡IP地址,也行。不懂就直接设置`0.0.0.0`是最快的。
::: tip 关于远程访问
守护进程端默认监听`1027`端口,若您配置监听`0.0.0.0`地址后仍无法访问,请检查系统防火墙配置防火墙 (ufw/iptables),以及服务商防火墙配置(如果是带额外防火墙功能的云服务器)。
:::

我的服务器是纯命令行环境,进不去网页控制台怎么办?
我们也提供了启动参数的配置模式:(只要用过一次启动参数,默认就会写入配置,下一次也会自动沿用配置)
```shell
MSLX.Daemon --host 0.0.0.0 --port 1027
```
## 使用内网穿透
由于大部分家庭宽带均没有 ==公网IP== ,那就只能内网穿透咯。
::: important 更建议的方案
我们更建议使用nginx等软件,进行本地反向代理并添加 ==SSL证书=={.important},然后使用Frp的HTTPS隧道。
:::
如果不考虑SSL,可以直接使用Frp的`HTTP/TCP`隧道映射端口`1027`(这是MSLX守护进程默认端口,如果你修改了,那就对应修改Frp配置即可)。

---
---
url: /docs/faq/main/index.md
---
# 常见问题
::: tip 善用搜索
善用 ==搜索== 功能,也许可以帮您快速找到您的问题的解决方案~
如果这里的常见问题都没能解决您的问题,您可以在右侧找到我们的 ==QQ交流群== 加入与群友们探讨解决。
:::
## 服务器日志乱码/输入中文指令内容乱码或"???"
#### ❔问题呈现:
日志输出是乱码符号:

或者输入指令包含中文时无法识别,变成“???”:

又或者是在控制台遇到其他的乱码情况,出现很多不认识的字符······
#### ✅解决方案:
进入实例设置,调整输入/输出的编码即可。(修改后保存重启才生效哦!)
如果是 ==Windows== 系统,那么一般是`输入UTF-8`/`输出GBK`。
如果是 ==Linux/macOS== 系统,那么一般`输入输出都是UTF-8`。

::: tip
如果按照上述方案修改后仍然乱码,可以尝试对这两个选项进行 ==排列组合== 测试,反正也就这几种组合。
正常来说,创建服务端时MSLX会根据当前的系统类型自动选择合适的编码,若非认为修改,一般都能直接正常使用。
!!当然,也可能是因为你修改了系统默认编码。比如简体中文版Windows默认是GBK,然后你改成了UTF8。!!
:::
## Frp(内网穿透)启动的时候报病毒/垃圾文件
#### ❔问题呈现:
\==此问题仅在高版本Windows下存在==

#### ✅解决方案:
在任务栏中找到 ==Windows 安全中心== (又叫Windows Defender),进入 ==管理设置== 。

拉到最下面,找到 ==排除项== 。

\==添加排除项== ,并选择 ==文件夹==。

然后选择您 ==MSLX所在的文件夹== 即可。
操作完成后即可尝试再次启动Frp隧道。
## Frp(内网穿透)启动的时候报应用程序控制策略已阻止此文件, 可能不需要的 application。
#### ❔问题呈现:
\==此问题仅在新版本Windows11上会出现,于2026-1-27遇到,情况是未签名的应用/dll库均不允许打开==

#### ✅解决方案:
打开 ==设置== ,搜索 ==智能应用控制== 。

选择 ==关闭== ,然后 ==确认==。


::: tip 这玩意用处不大,反而阻止了很多软件的使用,可以放心关闭。
:::
---
---
url: /docs/install/docker/index.md
---
# 在 Docker 中安装
::: warning 使用容器部署需要一定的使用经验
如果您没有使用过Docker部署服务,可能对你而言使用 ==直接安装=={.warning} 的方法会更加简单。
建议了解相关知识后再使用容器部署。
当然,本文档写的已经 ==尽量详细=={.warning} 新手也差不多能看明白并安装成功。
:::
::: tip 关于容器
当您将MSLX守护进程部署在容器运行后,您所有在MSLX上运行的 ==MC服务端/其他类型实例== 也均会运行在此容器上。
容器镜像自带了 OpenJdk 17 和 21版本环境,在创建服务端选择Java时可以直接选择 ==本地Java== 就能看见自带的Java环境了。
若这两个版本不符合您的MC版本要求,MSLX的 ==在线安装Java== 功能依旧 ==有效== 。
:::
::: important 系统架构支持
自 MSLX-Daemon ==v0.5.3.1-beta=={.important} 版本起,会自动构建 `amd64` 和 `arm64` 架构的镜像,拉取时会自动选择。
\==我们不会对32位的架构做支持,其完全不适合用于开服。=={.important}
:::
## 容器镜像地址
MSL容器镜像源 (中国大陆/中国香港): `docker.mslmc.cn/xiaoyululu/mslx-daemon:latest`
Dockerhub: `xiaoyululu/mslx-daemon:latest`
\==正常情况下建议直接拉取MSL容器镜像源,如果出现无法拉取的问题再使用Dockerhub源(可能需要配置加速镜像)==
## 手动安装
:::: steps
1. ### 安装Docker(已安装可跳过)
```shell
# 安装curl(如果没有)
apt install curl # 如果不是apt那就自己换一下
# 安装Docker
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
# 将当前用户加入 docker 组
sudo usermod -aG docker $USER && newgrp docker
# 启动 Docker 并设置开机自启
systemctl enable --now docker
# 验证安装
docker -v
```

::: tip 配置镜像源
如果您使用Dockerhub来拉取镜像,您可能需要设置加速镜像才能正常拉取。(如何配置请自行查找)
这里建议直接使用 ==MSL的容器镜像== 拉取,正常情况下还是比较快的。
:::
2. ### 安装并启动MSLX守护进程 - 配置文件方法
```shell
# 创建数据目录(也可以换成你喜欢的目录)并定位到目录
mkdir -p /opt/mslx && cd /opt/mslx
```
在这个文件夹新建一个配置文件`docker-compose.yml`。(可以直接在ssh的文件管理,也可以使用vim/nano等编辑工具)。
输入以下配置文件(可以根据需要修改,不会改就默认即可)。
```yaml
services:
daemon:
image: docker.mslmc.cn/xiaoyululu/mslx-daemon:latest
# image: xiaoyululu/mslx-daemon:latest # 这是Dockerhub的仓库,如果需要从Dockerhub拉取,请取消这行注释并注释掉上一行。
container_name: mslx-daemon
restart: always
# 端口映射
ports:
- "1027:1027" # 服务面板端口
- "25565-25585:25565-25585/tcp" # Java版游戏端口预留
- "25565-25585:25565-25585/udp" # 基岩版游戏端口预留
- "19132-19142:19132-19142/udp" # 基岩版游戏端口预留
# 数据挂载
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/DaemonData
environment:
- TZ=Asia/Shanghai
# - host=* # 配置监听地址,默认是*,没有特殊需求不需要改
# - port=1027 # 配置监听端口,没有特殊需求不需要改(改了的话上面的端口映射配置需要一起修改)
```
```shell
# 启动
docker compose up -d
```
执行启动后,Docker会自动拉取镜像和启动MSLX守护进程端。
如图即为成功:(如果`Created`后没有反应,可以按下回车,然后输入`docker ps -a` 查询状态)

3. ### 安装并启动MSLX守护进程 - 一键指令方法
::: tip
如果已经根据步骤二启动过了,那么这一步请略过不看。
\==更推荐步骤二的方法==
:::
```shell
docker run -d \
--name mslx-daemon \
--restart always \
-p 1027:1027 \
-p 25565-25585:25565-25585 \
-v $(pwd)/mslx_data:/app/DaemonData \
-v /var/run/docker.sock:/var/run/docker.sock \
-e TZ=Asia/Shanghai \
docker.mslmc.cn/xiaoyululu/mslx-daemon:latest
```
或者使用Dockerhub源:
```shell
docker run -d \
--name mslx-daemon \
--restart always \
-p 1027:1027 \
-p 25565-25585:25565-25585 \
-v $(pwd)/mslx_data:/app/DaemonData \
-v /var/run/docker.sock:/var/run/docker.sock \
-e TZ=Asia/Shanghai \
xiaoyululu/mslx-daemon:latest
```
4. ### 查询默认账号信息和一些注意事项
由于启动后可能没有日志输出,输入以下指令查询日志:
```shell
docker logs -f mslx-daemon
```

然后打开`http://localhost:1027`即可登入MSLX面板控制端。

::: tip 关于数据位置
在您没有修改启动配置文件/指令的情况下:
使用配置文件启动方法,默认数据保存在`/opt/mslx/data`。
使用一键启动命令方法,默认数据保存在`当前目录/mslx_data`。
:::
::: important 关于端口
以上的默认配置会把docker的`1027`端口以及`25565-25585`端口映射到主机,开服可以优选选择25565以及后面这20个端口,就不需要额外配置。
:::
5. ### 关闭/更新/重启MSLX
#### # 关闭MSLX容器
```shell
# 如果是配置文件的启动方式
cd /opt/mslx && docker compose down
```
```shell
# 如果是一键指令的方法
docker stop mslx-daemon
# 想再开就 docker start mslx-daemon
```
#### # 重启MSLX容器
```shell
docker restart mslx-daemon
```
#### # 更新MSLX容器镜像
更新不会删除数据,除非你自己删了。
```shell
docker pull docker.mslmc.cn/xiaoyululu/mslx-daemon:latest
docker rm -f mslx-daemon
# 然后重新运行启动命令 (up -d)
```
::::
## 使用 fnOS (飞牛OS) Docker 管理器部署
::: important 手动安装的重要提醒
!!踩了很多坑之后得出的结论!!
建议完全按照本教程来部署MSLX在fnOS上,不然 ==更新会超级麻烦=={.important} 。
\==切勿直接在镜像仓库安装MSLX=={.important} ,目前不知道为什么安装后无法检测更新。
:::
@[bilibili](BV1zfFBz4E6A)
:::: steps
1. ### 新建Compose项目
来到飞牛管理页面的 ==Docker== 管理器内,切换到 ==Compose== 选项卡,点击 ==添加项目== 。

输入项目名字(随便起),选择MSLX数据保存的位置,然后选择 ==创建docker-compose.yml== 。
将以下配置文件粘贴进去。
```yaml
services:
daemon:
image: docker.mslmc.cn/xiaoyululu/mslx-daemon:latest
# image: xiaoyululu/mslx-daemon:latest # 这是Dockerhub的仓库,如果需要从Dockerhub拉取,请取消这行注释并注释掉上一行。
container_name: mslx-daemon
restart: always
# 端口映射
ports:
- "1027:1027" # 服务面板端口
- "25565-25585:25565-25585/tcp" # Java版游戏端口预留
- "25565-25585:25565-25585/udp" # 基岩版游戏端口预留
- "19132-19142:19132-19142/udp" # 基岩版游戏端口预留
# 数据挂载
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/DaemonData
environment:
- TZ=Asia/Shanghai
# - host=* # 配置监听地址,默认是*,没有特殊需求不需要改
# - port=1027 # 配置监听端口,没有特殊需求不需要改(改了的话上面的端口映射配置需要一起修改)
```

确定创建即可,创建成功后启动项目。
2. ### 启动MSLX
等待镜像构建成功后,进入 ==容器== 页面,查询 ==运行日志== 。


在 ==运行日志== 中获取到初始的用户密码。

然后访问 ==MSLX控制台== (如果这里`1027`端口跳转过去之后无法正常访问,请把协议头从`https`改成`http`)。

使用 ==初始账号密码== 登录即可。(记得及时修改初始账户名和密码哦)。

3. ### 更新方法
!!由于不知道何种神秘力量影响,MSLX Docker镜像的更新在fnOS上无法检测到。!!
来到 ==Compose== 页面,停止MSLX项目。

然后来到 ==容器== 页面,删除`mslx-daemon`容器。(放心删,MSLX的数据文件存储在了你挂载的数据目录,是不会被删的。还不放心就备份一下吧。)

再然后来到 ==本地镜像== 页面。删掉`***/xiaoyululu/mslx-daemon`这个镜像。

最后,回到 ==Compose== 页面,重新启动MSLX项目即可,会自动拉取最新版本的镜像进行构建。

::::
## 使用 宝塔 的Docker管理部署
进入宝塔的容器页面。

选择 ==命令创建== ,然后输入一下指定,然后执行。(此命令中,默认把数据存在了`/www/wwwroot/mslx-daemon`,你也可以根据喜好编辑存储数据的位置)。
```shell
docker run -d \
--name mslx-daemon \
--restart always \
-p 1027:1027 \
-p 25565-25585:25565-25585 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /www/wwwroot/mslx-daemon:/app/DaemonData \
-e TZ=Asia/Shanghai \
docker.mslmc.cn/xiaoyululu/mslx-daemon:latest
```
或者使用Dockerhub源:
```shell
docker run -d \
--name mslx-daemon \
--restart always \
-p 1027:1027 \
-p 25565-25585:25565-25585 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /www/wwwroot/mslx-daemon:/app/DaemonData \
-e TZ=Asia/Shanghai \
xiaoyululu/mslx-daemon:latest
```

等待创建完成后,进入容器详情,查询日志即可获取 ==默认管理账号密码== 。
然后即可访问控制台进行登录访问(建议额外配置nginx反向代理)。

::: warning bug?
测试时发现命令创建成功后容器详情 ==没有正确读取到命令配置的端口映射=={.warning} ,不知道是啥问题(可能是宝塔不能识别范围端口)。
如果遇到无法使用的情况,可以参照第一步手动安装。
也可以尝试创建容器内的 ==手动创建=={.warning} 方法,按照指令填写参数(如果你会的话)。
:::
## 使用 1Panel 部署
::: tip
由于1Panel原本就是容器化的面板,确实会比较的适合。
:::
在容器页面进行新增容器,按以下配置。
镜像:`docker.mslmc.cn/xiaoyululu/mslx-daemon:latest` 或者使用Dockerhub源: `xiaoyululu/mslx-daemon:latest`
端口:`1027`是 ==必须映射== 的,这是面板默认服务端口。25565-25585是预留的MC服务器端口,可以自行修改。

\==挂载== (服务器内目录也可以更改为自己喜欢的目录,容器内目录必须是`/app/DaemonData`)。

\==环境变量== 推荐配置:`TZ=Asia/Shanghai`。

\==重启规则== 按照自己喜好即可。

然后确定,等待任务完成即可。

查询日志即可找到 ==默认管理账号密码== ,然后访问您的IP地址+1027端口即可访问面板(建议套一层nginx反向代理哦!)

---
---
url: /docs/install/fnos/index.md
---
# 在 FnOS (飞牛) 上安装
::: important 版更说明
受限于飞牛的应用商店的更新审核机制,MSLX主线的更新无法立即同步到飞牛应用商店中。
飞牛商店版本大概是 ==每周会同步一次主线版本更新=={.important} ,可直接在商店中更新。
若希望及时用上新版本,可以参考上方`使用 FnOS Docker 管理器`。
:::
## 视频安装教程
@[bilibili](BV1krcSzaE34)
## 文本安装教程
:::: steps
1. ### 在应用商店安装MSLX
在应用商店中搜索`MSLX`,然后进行安装。
注意选择安装位置,==后续您的所有MC服务端文件均存放在此处== 。

2. ### 查询初始账户密码信息
安装完成后,进入以下路径查询初始账户信息:`文件管理 → 应用文件 → MSLX → 初始登录凭证.txt`。

复制里面的密码即可。
3. ### 登录到MSLX控制台
从桌面的MSLX图标点击进入MSLX控制台,使用刚才复制的账户密码即可完成登录(记得立即修改初始账户密码哦)。
::: tip 关于端口
MSLX使用的是NAS设备的`1027`端口,请确保可以正常访问。
:::
::::
---
---
url: /docs/install/linux/index.md
---
## 一键安装
\==脚本支持大部分Linux系统,如果安装不成功,请自行手动安装MSLX。==
Linux 通用版本(Ubuntu/Debian/CentOs/Arch系 等等):
```bash
curl -sL "https://files.mslmc.cn/d/MSL/MSL%20Resources/MSLX/scripts/20260708/install_common.sh?sign=S4vPlcS2dhdrSEFr4vkOmiCgfp_E6UMxwb7l-kTpmKo=:0" | sudo bash
```
Alpine Linux 版本:
```bash
apk add curl sudo bash # 安装必要软件包
curl -sL "https://files.mslmc.cn/d/MSL/MSL%20Resources/MSLX/scripts/20260708/install_alpine.sh?sign=i31UvXEqfNAzJ_YemSGnpLKS7JILQPqEa4rmx9SEXyk=:0" | sudo bash
```
::: tip 关于监听地址的选择
脚本运行会询问您监听的地址,如果不知道选什么,建议选监听全部地址。
若想直接使用ip+端口访问,那么就选2监听全部地址。
若想frp映射端口/nginx本地反向代理,那么选1监听本机即可。
:::
::: tip 关于远程访问
守护进程端默认监听`1027`端口,若您配置监听`0.0.0.0`地址后仍无法访问,请检查系统防火墙配置防火墙 (ufw/iptables),以及服务商防火墙配置(如果是带额外防火墙功能的云服务器)。
:::
::: tip 关于Linux的mslx管理命令
开启mslx:systemctl start mslx\
关闭mslx:systemctl stop mslx\
重启mslx:systemctl restart mslx\
查看mslx日志:journalctl -u mslx -f
:::
::: warning 一键卸载脚本
```bash
curl -sL "https://files.mslmc.cn/d/MSL/MSL%20Resources/MSLX/scripts/20260708/uninstall.sh?sign=FFmB7MaL5FZXohXRQ7vslfcQ6gIO_Opx1-wG7tmuRjw=:0" | sudo bash
```
:::
## 手动安装
::: important 运行环境\
运行环境: ==.NET Core 10.0 LTS=={.important}
(一般系统都不自带此环境,请确保您安装成功了)
```shell
# 安装依赖
apt-get update && apt-get install -y libicu-dev
# 如果是CentOS等系统 请使用 yum install -y libicu
# 下载并安装.NET Core 10.0 SDK
wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh
chmod +x ./dotnet-install.sh
./dotnet-install.sh --channel 10.0 --install-dir /usr/share/dotnet
# 建立全局软链接
ln -sf /usr/share/dotnet/dotnet /usr/bin/dotnet
# 设置权限
chmod -R 755 /usr/share/dotnet
# 验证安装
dotnet --info
```
```shell :collapsed-lines=3
# 正常安装成功输出如下
.NET SDK:
Version: 10.0.101
Commit: fad253f51b
Workload version: 10.0.100-manifests.c57ac48b
MSBuild version: 18.0.6+fad253f51
Runtime Environment:
OS Name: ubuntu
OS Version: 24.04
OS Platform: Linux
RID: linux-x64
Base Path: /root/.dotnet/sdk/10.0.101/
.NET workloads installed:
There are no installed workloads to display.
Configured to use workload sets when installing new manifests.
No workload sets are installed. Run "dotnet workload restore" to install a workload set.
Host:
Version: 10.0.1
Architecture: x64
Commit: fad253f51b
.NET SDKs installed:
8.0.416 [/root/.dotnet/sdk]
10.0.101 [/root/.dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 8.0.22 [/root/.dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 10.0.1 [/root/.dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 8.0.22 [/root/.dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 10.0.1 [/root/.dotnet/shared/Microsoft.NETCore.App]
Other architectures found:
None
Environment variables:
DOTNET_ROOT [/root/.dotnet]
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
```
:::
在确定安装好 ==运行环境== 后,将`MSLX.Daemon`放在你喜欢的位置,然后赋予可执行权限,然后启动`MSLX.Daemon`软件即可。
如果出现闪退,那么就还是运行环境没有安装好或者是可执行权限没给。
守护进程:目前需要自行配置`systemd`或`supervisor`进行进程守护,后续会出一键安装脚本,敬请期待~
---
---
url: /docs/install/macos/index.md
---
# 在 macOS 上安装
## 一键安装
\==需确保已拥有Homebrew环境。请自行查找配置Homebrew环境的教程。==
安装命令:
```bash
brew tap MSLTeam/tap && brew trust mslteam/tap && brew install mslx-daemon && brew services start mslx-daemon
```
安装完成后会自动打开登录页面,并且会自动打开初始账号密码。
更新命令:
```bash
brew update && brew upgrade mslx-daemon && brew services restart mslx-daemon
```
::: warning 完全卸载命令(完全清除用户数据):
```bash
brew services stop mslx-daemon && brew zap mslx-daemon && brew untap MSLTeam/tap
```
:::
## 手动安装
::: important 运行环境\
运行环境: ==.NET Core 10.0 LTS=={.important}
(一般系统都不自带此环境,请确保您安装成功了)
:::
在确定安装好 ==运行环境== 后,将`MSLX.Daemon`放在你喜欢的位置,然后赋予可执行权限,然后启动`MSLX.Daemon`软件即可。
如果出现闪退,那么就还是运行环境没有安装好或者是可执行权限没给。(可能需要在 ==隐私与安全== 中放行)
注意:MSLX.Daemon 并非标准的mac app格式,==请不要把他放进去application目录== !
::: tip 文件存储位置
由于macOS的安全机制,通常不应该在软件的目录存储数据。
故目前默认数据目录位于:`/Users/用户名/Library/Application Support/MSLX`
:::
::: warning 关于SIP (系统完整性保护)
如果您在新版本macOS系统中启动MSLX守护进程端遇到错误:`Failed to create CoreCLR, HRESULT: 0x8007000C`。
若您曾关闭过SIP功能,请尝试重新打开SIP以运行MSLX。
[相关内容请见 → **#110 · MSLTeam/MSLX**](https://github.com/MSLTeam/MSLX/issues/110#issuecomment-4231051520){.readmore}
:::
---
---
url: /docs/install/start/index.md
---
# MSLX 介绍
## 关于 MSLX

\==MSLX== 是由 [**MSL**](https://www.mslmc.cn) 原班团队 **MSLTeam** 倾力打造的全新一代开服工具。基于 ==.NET Core 10.0== 环境。
它传承了 MSL 经典的 UI 设计语言,旨在让操作零门槛——无论是老用户还是新伙伴,都能即刻上手,极速部署您的 MC 服务器。
MSLX 不仅 ==完美支持跨平台== (Windows / macOS / Linux) 运行,相比前代,更引入了强大的 ==远程访问== 功能,让管理更自由。
@[bilibili](BV13NkWBxEwg)
## 与MSL的区别?
MSLX采用的是 ==前后端分离== 的模式。
简而言之,==Daemon== 端负责管理您的服务器,而 ==网页控制台/桌面客户端== 负责控制您的服务器管理器。
因此可以实现远程管理您的服务器,只需要使用 ==网页控制台/桌面客户端== 连接您守护进程的服务即可,您可以查阅相关文档完成此操作。
## 开发进度
目前 MSLX 发布了基于网页控制台的版本,基于AvaloniaUI的全平台客户端仍在开发中······
也欢迎大家尝试和积极[反馈问题和建议](https://github.com/MSLTeam/MSLX)哦~
## MSLX 技术栈
* \==MSLX Daemon== : ASP.NET Core (.NET Core 10.0 LTS)
* \==MSLX 网页控制台=={.important} : Vue3 + Pinia + TypeScrpt
* \==MSLX 桌面客户端=={.tip} : AvaloniaUI (.NET Core 10.0 LTS)
## 安装使用
\==暂时仅提供 Daemon 守护进程端的安装==,桌面客户端仍在开发中······
---
---
url: /docs/install/windows/index.md
---
# 在 Windows 上安装
::: important 运行环境\
运行环境: ==.NET Core 10.0 LTS=={.important}
(一般系统都不自带此环境,请确保您安装成功了)
**不建议将MSLX放置于磁盘根目录或C盘某些特殊目录(如临时目录或需要管理员权限的目录),否则后果自负!**
**建议在使用MSLX时给软件所处目录添加至杀毒软件信任区中,或在杀软提示时及时添加信任,防止误杀**。
:::
在确定安装好 ==运行环境== 后,直接启动`MSLX.Daemon`软件即可。
如果出现闪退,那么就还是运行环境没有安装好。
---
---
url: /docs/proxy/frp-real-ip/index.md
---
# Frp获取用户真实IP
默认情况下,开启Frp后,MC服务器获取到的IP均为本地回环地址`127.0.0.1`。
按照以下操作即可开启frp的`proxy protocol`协议以支持获取用户真实IP。
::: warning 注意
开启此协议需要您正在使用的服务端 ==支持proxy protocol=={.warning} 协议。
并且大部分情况下,启用此协议支持后您 ==无法再通过非代理地址=={.warning}(即内网/本地IP地址)直接进入您的服务器。
:::
:::: steps
1. ### 配置隧道参数
这里以 ==MSLFrp== 为例进行配置,其他Frp服务商请自行寻找相关配置方法或者自行修改Frpc配置文件。
首先,在创建隧道的时候填写开启协议支持的额外参数:
```toml
transport.proxyProtocolVersion = "v2"
```

然后按照正常步骤启动Frp隧道。
2. ### 配置服务端协议支持
接下来需要配置服务端的支持(这里以paper端为例)。
::: warning 注意
\==并非所有服务端都支持此协议=={.warning},例如Spigot端就不支持。
\==大部分的paper及其下游服务端=={.warning} 是支持的,其他服务端可以自行寻找模组/插件进行支持。
:::
找到paper的配置文件`config\paper-global.yaml`,找到配置组`proxies`,将配置项`proxy-protocol`修改为`true`即可,而后重启您的服务端就完成了所有的配置流程。

玩家再次加入服务器时,即可正常获取真实的IP。
::::
::: tip 其他支持方案
* 使用[Velocity](https://papermc.io/software/velocity)代理端嵌套您的插件/模组服务端以实现(此代理端支持上述proxy协议),可能需要配合此模组:[Proxy Compatible Forge - MC百科](https://www.mcmod.cn/class/13564.html) 或者此插件:[Ambassador - Minecraft Plugin](https://modrinth.com/plugin/ambassador/versions)。
* Fabric可以看看这个模组(似乎很久没更新了):[Proxy Protocol Support - Minecraft Mod](https://modrinth.com/mod/proxy-protocol-support/versions)。
* 对于模组端,可能更加通用的方案仍然是使用上述所说的代理端。
:::
---
---
url: /docs/proxy/frp/index.md
---
# 内网穿透(Frp)配置
::: tip 内网穿透(Frp)
[这是什么? 前往**GoFrp项目官网** 了解](https://gofrp.org/zh-cn/){.readmore}
简单来说,就是把 ==内网的服务映射到公网== 。
由于很多家庭宽带是不提供 ==公网IP== 的,想用家里的电脑/没有公网IP的设备开服就需要用到内网映射服务,将您的服务器映射到公网以让其他小伙伴加入游玩!
:::
## MSLFrp
MSLFrp是嵌套于 ==MSL用户中心== 的服务。
本服务由MSLTeam与广州兮辰云科技联合提供。
:::: steps
1. ### 登录到MSLFrp
首先,进入MSLX的 ==添加隧道== 页面,登录到MSL账户。
若未注册MSL账户,请先前往 ==MSL用户中心== 注册账户。
[MSL用户中心](https://user.mslmc.net){.readmore}
2. ### 添加隧道
点击添加隧道,会跳转到 ==MSL用户中心== 的隧道管理页面,需要在这里新建隧道(如果是Java版本服务端,端口和协议都是默认不需要修改的)。

3. ### 导入隧道到MSLX
创建隧道后,回到MSLX的 ==创建隧道== 页面,并刷新,选择刚才新建的隧道,添加即可。

4. ### 启动隧道
回到 ==隧道列表== 页面,点击你刚才创建的隧道进入启动页面。

\==启动== 隧道,成功后即可使用 ==连接地址== 进入您的MC服务器。(右侧的连接地址单击后可以快捷复制的哦~)

::::
::: tip
由于内网穿透的特性,默认情况下通过内网穿透进入的玩家IP都是`127.0.0.1`。
这可能导致部分登录插件识别到是同一台电脑的玩家登录,也可能导致封禁使用`/ban-ip`后全员进不去。
通过调整登录插件的配置,以及不使用`/ban-ip`是个比较好并且简单的方案(或者使用外置验证登录)。
如果还是希望获取玩家真实IP,请看这里:
[教程 - **Frp获取用户真实IP**](/docs/proxy/frp-real-ip/){.readmore}
:::
## 其它Frp
更多Frp服务商仍在陆续适配中,若现阶段需要使用其他服务商的服务,可以参考下面 ==自定义Frp== 的说明进行创建隧道。
## 自定义Frp
选择 ==高级模式==,粘贴配置文件进去就好~(建议`toml`格式)。
通过此模式您可以快速启动MSL尚未接入的第三方Frp服务提供商。

---
---
url: /docs/proxy/p2p/index.md
---
# 点对点联机教程
::: tip 互通提醒
MSL和MSLX的点对点联机功能是 ==互通== 的,换言之,房主可以使用MSLX开放,成员可以使用MSL加入房间,反之亦然。
此处演示使用MSLX,MSL的教程可以看这里。
[点对点联机教程 | MSL开服器](https://www.mslmc.cn/docs/proxy/p2p/){.readmore}
:::
::: tip TIPS
点对点联机功能 ==无法穿透所有类型的NAT== ,如果你无法成功联机,请使用 ==内网映射== 功能\
由于Minecraft的限制,可能仅 ==正版用户== 才能成功联机,若你是离线用户,请 ==开服务器== 或者安装相关模组进行联机。
:::
## 房主部分
:::: steps
1. 下载与你的客户端对应的自定义联机模组(这是可选的,但是用了模组可以固定端口 / 关闭正版验证)。
[**mcwifipnp** 更高级联机设置 (LAN World Plug-n-Play)](https://www.mcmod.cn/class/4498.html){.readmore}
2. 启动游戏,进入一个单人世界。
3. 按ESC,呼出游戏菜单。
4. 点击 ==对局域网络开放== 。

5. 根据个人需要调整配置并确认。

6. 游戏左下角会给你一个 ==端口==,将此端口填入点对点联机的端口中。

7. 进入MSLX的 ==添加隧道== 页面,并选择 ==MSL联机==,然后填写房间号(建议是QQ号),以及密码(随便写即可)。

8. 配置完成后,进入隧道页面并选择刚才创建的联机房间,启动即可。
ps:右侧 ==隧道概览== 处,点击房间号和密钥是可以直接复制的哦~


::::
## 成员部分
::: tip 提醒
如果联机成员使用的是 ==Windows== 系统,更推荐使用MSL加入联机房间,会更方便。
[点对点联机教程 | MSL开服器](https://www.mslmc.cn/docs/proxy/p2p/){.readmore}
:::
:::: steps
1. 进入MSLX ==添加隧道== 页面,将房主给你的QQ号(==房间号==),==密钥== 填入。
2. 端口号默认为25565即可,成员 ==无需像房主那样更改端口号== ,然后添加隧道即可。

3. 配置完成后,来到 ==隧道列表== ,进入刚才添加的隧道,启动即可。

4. 启动成功后,进入和房主 ==版本一致的Minecraft客户端== 。
5. 点击 ==多人游戏== 。
6. 点击 ==直接连接==(或 ==添加服务器==)。
7. 在地址栏填写`127.0.0.1`(如果你更改了端口号,请在127.0.0.1后面加上半角冒号+你更改后的端口号,如:127.0.0.1:12337)

8. 然后即可成功联机。
::::
---
---
url: /docs/proxy/server-no-port/index.md
---
# Frp映射地址隐藏端口
::: tip 带端口的域名很难看(如 xxx.xx:12345)?本篇教程可以教您使用域名SRV解析隐藏端口!(仅限Java版)
:::
::: warning 经过测试,不一定所有的DNS服务都支持解析SRV记录,部分运营商的DNS服务可能会无法解析,切换到阿里云等其他常见的公共DNS可以解决。
:::
## 使用 MSLFrp 自带的子域名服务
::: tip 如果您正在使用 ==MSLFrp== 并且没有您自己的域名,可以使用 MSLFrp 自带的子域服务。
:::
创建并启动您的隧道,映射Minecraft 服务。

映射成功后,前往MSL用户中心的子域服务页面。点击添加解析记录。
[MSLFrp-子域服务 | MSL用户中心](https://user.mslmc.net/frp/dns){.readmore}
选择一个你心仪的域名后缀,然后填写子域名前缀和选择你刚才创建(启动)的那条Frp隧道,点击创建即可自动解析成功。
::: info 子域名前缀什么意思?
比如,你选择的公共域名后缀为`ovvo.space`。你想使用`qwq.ovvo.space`作为你的MC服务器连接地址。
那么就在子域名称处填写`qwq`即可。
:::

创建成功后,会显示您的连接地址,使用此地址即可进入您的服务器。

## 使用自定义域名实现
::: important 这需要您自己有一个域名!如果只是用于MC隐藏端口,没有强制备案要求。
:::
进入您的域名服务商解析控制台,添加解析记录。(这里以阿里云为例)。
域名记录选择 `SRV`,主机记录填写 `_minecraft._tcp.自定义子域名前缀`。
记录值:优先级和权重都写 `5` 即可(如果你有多个地址那就自己考虑了,一般统一写5即可)。
端口填写 ==您Frp服务商隧道的端口/服务器的端口==,目标地址填写 ==您Frp服务商隧道的连接地址/服务器IP地址== (允许填写IP地址/域名)。

创建成功后即可使用此地址连接。
假如您的域名是xxx.cn,填写的连接地址是`_minecraft._tcp.qwq`,那么连接地址就是`qwq.xxx.cn`。
---
---
url: /docs/resources/msl-mirrors/index.md
---
# MSL 服务端镜像源

## 简介
MSL服务端镜像源为 ==MSLTeam== 自主研发的MC服务端镜像源同步系统,支持诸多常用的MC服务端,且会定期从各服务端官方API拉取更新。
目前大部分服务端均在MSL服务器做了镜像,下载速度 ==非常快==~
部分服务端来自第三方源(如Forge端返回的是来自BMCL的下载地址)。
::: important 开发须知
MSL 服务端镜像源大部分采用了 ==自建加速镜像源=={.important},搭配了全球加速CDN,存在流量成本。因此,如果您需要使用我们的服务,请遵守以下规则,若发现违反的行为,我们有可能会在不通知的情况下在后端对相关请求进行屏蔽操作。
* 如果您需要在您的软件/应用中集成我们的下载服务,请务必在 ==使用本API的软件页面=={.important} 注明 `本服务由MSL开服器提供`,并带上我们的 ==Logo以及官网地址=={.important} 。
* 对于使用量大的情况,请务必向 `support@mslmc.net` 发送邮件进行相应申请,并带上您应用所使用的UA。
:::
## MSL服务端镜像源API文档(概述版)
::: tip API信息
API端点地址:
```
https://api.mslmc.cn/v4
```
MSL-API-V4 通用返回格式:
```json
{
"code": 200,
"message": "",
"data": ""
}
```
单IP QPS限制:中国大陆地区 ==20 QPS== | 海外(含港澳台) ==100 QPS==
请求API时请带上含有相应APP名字的 ==User-Agent==
:::
### 1.查询镜像源支持的服务端
```
/mirrors
```
返回服务端列表(分类显示),示例:
```json
{
"code": 200,
"message": "",
"data": {
"pluginsCore": [
"paper",
"purpur",
"leaf",
"spigot",
"bukkit",
"folia",
"leaves",
"pufferfish",
"pufferfish_purpur",
"spongevanilla"
],
"pluginsAndModsCore_Forge": [
"arclight-forge",
"arclight-neoforge",
"youer",
"mohist",
"catserver",
"spongeforge"
],
"pluginsAndModsCore_Fabric": [
"arclight-fabric",
"banner"
],
"modsCore_Forge": [
"neoforge",
"forge"
],
"modsCore_Fabric": [
"fabric",
"quilt"
],
"vanillaCore": [
"vanilla",
"vanilla-snapshot"
],
"bedrockCore": [
"bedrock-server",
"nukkitx"
],
"proxyCore": [
"velocity",
"bungeecord",
"lightfall",
"travertine"
]
}
}
```
```
/mirrors?view=list
```
返回服务端列表(无分类),示例:
```json
{
"code": 200,
"message": "",
"data": [
"paper",
"purpur",
"leaf",
"leaves",
"spigot",
"arclight-forge",
"arclight-fabric",
"arclight-neoforge",
"spongevanilla",
"youer",
"mohist",
"catserver",
"banner",
"spongeforge",
"neoforge",
"forge",
"fabric",
"bukkit",
"vanilla",
"vanilla-snapshot",
"folia",
"lightfall",
"pufferfish",
"pufferfish_purpur",
"travertine",
"bungeecord",
"velocity",
"bedrock-server",
"nukkitx",
"quilt"
]
}
```
### 2.查询服务端支持的MC版本
::: field name="server" type="String" required
服务端名字(从上一步获取到的)
:::
::::
```
/mirrors/{server}
```
返回支持的MC版本列表(数组),示例:
```json
{
"code": 200,
"message": "",
"data": {
"description": "[原版端推荐]Paper是基于Spigot的高性能Fork,仅支持插件",
"versions": [
"26.1.1",
"1.21.11",
"1.21.10",
"1.21.9"
]
}
}
```
### 3.查询特定MC版本的服务端下载地址
::: important 防滥用限制
本接口具有特殊的请求限制\
1小时: ==30次=={.important} 1天: ==60次=={.important}
:::
:::: field-group
::: field name="server" type="String" required
服务端名字
:::
::: field name="version" type="String" required
MC版本号
:::
::::
```
/download/server/{server}/{version}
```
返回下载地址链接和校验值(如果有),示例:
```json
{
"code": 200,
"message": "",
"data": {
"url": "https://file.mslmc.cn/servers/xxx/xxx.jar",
"sha256": "933514c5ff8df47ab8fdb106ad435945bf6512702f9299cc66c4d173a1b7062x"
}
}
```
::: warning 注意
并非所有服务端下载都会返回 ==sha256=={.warning} 这个key!
也有可能是这样的:
```json
{
"code": 200,
"message": "",
"data": {
"url": "https://file.mslmc.cn/mirrors/vanilla/xxx/server.jar"
}
}
```
:::
### 其他API
我们还支持获取各服务端的简介,服务端分类,部分服务端支持下载不同的构建版本的api接口,这些请参考Apifox文档啦~
---
---
url: /docs/resources/msl-skin/index.md
---
# MSL Skin (MSL皮肤站)
::: important ⚠️ 这并不能代替正版
\==请始终考虑购买正版的 Minecraft。=={.important}
使用正版的 Minecraft 可以为你提供更省心的游玩体验。
:::
[MSL Skin (MSL皮肤站) ](https://skin.mslmc.net)是基于 [Blessing Skin](https://github.com/bs-community/blessing-skin-server/) 的一个MC皮肤站点,并且支持对接外置登录 Yggdrasil API 。
简单来说,MSL Skin可以提供联机时的 ==皮肤== 和 ==鉴权服务==,但不提供联机服务本身。
此站点由MSLTeam二次开发,深度对接了[MSL用户系统](https://user.mslmc.net),使用统一的 ==MSL账号== 登录。

::: tip 有何优点?
* 只需要在启动器完成 ==一次登录== ,无需进服后再次输入`/login`。
* 方便的使用皮肤系统,而不需要打其他的补丁。
* 优雅的 ==账号控制==,其他人无法随意伪造您的用户名,也不能轻易注册多重账号,还可以防止服务器遭到假人压测。
:::
## 登录到MSL Skin
正如上文所说,MSL Skin使用的账号是您的 ==MSL账号== (即在MSL用户中心中注册的账号) ,进入MSL Skin网站登录时仅支持跳转MSL用户中心进行授权登录,==不支持账户密码登录==。如果您还没有MSL账号,您可以点击页面的注册按钮前往注册哦~

::: tip 关于默认角色名字
若您在MSL用户中心设置的昵称是符合角色名规范的,那么角色名将自动同步,若不符合命名规范,则会随机生成一个角色名,您可以在登录后自行修改。
:::
::: tip 关于UUID
本站采用了不兼容离线模式的UUID生成方式,即使您修改了游戏角色名,您的UUID也不会变化,换言之,==即使您修改了游戏角色名,您登录过的服务器玩家数据是不会变的==。
:::
::: tip 是否必须先登录皮肤站?
登录皮肤站 ==并非必须步骤==,您也可以按照下文配置好启动器外置登录后直接使用 ==MSL账户的账户密码==进行登录。但是如果需要修改角色名,还是需要前往皮肤站登录哦~
:::
## (玩家)游戏客户端配置&登录
目前主流的第三方启动器均支持配置外置登录,只需要填入MSL Skin页面提供的 ==外置登录API地址== 即可,如:


::: tip
如果您是服主分发整合包,可以提前配置好外置登录后再分发游戏哦~
:::
然后直接使用 ==MSL用户中心== 的账户密码登录即可。
## (服主)在MSLX中开服并将MSL Skin作为外置登录验证服务器
非常简单,在 ==服务端设置== 中的 ==外置登录设置== 中选择 ==MSL统一身份认证== 即可。

::: tip
如果您使用自定义模式创建服务器,那么在创建时已经会有启用外置登录的引导。
若您使用的是快速模式,您需要配置完成服务器后再前往服务器设置页面启用外置登录。
:::
启动服务器,出现以下提示即为配置成功!

::: warning 注意
一旦您的服务器启用了MSL Skin外置登录,您的 ==所有玩家=={.warning} 必须在游戏客户端配置好外置登录地址并 ==登录MSL账号=={.warning} 才能加入服务器哦。
并且,您需要 ==开启正版验证=={.warning},否则是无效的哦~
:::
## 使用MSL Skin登录进行联机
由于MC联机 (对局域网开放功能) 是默认存在 ==正版验证== 的,若离线登录是无法进行联机的。
此时便可以联机者均使用MSL Skin外置登录,即可顺利完成联机!
::: warning 注意
MSL Skin可以提供联机时的皮肤和鉴权服务,但 ==不提供联机服务本身=={.warning}。
:::
---
---
url: /docs/resources/oauth2/index.md
---
# MSL OAuth 2.0
::: tip TIPS
此处介绍的开发者将自己的服务 ==接入MSL统一身份验证==(即MSL用户中心服务) ==第三方登录== 。\
通过此服务,您可以将MSLX接入MSL账号快捷登录。
[配置MSL账号登录面板 | MSLX 开服器](https://mslx.mslmc.cn/docs/config/msl-oauth/){.readmore}
:::
## 1.申请OAuth App
进入MSL用户中心的OAuth App管理页面,点击添加应用。
[MSL OAuth App管理](https://user.mslmc.net/user/oauth){.readmore}

填写应用的 ==名字==,==图标==(推荐正方形,需要是可以外部访问的url地址),以及您的App的 ==回调地址== 。
注意:应用权限请保持默认的选择 ==用户信息== 。
::: tip 关于应用权限
如果你只是需要调用MSL用户中心进行登录,那么选择 ==用户信息== 是完全足够的。
\==所有权限== 是提供MSL账号的完全访问权限,仅适用于对接我们的其他服务(如MSLFrp),若您有这方面的需求,可以在Q群或者邮件联系我们商讨后为您开通相关权限并提供此授权模式的两种方法的文档(App/网页)。
:::

点击确定后,会返回您的App ==客户端ID== 以及 ==密钥== 信息。
::: important 注意
请妥善保管您的密钥,==密钥仅会显示一次=={.important} 。
后续若忘记密钥就只能重置了。
:::


::: info 审核
添加App后会进入待审核状态,请 ==联系管理员审核== 。
否则App无法正常调用哦!
:::
## 2.OAuth流程
::: tip OAuth 2.0
[什么是 OAuth2 ?](https://oauth.net/2/){.readmore}
MSL统一身份验证基于OAuth2的授权码模式规范设计\
若有出入,请联系反馈~
:::
::::: steps
1. ### 请求获取授权码(跳转MSL用户中心授权)
请求跳转授权地址:
```
https://user.mslmc.net/oauth/authorize
```
查询参数:
::: field name="client\_id" type="String" required default="NeQ5v7T72vm4Yi6ADyYAW6m4eVK"
客户端ID(第一步申请得到的)。
:::
::: field name="state" type="String" optional default="SiGEWINNEQWQ"
随机字符串,防止CSRF,请求方应当生成并记录此字符串,用于后续验证。
:::
::: field name="redirect\_uri" type="String" optional default="https://api.mslmc.cn/api/callback"
登录成功后重新向的地址(一般是编码的地址),若不传此参数则读取App设置的URI地址。
:::
示例拼接地址:
```
https://user.mslmc.net/oauth/authorize?client_id=NeQ5v7T72vm4Yi6ADyYAW6m4eVK&state=SiGEWINNEQWQ&redirect_uri=https%3a%2f%2fapi.mslmc.cn%2fapi%2fcallback
```
::: warning 最小示例拼接地址
```
https://user.mslmc.net/oauth/authorize?client_id=NeQ5v7T72vm4Yi6ADyYAW6m4eVK
```
但是**不建议**这么做,缺少 ==state=={.warning} 参数可能会导致一些风险(如:==跨站攻击=={.warning})哦~
:::
若地址正确,访问后应该是如下页面:

2. ### 使用授权码交换AccessToken
登录成功后,MSL用户中心将根据填写的App回调地址重定向并添加 ==code== 和 ==state== 参数(方法是GET)
::: tip
\==code== 有效期只有 ==10分钟== 。
:::
MSL用户中心授权成功的重定向示例:
```
https://api.mslmc.cn/api/callback?code=y94vzbhskzcizEDmJMbWt775tbI&state=iGEWINNEQWQ
```
您的客户端接收到回调后应该核对 ==state== 否与请求时的一致,若不一致,请 ==拒绝登录请求== 。
然后需要用拿到的code通过api交换得到AccessToken
```
https://user.mslmc.net/api/oauth/exchangeAccessToken
```
:::: field-group
::: field name="code" type="String" required default="y94vzbhskzcizEDmJMbWt775tbI"
回调拿到的授权码
:::
::: field name="client\_id" type="String" required default="NeQ5v7T72vm4Yi6ADyYAW6m4eVK"
您在第一步申请的客户端ID
:::
::: field name="client\_secret" type="String" required default="FAOFoGDPtTK8Yudlerv..."
您在第一步申请的客户端密钥
:::
::::
返回示例:
```json
{
"code": 200,
"msg": "授权成功",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsImlhdCI6MTc0NzU1NzY3MiwiZXhwIjoxNzQ3NTYxMjcyfQ.iyX0dIXxrUkr6Dg7HCZ7YNQb2G1u5EYpzh-6wKYJShg",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "user_info"
}
```
获取到 ==access\_token== 即可
[完整API文档:**获取Access Token - MSL-User-System**](https://apidoc-user.mslmc.cn/297247077e0){.readmore}
3. ### 获取用户信息
::: warning 接口适用提醒
本api接口仅适用于权限类型为 ==用户信息=={.warning} 的应用。
若您使用的应用类型为所有权限,请参照我们提供的API文档获取用户信息。
:::
```
https://user.mslmc.net/api/oauth/user
```
需要添加 ==Authorization== 请求头
在 Header 添加参数 Authorization,其值为在 Bearer 之后拼接 Token
示例:
```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsImlhdCI6MTc0NzU1NzY3MiwiZXhwIjoxNzQ3NTYxMjcyfQ.iyX0dIXxrUkr6Dg7HCZ7YNQb2G1u5EYpzh-6wKYJShg
```
返回示例:
```json
{
"code": 200,
"msg": "获取用户信息成功",
"uid": 1,
"username": "小可爱",
"email": "user@mslmc.cn",
"qq": null,
"score": 1500,
"avatar": "https://cravatar.cn/avatar/d31946d60f6051840edc9d41a1261?d=identicon&s=640",
"regTime": 1737992780,
"lastLoginTime": 1745988703,
"permission": 1,
"realName": false,
"lastCheckInTime": null,
"twoFactorAuth": true
}
```
请使用 ==uid== 字段作为判断用户绑定的参数,这是每位用户唯一的ID,且不会变化。
其他的信息按需使用/更新即可。
[完整API文档:**获取用户信息 - MSL-User-System**](https://apidoc-user.mslmc.cn/297251390e0){.readmore}
:::::
## 3.快速接入MSL登录
### # 接入到WordPress
使用此插件:
下载zip,并在您的wordpress上安装并启用插件。

在插件设置填写OAuth App信息:

回调地址要填写到OAuth App信息中

两边的信息配置好后,即可进入个人资料页面绑定MSL账户,绑定后即可使用MSL账户快速登录~

---
---
url: /docs/server-config/crons/index.md
---
# 定时任务
## 定时任务
MSLX 的定时任务对比原MSL的定时任务进行了全面的升级。
不仅支持 ==间隔性任务== 还支持 ==周期性任务== 。
支持的任务有:==开启/关闭/重启服务器、存档备份、发送指令== 。
## 配置定时任务
进入 ==服务端的设置弹窗== ,进入定时任务这一栏,开始进行配置。

定时任务是根据设置的 ==Cron表达式== 来决定执行的时间。
如果您熟悉Cron表达式的填写,那么就直接填写即可。
不会填写Cron表达式?没关系,我们也提供了可视化从编辑器。

### 时间间隔性任务
如果您只是想 `10分钟执行一次` 或者 `1小时执行一次`,那么可以直接在生成器的 ==新手模式== 下选择你喜欢的间隔,然后点击确定即可自动生成对应的表达式。(注意:只能填写整数哦)
::: demo-wrapper title="示例: 配置12小时执行一次备份的任务"
首先在表达式生成器中选择 ==单位== 为小时,然后填入 ==间隔的时间== 12小时即可。

点击确定,然后填写其他剩余的参数,保存即可。

:::
### 周期性任务
如果你想要 `每天的凌晨3点执行` / `每周的周一执行` ,那么 ==新手模式== 已经无法满足您的需求了,您需要切换到 ==专业模式== 。
看不懂如何配置?看下面的示例来理解一下吧!
::: demo-wrapper title="示例: 配置每天的凌晨3点执行"
`秒`: 指定为0秒 | `分`: 指定为0分 | `时`: 指定为3时
`日/月`: 保持默认为每周即可 | `周`: 这是可选配置,保持默认即可
最后的配置应该是这样的:

\==注意:一定要把秒和分改成0或者一个你喜欢的秒,否则就会变成指定周期内每秒/每分钟执行一次...==
:::
::: tip 还是看不懂?
有一个更简单的办法,问AI就好咯......
示例提示词:
```
我想在每天凌晨3点执行一次任务,请告诉我这个任务的Cron表达式怎么写。
```
:::
### 验证表达式正确性
\==建议使用哪种方法写的表达式都要看一下,避免出现奇怪的问题==
表达式生成器自带了 ==计算未来5次执行时间== 的功能,可以看一下这些时间是不是你所期望的,就能快速验证表达式的正确性了。

---
---
url: /docs/server-config/yggdrasil/index.md
---
# 配置服务端外置登录
::: important ⚠️ 这并不能代替正版
请始终考虑购买 ==正版的 Minecraft=={.important} 。
使用正版的 Minecraft 可以为你提供更省心的游玩体验。
:::
::: warning 注意
一旦启用了外置登录,您的 ==所有玩家=={.warning} 必须使用 ==同一外置登录服务=={.warning} 进入游戏。
否则将无法正常加入服务器!
:::
## 配置外置登录
首先,在您的 ==外置登录提供服务的站点处== 获取外置登录 ==验证API地址==,然后直接填入 ==MSLX的服务端服务器实例设置== 中即可!
若您使用MSL Skin的服务,可以直接选择 ==设置为MSL统一身份验证== 即可。
若您使用Littleskin的服务,可以直接选择 ==Littleskin== 即可。使用其他的服务请选择 ==自定义== 并填入API地址。
然后记得点击 ==保存== 哦!


然后开启您的服务器即可,您 ==不需要做任何的额外工作== 。(MSLX将自动帮您下载最新版本的authlib-injector并嵌入您的服务端运行)
出现如下提示即为正常连接到您的外置登录服务。

::: warning 注意
您配置了外置登录验证后请务必开启原有的 ==正版验证=={.warning} 。
否则是无效的。
:::
## 自建外置登录服务(皮肤站)
使用此开源项目即可:
---
---
url: /docs/server/bedrock/index.md
---
# 基岩版开服教程
::: tip 支持情况
官方基岩版服务端仅支持 ==Windows/Linux== 系统,
若您想使用macOS开基岩版服务器,请使用 ==容器== 运行MSLX。
[教程 -> **在 Docker 中部署 MSLX**](http://localhost:8080/docs/install/docker/){.readmore}
:::
## 快速搭建基岩版服务端
::: tip 这是 MSLX ==v1.3.3== 版本新增的功能,如果您正在使用更老的版本,请参考[手动添加基岩版服务端](#手动添加基岩版服务端)。
:::
:::: steps
1. ### 填写基本信息
进入 ==创建服务端== 页面,右上角选择 ==基岩版== 模式。
填写好名字和保存位置信息。!!忽略EULA提示的开关请保持打开,否则可能会出现怪异的现象......!!

2. ### 选择游戏版本
(release为正式版,beta为预览版,一般默认第一个即可)

3. ### 配置启动指令
没啥其他需要这里不需要改,直接 ==下一步== 就好。

4. ### 提交创建
确认信息无误后提交创建即可。


5. ### 开服 & 进入游戏
进入新建的服务端的控制台,然后开启即可。

配置内网映射和连接请参考 → [连接指南](#连接指南)。
6. ### 如何更新?
进入 ==实例设置== → ==更多功能== ,在这里可以一键更新!
::: tip 更新前务必 ==备份存档!!!==
:::

::::
## 连接指南
:::: steps
1. ### 配置内网映射
\==基岩版使用的协议是udp==。
::: tip
如果您有公网IP或者是局域网游玩,可以略过这一步。
但是如果需要本机进入本机的服务器,可能需要解除本地回环限制。(目前新版本基岩版似乎已经不是UWP应用了,可能已经不需要额外操作了)。
[解除UWP应用本地回环限制](https://www.minebbs.com/threads/uwp.17877/){.readmore}
:::
以MSLFrp为例,配置协议为`udp`,本地端口默认为`19132`。

创建隧道后进入MSLX的 ==隧道管理== 添加刚才的隧道,并启动即可。
2. ### 加入服务器
内网映射成功后,你应该会得到一个类似这样的IP地址`xxx.xxx.xxx.xxx:15566`
`xxx.xxx.xxx.xxx`即为IP地址,冒号后面的即为端口。
按照下图示例输入即可。

然后畅快的游戏吧~

::::
## 手动添加基岩版服务端
:::: steps
1. ### 下载MC基岩版官方服务端


2. ### 添加服务端实例
来到MSLX的 ==新建服务端== 页面,选择 ==自定义模式== 。
填写服务器名称,路径(可选),启动指令如果是Windows系统请填写`bedrock_server.exe`如果是Linux系统请填写`./bedrock_server`,填写完成后提交创建即可。

3. ### 上传&解压服务端文件
前往刚才创建的服务端实例页面,进入 ==文件管理== ,将刚才下载的 ==基岩版服务端压缩包== 上传。

上传成功后对此文件解压,注意 ==不要选择创建同名文件夹==。

解压出来是这样的。
::: tip 设置可执行权限
如果您正在使用Linux,请对着`bederock_server`文件设置 ==权限== 为755,都则可能无法运行。
:::
4. ### 启动服务端
返回控制台,即可启动服务端。出现`Server started.`字样即为启动成功。

5. ### 配置内网映射/进入游戏
参照上面的[连接指南](#连接指南)
::::
---
---
url: /docs/server/choose-server-tips/index.md
---
# 如何选择服务端
::: tip TIPS
请看右边的目录选择你的需求以查看~\
注意:就算是不推荐的端,您也可以按照个人需求使用。无论是否推荐,MSL内都提供了下载~
:::
## 纯生存
::: tip TIPS
此类服务端 ==大多都支持插件== ,不支持的另外说明。
:::
### 推荐的端
* \==Paper端==,老牌的基于Spigot的高性能Fork端,对于性能和特性都有不错的优化!美中不足是修改了一些原版的特性,比如TNT复制等(但是这是可以关闭的)。
* Purpur端,官方说性能比Paper更好,但是部分优化可能不太合适全部人,可以尝试。
* Leaves端,基于Paper的一款新服务端,只有1.19+的版本,可以尝试。
### 多线程服务端
* Folia端,一款支持多线程的服务端,**不支持已有大部分插件**,电脑性能差可选择!!!(洋垃圾救星?)!!
### 不推荐的端
* Bukkit端,插件端老祖,但是优化很少,不推荐。
* Spigot端,也算是插件端老祖了,优化也很少,不推荐。
* Vanilla端(即原版官方服务端),==**不支持插件**==,==无额外优化==,不推荐。!!(当然,你要追求原汁原味也不是不行)!!
## 插件与模组混合服
::: important 注意!
请注意:由于各种原因,==非常不推荐将客户端模组== 加入服务端(特别是这种模组+插件的端),可能会导致一大堆的Mixin错误!
因此,您可能需要手动清理部分客户端模组。
:::
### 推荐的端
* \==Arclight端==,高版本的模组+插件端首选,兼容性较好,更换Forge版本也挺方便。
* \==Mohist/Youer端==,较老牌的一款模组+插件端,支持版本丰富,更新频率快,新出的NeoForge也支持了,可以选用。
* Catserver端,在1.12.2的版本支持比较好,高版本建议选用上面这俩。
### 不推荐的端
!!似乎没有。!!
## 仅模组服(不含插件)
::: tip 提醒
以下端均 ==不支持插件== !
:::
### 推荐的端
* \==NeoForge端==,1.21+版本模组大部分都是支持这个哩,相比混合端 ==稳定性比较高== 。
* Forge端,老东西了,没啥可说,1.20.x及其更低版本基本用这个,稳定性会比模组插件混合端要好。
### 其它端
* Fabric端,新生的模组加载器,但是部分大型模组的支持似乎不太好,只推荐开小型模组服务器,不推荐开大型模组服务器。(交流群内出现过很多次Fabric服务端产生的诸多问题)。
### 不推荐的端
* Quilt端,基于Fabric的一款模组加载器,使用的人似乎不多,加上Fabric端的已有问题,不推荐。
## 代理端
::: tip 提醒
以下端为代理端,用于架设 ==群组服务端== ,如您没有这个需求,那么,就别看了。
:::
### 推荐的端
* \==Velocity端==,基于Bungeecord,并进行优化。
* \==Lightfall端== ,对于Forge进行了优化。
* Waterfall端,就是停更了。
### 其他端
* Bungeecord端,代理端老祖,由于代理端本身功能不多,!!用用也没事!!。
## 基岩版服务端
::: tip 提醒
以下端为基岩版Bedrock服务端,支持跨平台的那个MC版本。
:::
### 推荐的端
* BDS官方端,开服参照这里→ [基岩版开服教程](/docs/server/bedrock/)。
* BDS官方端+LiteLoader,官方端+外置插件加载器,开基岩版优先使用(如果版本支持)!
* 用Geyser转接,采用Java的特性。
### 不推荐的端
* Nukkit端,支持插件,但是丢失了很多原版特性。
---
---
url: /docs/server/docker/index.md
---
# Docker部署服务端
## 功能介绍
Docker为虚拟化容器,可以将服务端 ==运行在完全隔离宿主机== 的沙盒环境下,可以保护宿主机不受入侵。比较适合用于 ==分发== 资源,也自带限制CPU/内存/网络/磁盘资源的功能。MSLX 自`v1.5.0` 版本起支持此功能。
使用条件:==需要自行在宿主机安装Docker环境==。(Linux直接软件包管理器装,Windows/macOS需要安装Docker Desktop)。
::: tip Docker在 ==Linux== 上使用是最好的,如果在Windows/macOS上使用,性能损耗可能会比Linux上高(特别是磁盘性能)。
:::
## 创建一个Docker环境下的服务端
目前:`快速模式`、`整合包模式`、`自定义模式` 已完成对Docker服务端创建的支持。基岩版和MCDR还在开发中。(其实也能用,看会不会调了)。
在选择Java的阶段,直接选择 ==Docker容器环境== 。然后选择合适的Java版本即可。
就是这么简单,无需关心镜像那些内容,MSLX全程为您自动处理。

::: tip 关于内置运行时镜像
内置的官方运行时镜像为MSLX自行打包的Java运行时镜像,下载源位于中国大陆,拉取速度也很快。
镜像源默认**内置**了:==当前选择的Java版本运行环境+Python3+MCDR+基岩版所需运行环境。==
:::
接着,在 ==资源配置== 中填写端口配置。
不会填?你开服想用哪些端口,就左右填一样的就好,如:(这里示例使用25565和25566)

然后一直下一步就可以了,MSLX会自动处理那一堆东西。
::: warning 关于NeoForge/Forge安装
如果您在Windows/macOS环境下使用了Docker,并且正在创建需要安装NeoForge/Forge的服务端。安装时间可能会比宿主机安装 ==慢很多很多=={.warning} (因为磁盘挂载的问题),这是正常现象,请耐心等待。(比如1分钟变10分钟都是很正常的~)。
:::
## 调整Docker容器配置
### 对未启用Docker的服务端启用Docker托管
进入 ==「实例设置」== ,调整 ==运行方式== 。(如果是MC服务端,建议选择内置运行时,内置运行时就像选择Java一样选择一个版本即可。自定义的话需要自行指定容器镜像和完整的启动指令)。


### 调整高级设置
\==除非你知道你在干什么,否则不要乱改哦==。
高级设置大部分都仅适用于分发资源的情况(你自己用就没必要限制资源叭qwq)。
此部分不做过多解释,面板内说明已经比较完善,若不理解可以查阅相关Docker文档/请教AI。

## MSLX已运行在Docker下,如何再部署Docker服务端实例?
对于MSLX本身就安装在Docker的情况下,自`V1.5.1`版本起也做了相应的支持。
采用的模式为:`Docker Out Of Docker`,即创建的容器会在和MSLX的Docker为同一层,不是嵌套的关系(嵌套的性能损耗较大,尤其磁盘资源)。
### 前置条件
必须在MSLX运行的容器中 ==挂载了宿主机Docker的套接字== 才能运行,否则会报错哦!
只需要映射以下文件即可:
```shell
- /var/run/docker.sock:/var/run/docker.sock
```
如果你不知道改哪里,可以前往查看Docker安装文档,里面的配置文件均包含此项配置。
[在 Docker 中部署 MSLX](/docs/install/docker/){.readmore}
配置后,即可正常在MSLX中部署Docker服务端实例了。
### 挂载额外数据目录
如果您的服务端文件不在MSLX的默认数据目录,需要挂载的话,请保证 ==文件夹路径与挂载进Docker的路径一致==。
例如我的数据文件在`/game`,那么需要这样挂载:`/game:/game`。否则将无法在Docker容器中正常启动!
::: warning 挂载只能填写绝对路径,**请勿填写相对路径**,否则也会无法启动!!!(`./`开头的即为相对路径)。
:::
---
---
url: /docs/server/java/index.md
---
# Java版开服教程
## 视频教程
@[bilibili](BV13NkWBxEwg)
## 文本教程
使用 ==快速模式== ,根据引导创建服务端即可......
!!没啥好说的,要说的都在页面上提示了qwq!!

---
---
url: /docs/server/package/index.md
---
# 服务器导入整合包教程
::: steps
1. ## 下载服务端整合包
首先,先确保你要导入整合包的类型为 ==服务端== (带有server或服务端字样)。
就像这样,这里的才是 ==服务端整合包== :

2. ## 导入服务端整合包
来到MSLX的 ==创建服务端== 页面,选择 ==导入整合包== 模式,填写名称和路径后,选择刚才下载的服务端文件。

3. ## 选择核心
上传成功后,进入 ==核心选择== 页面,正常情况下都会能检测到核心,如果没检测到,可以在核心库 ==选择和你整合包一样的模组加载器和版本== 即可。

4. ## 选择Java
Java也是按照提示选择即可。

5. ## 提交创建
提交创建,MSLX会自动完成整合包解压,Java环境部署,NeoForge安装等流程,稍等即可。

6. ## 部署完成
部署成功即可去开服啦!

::::
::: warning
注意:部分整合包作者比较贴心,分为server和java这俩文件夹,此时你需要自己解压并且把server文件夹的东西压缩,然后才能导入。
:::
---
---
url: /docs/style/webpanel/index.md
---
# 网页控制台主题设置
::: tip 支持情况
MSLX 网页控制台自 ==v0.3.0-alpha== 版本起支持自定义一些主题配置。
\==注意:使用自定义主题会在一定程度上影响文本的可阅读性,请酌情开启==
!!好看就行,管他呢!!!
:::

## 基础主题配置
::: important 配置不共享
在此面板下的任何配置调整都是仅适用于 ==当前浏览器=={.important} 。
当您更换了设备/浏览器,或者清空了浏览器的本地存储,这些都会被 ==重置=={.important} 。
:::
点击网页控制台右上角的设置图标,会进入基础主题配置的弹窗。
可以对:==主题模式== 、 ==主题色== 、 ==导航布局== 进行配置。(配置这三项一般不会影响文本的可阅读性)
::: tip 导航布局
第一个导航布局是经典侧边栏布局,第二个则是顶部菜单布局。
由于菜单项目较多,在PC端的顶部菜单布局下部分菜单项会被折叠成 ==更多== 菜单项。
这里建议PC端使用侧边栏布局,手机端可以切换到顶部菜单布局。!!当然,一切都是你喜欢就好啦~!!
:::

## 终端日志染色等级配置
::: tip 从MSLX Webpanel v1.1.3 版本起,新增对日志染色等级调整的功能
:::
以下为预览效果,可根据个人喜好进行选择,系统默认选择 v1.1.3 版本新增的 ==简约染色== 。
### 不染色
基本上是全黑/全白。原始返回。

### 简约染色
这是新版本的默认模式,比较耐看吧。

### 增强染色
这是老版本 (v1.1.2以及之前的版本)的默认染色模式,染色更丰富。

## 日志原彩显示功能
::: tip 在MSLX ==v1.1.7== 版本,我们新增了 ==日志原彩显示== 功能,可以在控制台上展现日志的原有颜色。此功能可以,也建议和下述的简约染色搭配使用。
:::
以下为预览效果,可根据个人喜好进行选择,系统默认选择 v1.1.3 版本新增的 ==简约染色== 且开启日志原彩显示 。
### 日志原彩 & 简约染色
混合日志的原本色彩配合MSLX进行额外的颜色渲染。

### 日志原彩 & 不染色
仅显示日志原本的色彩。

### 简约染色 & 不开启日志原彩
此模式下为仅使用MSLX给日志染色。

## 自定义背景图 (进阶配置)
再次说明:开启后,在对比默认主题下, ==文本可阅读性确实会降低== !!我不管!我不管!!!
::: important 配置共享
在以下配置的自定义设置均会被保存到 ==MSLX守护进程=={.important} 端的设置中。
是会 ==多端共享=={.important} 的。
:::
### 配置方法
首先,为了启用自定义背景,您需要在上方说到的配置面板中打开 ==开启背景美化== 。此时,默认背景将会加载。
然后从菜单栏进入 ==设置== 页面,即可开始配置您的主题。
如图,我们提供了以下的配置项(暗黑模式和明亮模式的配置均是分离的):

#### 1. 自定义背景
背景的设置支持填写 ==在线的资源地址== (如:`https://www.mslmc.cn/logo.png`)
也支持 ==本地上传== ,只需要添加填空框框的最右侧的上传按钮即可上传文件作为您的背景图。(图片文件大小不能大于 10 MB)
小建议:可以选择一些比较符合当前主题色调的图,不然真的很难阅读。!!无视风险,强制开启!!!
::: tip 实时预览
配置的项目在修改后是可以立即预览到效果的。
但是如果你调整的参数模式和您现在处在的模式不一样,您需要在上面所说的面板中调整到 ==目标模式== 才能预览到哦。
调到满意的效果再保存哦~
:::
#### 2. 透明度调整
透明度调整支持调整背景图片本身的透明度。
其中,背景的透明度:==数字越小,背景越不透明==。而组件透明度是:==数字越大,组件越不透明==。
!!听不懂这句话的意思吗?其实你拉一下调整一下就明白了,因为是实时调整的。!!
#### 3. 终端毛玻璃强度
由于设置页面和终端不在一个页面,所以 ==没办法做到实时预览== 。
这个参数设置的是终端的模糊程度(有些时候模糊一些可以提升文本的可阅读性)。
上图:==(毛玻璃强度 0 vs 毛玻璃强度 15)==


可以根据自己的喜好调整到合适自己的参数即可。
注意:这个强度并不是百分比,只能设置0-50。!!学过css的都知道,这里的单位其实是px。!!
### 上传图片的保存位置
在这里:`MSLX数据目录\DaemonData\Public\Images`
MSLX数据目录一般都在守护进程端同一文件夹。
::: important 一些你需要知道的事情
* 当你嫌弃了你上一张背景图,重新上传了一张背景图后,以前这张图我们不会自动删除它,您需要自行去文件夹删除,或者,就留着吧。
* 如果您的面板暴露在了公网上,您需要知道,在这个文件夹里面的图片都能 ==无权限== 被公网访问。!!所以,不要在这个文件夹放一些奇怪的东西哦!!
:::
## 还是不满足?
!!你可真是个小馋猫啊!!
\==留给你的只有一条路,那就是魔改前端代码的道路。==
前端项目在 `MSLX.Webpanel`内,需要环境`Node.JS 22 +` 。
!!如果你看不懂上面的话,那放弃吧~!!
若你选择魔改前端,你会享受到 ==魔法对轰之 — CSS 大作战==。
目前,自定义背景图的实现均在`MSLX.Webpanel/src/layouts/index.vue`内,已经 ==魔法对轰== 了很多内容了。
---
---
url: /eula/index.md
---
# Minecraft Server Launcher X 用户使用协议
2025/12/06 更新
欢迎使用**MSLTeam**(以下简称“开发者”)提供的 **Minecraft Server Launcher X**(以下简称“本软件”)软件与服务。 为了保障**用户**(或称“您”)的权益,特制定本**用户使用协议书**(以下简称“本协议”)。 请您在使用本软件前,详细阅读本协议的所有内容。开发者可能随时更新本协议,修改后的本协议一旦在页面上公布即有效代替原用户协议书。
请您仔细阅读以下内容,当您使用本软件时,即代表您已经详细阅读并同意本协议的全部内容,且**同意遵守**本协议的规定。
## 使用须知
1. 用户应自行配备**本软件**和本软件**功能**(包括但不限于开启Minecraft服务器、内网桥接联机等)所需要的硬件和软件配置。
2. 用户应自行负担连接互联网后所需支付的相关电话、宽带使用等费用。
3. 用户应为其使用本软件产生的行为、事件、结果承担法律责任。
4. 用户与其他未授权的非官方个人之间产生的任何交易与纠纷,与开发者无关。
5. 用户应遵守中华人民共和国相关法律法规(如果用户是中华人民共和国境外的使用者,还应遵守所属国家或地区的法律法规)。
6. 用户**不得**使用本软件(或本软件的一些特性功能)从事非法行为,**不得**使用与本软件有关联的相关进程和服务(包括但不限于Minecraft服务器、使用本软件功能的Minecraft游戏等)从事非法行为,其任何行为造成的后果,与开发者无关。
7. 用户应当自行承担其所发布的信息内容所涉及的法律责任。用户**不得**在本软件内、本软件运行的相关进程与服务(包括但不限于Minecraft服务器、使用本软件功能的Minecraft游戏等)内输入、发表和传播下列任何内容,**不得**以任何形式发布下列任何内容:
1. 反对中华人民共和国宪法所确定的基本原则的;
2. 危害国家安全,泄露国家机密,颠覆国家政权,破坏国家统一的;
3. 损害国家荣誉和利益的;
4. 煽动民族仇恨、民族歧视,破坏民族团结的;
5. 破坏国家宗教政策,宣扬邪教和封建迷信的;
6. 散布谣言,扰乱社会秩序,破坏社会稳定的;
7. 散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;
8. 侮辱或者诽谤他人,侵害他人合法权益的;
9. 含有中华人民共和国法律、行政法规禁止的其他内容的。
8. 除非法律允许或开发者书面许可,用户不得从事下列任何行为:
1. 不合法、不恰当地使用本软件及服务;
2. 破坏本软件系统或网站的正常运行,故意传播计算机病毒等破坏性程序;
3. 采取任何可能影响本软件网络服务的非正常使用行为(包括但不限于损害、攻击服务器或使服务器过度负荷等);
4. 删除本软件及其副本上关于著作权的信息。
9. 若用户做出违法违规或违反本协议规定的行为,开发者有权视情节严重程度,依据本协议及法律法规,对您做出包括但不限于终止服务等处理措施;情节严重的,开发者将移交有关行政管理机关给予行政处罚,或者追究您的刑事责任。
## 数据收集与使用
若您同意本使用协议且使用本软件的**在线服务**,我们会收集以下信息:
1. 本软件所运行设备的IP地址(可能并非正确地址);
2. 本软件所运行设备的部分系统信息;
3. 软件崩溃时,可能会在经用户同意的情况下,上传软件在系统运行的日志(含有部分系统信息),以帮助解决问题和改善软件;
4. 其他会在经用户同意情况下上传的部分信息(软件中会具体说明)。
## 用户支持和反馈
用户在使用过程中如遇到任何问题,可以通过电子邮件或在软件源码仓库提交issue的方式进行反馈。开发者会认真考虑用户的反馈以改进服务。
## 服务的变更或中止
1. 对用户服务的中止与终止:
1. 用户有发布违法信息、严重违背社会公德、以及其他违反法律禁止性规定的行为,开发者应终止对用户提供服务;
2. 用户在接受本软件服务时实施不正当行为的,开发者有权终止对用户提供服务(该不正当行为的具体情形在本协议中有明确约定);
3. 用户使用本软件的第三方修改版本的,用户应自行承担风险与法律责任。
2. 对本软件及服务的中断、中止与终止:
1. 发生下列情形之一时,开发者有权终止或中断本软件全部或部分服务,对因此造成的不便与损害,开发者对用户或第三人均不承担任何责任:
a. 因本软件及服务自身的需要;
b. 因服务器遭受损害、无法正常工作;
c. 因突发性的软硬件设备与电子通信设备故障;
d. 因网络提供商线路或其他故障;
e. 因政策因素;
f. 第三方原因或其他不可抗力的情形。
2. 开发者保留在其认为有必要的情况下终止或部分终止本软件及服务的权利,开发者可以采取公告的形式通知用户,但开发者不承担对用户造成的任何损失。
## 免责声明
1. 用户理解并同意,在法律许可范围内,开发者不对本软件提供任何保证。 用户使用本软件所造成的的风险均由用户自行承担。
2. 用户理解并同意,开发者不保证本软件及服务一定能满足用户需求,也不保证服务不会被中断,并且对本软件及服务的正确性、安全性等方面不提供任何担保。
3. 用户理解并同意,开发者无法完全保证本软件**在线服务**所下载的第三方文件的的正确性、安全性、合法性,也不对本软件内存在的**第三方服务**(包括但不限于内网映射、文件下载源/API等服务)的正确性、安全性、合法性等负责。因此,前面提到的内容与开发者和本软件无关,不代表开发者及本软件的立场。相关争议应由第三方服务提供方承担。
4. 用户理解并同意,若以错误方式、非通过本软件的手段使用本软件在线服务以及本软件所下载的相关文件,其造成的后果由用户自行承担,若导致财产损毁、版权或知识产权被侵犯等问题,开发者概不负责,不会也不能承担任何法律责任。
5. 用户理解并同意,本软件不对**第三方服务**内容提供担保。 若用户使用第三方服务导致财产损毁、版权或知识产权被侵犯等问题,开发者概不负责,不会也不能承担任何法律责任。
6. 用户理解并同意,开发者对**本软件功能**(包括但不限于开启Minecraft服务器、内网桥接联机等)不提供任何保证和法律支持,若用户使用本软件功能从事违法犯罪或其他不正当的行为,所造成的风险和法律后果均由用户自行承担。
## 知识产权
1. 本软件著作权、专利权及其他知识产权,均为开发者或者指定版权方所有。
2. 本软件所使用的第三方服务归相关版权方所有,包括但不限于:
1. 本软件为沙盒游戏**Minecraft**(其最终解释权归Microsoft公司和Mojang AB,即Mojang Studio工作室所有)的服务器管理和游戏联机工具。用户应当遵守**Minecraft最终用户许可协议**(MinecraftEULA)和中国区代理公司网易在中国大陆实行的相关政策,不得将游戏本体内容用于商业用途,或实施其他被**Minecraft最终用户许可协议**所禁止的行为。
2. 本软件提供的部分在线文件资源(服务端核心、游戏/服务器模组和插件等内容)下载服务由相应官方/第三方下载源、CurseForge等第三方平台提供,版权依照第三方平台规定处理。
3. 本软件使用的其他第三方服务,版权归服务提供商所有。
3. 本软件是开源软件,用户或其他非本软件的软件开发者应当遵守本软件的开源协议。
4. 用户理解并同意,除第三方资源外,本软件提供的所有服务器上的数据均归开发者所有。开发者有权决定保留或不保留服务器上的全部或部分数据。
## 条款变更
开发者**有权**在必要的时候修改本协议。本协议一旦发生变动,开发者将在重要页面展示修改内容,敬请定期查询。若用户不同意本协议的修订或更新,用户可以主动停止使用本软件及服务。 若用户在本协议修订后仍继续使用本软件及服务,即表示用户同意本协议所做的所有修订或更新。 若用户在本协议修订后因未熟悉变更而引起的损失,开发者不承担任何责任。
## 其他规定
1. 本协议适用于中华人民共和国法律,并且排除一切冲突法规规定地适用;
2. 开发者不行使、未能及时行使或者充分行使本协议或者依照法律规定所享有的权利,不应被视为放弃行使该权利,也不得影响开发者在将来行使该等权利;
3. 在法律许可范围内,开发者享有对本协议条款的解释权;
4. 用户可以通过电子邮件投诉、举报各类违法违规行为,邮件请发送至邮箱`2035582067@qq.com`。
## 条款可分性
如果本协议的任何条款被认定为无效或不可执行,其余条款仍应完全有效。
---
---
url: /msl-changelogs/index.md
---
# Minecraft Server Launcher X 更新日志
---
---
url: /plugin-dev/backend/api/index.md
---
# SDK 完整接口与核心服务
::: warning v1.7.0 核心接口重大变更通知
原控制服务上帝接口 `IMCServerService` 已被正式废弃(标记为 `[Obsolete]`),并计划于 **v1.8.0** 彻底移除。
为彻底解决上帝接口臃肿及命名不规范的问题,新版 SDK 已将其拆分为三个高度内聚的新接口:
* **`IInstanceLifecycleService`**:负责实例生命周期(启/停/杀/查状态/EULA)。
* **`IInstanceConsoleService`**:负责实例终端交互(发送指令/PTY控制/获取日志)。
* **`IInstanceBackupService`**:负责实例备份触发。
推荐所有新开发插件直接注入新接口,现有插件亦请尽快完成迁移适配!
:::
## 概述
`MSLX.SDK` 为后端插件提供了操作宿主数据与底层控制的核心接口。可以通过静态对象 `SDK.MSLX`(包含 `Config`配置、`Downloader`下载器、`Http`请求工具、`Logger`日志工具)直接调用,也可以通过依赖注入(DI)在插件的服务或 Controller 中注入 `MSLX.SDK.IServices` 下的核心服务。
## 静态工具与 Bridge (`SDK.MSLX`)
静态入口 `SDK.MSLX` 整合了宿主的数据 Bridge、下载管理器、网络请求与日志模块:
```c#
SDK.MSLX.Config // 配置 Bridge 集合
SDK.MSLX.Downloader // 下载器服务
SDK.MSLX.Http // 网络请求工具
SDK.MSLX.Logger // 统一日志输出
```
### 1. 配置 Bridge 集合 (`SDK.MSLX.Config`)
`SDK.MSLX.Config` 提供了对宿主核心数据文件(`ServerList.json`, `FrpList.json`, `TaskList.json`, `UserList.json`, `Config.json`)及插件自身独立配置的安全读写能力。
#### 1.1 服务端实例 Bridge (`Config.Servers`)
用于查询、新建、更新和删除 Minecraft 服务端实例配置。
```c#
using MSLX.SDK;
// 获取所有服务端实例
List servers = SDK.MSLX.Config.Servers.GetServerList();
// 获取指定 ID 的服务端实例
McServerInfo.ServerInfo? server = SDK.MSLX.Config.Servers.GetServer(1001);
// 生成一个全新的唯一下标 ID
uint newId = SDK.MSLX.Config.Servers.GenerateServerId();
// 新建服务端实例
bool created = SDK.MSLX.Config.Servers.CreateServer(newServerInfo);
// 更新服务端实例
bool updated = SDK.MSLX.Config.Servers.UpdateServer(serverInfo);
// 删除服务端实例 (可选是否同时删除本地硬盘文件)
bool deleted = SDK.MSLX.Config.Servers.DeleteServer(serverId: 1001, deleteFiles: false);
```
#### 1.2 FRP 隧道 Bridge (`Config.Frp`)
用于读取和配置宿主的 FRP 穿透隧道。
```c#
// 获取所有 FRP 配置
List frpList = SDK.MSLX.Config.Frp.GetFrpList();
// 获取特定 FRP 配置对象
JObject? frpConfig = SDK.MSLX.Config.Frp.GetFrpConfig(1);
// 校验 FRP ID 是否有效
bool isValid = SDK.MSLX.Config.Frp.IsFrpIdValid(1);
// 生成新的 FRP 配置 ID
int newFrpId = SDK.MSLX.Config.Frp.GenerateFrpId();
// 创建 FRP 配置
bool created = SDK.MSLX.Config.Frp.CreateFrpConfig(
name: "插件隧道",
server: "frp.example.com:7000",
configType: "ini",
config: "[web]\ntype = http..."
);
// 更新与删除
SDK.MSLX.Config.Frp.UpdateFrpConfig(id: 1, name: "新名称", server: "frp2.example.com", configType: "toml");
SDK.MSLX.Config.Frp.DeleteFrpConfig(id: 1);
```
#### 1.3 计划任务 Bridge (`Config.Tasks`)
控制宿主内置的定时计划任务。
```c#
// 获取全部计划任务
List tasks = SDK.MSLX.Config.Tasks.GetTaskList();
// 获取指定实例关联的计划任务
List instanceTasks = SDK.MSLX.Config.Tasks.GetTasksByInstanceId(1001);
// 创建 / 更新 / 删除计划任务
SDK.MSLX.Config.Tasks.CreateTask(newTask);
SDK.MSLX.Config.Tasks.UpdateTask(updatedTask);
SDK.MSLX.Config.Tasks.DeleteTask(taskId);
// 更新计划任务上次执行时间
SDK.MSLX.Config.Tasks.UpdateLastRunTime(taskId, DateTime.Now);
```
#### 1.4 用户与鉴权 Bridge (`Config.Users`)
用于访问宿主面板的用户数据、校验密码及操作 OpenID/资源权限。
```c#
// 校验用户名密码
bool isValidUser = SDK.MSLX.Config.Users.ValidateUser("admin", "rawPassword");
// 查询用户
UserInfo? userByName = SDK.MSLX.Config.Users.GetUserByUsername("admin");
UserInfo? userById = SDK.MSLX.Config.Users.GetUserById("user_id_xxx");
UserInfo? userByApiKey = SDK.MSLX.Config.Users.GetUserByApiKey("api_key_xxx");
UserInfo? userByOpenId = SDK.MSLX.Config.Users.GetUserByOpenId("openid_xxx");
// 用户 OpenID 绑定与解绑
SDK.MSLX.Config.Users.BindUserOpenId(userId: "user_id_xxx", openId: "openid_xxx");
SDK.MSLX.Config.Users.UnbindUserOpenId(userId: "user_id_xxx");
// 校验用户对特定资源(如服务端实例)的访问权限
bool hasAccess = SDK.MSLX.Config.Users.HasResourcePermission(userId, type: "instance", id: 1001);
```
#### 1.5 宿主主配置 Bridge (`Config.Main`)
操作宿主的 `Config.json` 全局主配置。
```c#
JObject mainConfig = SDK.MSLX.Config.Main.ReadConfig();
JToken? portToken = SDK.MSLX.Config.Main.ReadConfigKey("Port");
SDK.MSLX.Config.Main.WriteConfigKey("CustomField", "value");
```
#### 1.6 插件独立配置控制 (`Config.GetPluginConfig`)
```c#
// 获取指定插件 ID 的独立配置 Bridge
var pluginConfigBridge = SDK.MSLX.Config.GetPluginConfig("mslx-plugin-demo");
JObject configJson = pluginConfigBridge.ReadConfig();
pluginConfigBridge.WriteConfigKey("EnableAutoUpdate", true);
```
#### 1.7 路径与 JSON 文件助手
```c#
string appDataPath = SDK.MSLX.Config.GetAppDataPath(); // 面板 AppData 根目录
string appConfigPath = SDK.MSLX.Config.GetAppConfigPath(); // Config.json 路径
// 通用 JSON 加载与保存
JObject json = SDK.MSLX.Config.LoadJson(filePath);
SDK.MSLX.Config.SaveJson(filePath, json);
```
***
### 2. 下载器服务 (`SDK.MSLX.Downloader`)
底层映射宿主的并行下载管理器,支持带进度回调与实时下载速度通知。
```c#
using MSLX.SDK;
string targetPath = Path.Combine(this.Config().GetDataPath(), "server.jar");
var result = await SDK.MSLX.Downloader.DownloadFileAsync(
url: "https://example.com/server.jar",
savePath: targetPath,
onProgress: (progressPercent, speedText) =>
{
SDK.MSLX.Logger.Debug($"下载进度: {progressPercent:0.0}% [{speedText}]");
},
progressIntervalMs: 1000 // 进度通知频率 (毫秒)
);
if (result.Success)
{
SDK.MSLX.Logger.Info("文件下载成功!");
}
else
{
SDK.MSLX.Logger.Error($"下载失败: {result.ErrorMessage}");
}
```
***
### 3. HTTP 请求工具 (`SDK.MSLX.Http`)
宿主内置的轻量 HTTP 客户端,支持 GET / POST 请求及多种 ContentType。
#### 方法与类型定义
```c#
public enum PluginHttpContentType { Json, FormUrlEncoded, Text, Octet }
public class PluginHttpResponse
{
public string? Content { get; set; }
public int StatusCode { get; set; }
public Dictionary Headers { get; set; }
public Dictionary Cookies { get; set; }
public bool IsSuccessStatusCode { get; set; }
public Exception? ResponseException { get; set; }
}
```
#### 调用示例
```c#
// 1. GET 请求示例
PluginHttpResponse getRes = await SDK.MSLX.Http.GetAsync(
url: "https://api.example.com/data",
queryParameters: new Dictionary { { "key", "value" } },
headers: new Dictionary { { "User-Agent", "MSLX-Plugin" } },
timeout: TimeSpan.FromSeconds(10)
);
if (getRes.IsSuccessStatusCode)
{
string responseContent = getRes.Content ?? "";
}
// 2. POST 请求示例 (JSON 格式)
PluginHttpResponse postRes = await SDK.MSLX.Http.PostAsync(
url: "https://api.example.com/action",
contentType: PluginHttpContentType.Json,
data: new { action = "start", serverId = 1001 },
headers: null,
timeout: TimeSpan.FromSeconds(15)
);
```
***
### 4. 统一日志输出 (`SDK.MSLX.Logger`)
用于向面板后台日志与文件输出统一格式的日志。
```c#
SDK.MSLX.Logger.Info("插件初始化成功");
SDK.MSLX.Logger.Warn("配置项未设置,使用默认值");
SDK.MSLX.Logger.Debug("调试追踪数据: count=5");
try
{
// ...
}
catch (Exception ex)
{
SDK.MSLX.Logger.Error("操作发生异常", ex);
}
```
***
## 依赖注入核心服务 (`MSLX.SDK.IServices`)
宿主会将管理进程中的底层控制服务注册到依赖注入容器中。插件可以在 Controller、Hub 或自定义服务中通过**构造函数注入**直接使用。
### 1. 实例控制与交互服务 (`IInstanceLifecycleService` / `IInstanceConsoleService`)
旧版 `IMCServerService` 已废弃,现已拆分为职责更加单一的生命周期控制、终端交互与备份服务。
```c#
using MSLX.SDK.IServices;
public class MyPluginController : ControllerBase
{
private readonly IInstanceLifecycleService _lifecycle;
private readonly IInstanceConsoleService _console;
public MyPluginController(IInstanceLifecycleService lifecycle, IInstanceConsoleService console)
{
_lifecycle = lifecycle;
_console = console;
}
[HttpPost("start/{instanceId}")]
public IActionResult StartInstance(uint instanceId)
{
// 检查实例是否正在运行
if (_lifecycle.IsServerRunning(instanceId))
{
return Ok("实例已在运行中");
}
// 启动服务器 (非阻塞)
var (success, message) = _lifecycle.StartServer(instanceId, isAutoRestart: false, skipEulaCheck: true);
return Ok(new { success, message });
}
[HttpPost("command/{instanceId}")]
public IActionResult SendCmd(uint instanceId, [FromBody] string cmd)
{
// 向服务器控制台发送指令
bool sent = _console.SendCommand(instanceId, cmd, repeatCommandToLog: true);
return Ok(new { success = sent });
}
[HttpGet("logs/{instanceId}")]
public IActionResult GetLogs(uint instanceId)
{
// 获取实时日志与在线玩家
List logs = _console.GetLogs(instanceId);
List players = _lifecycle.GetOnlinePlayers(instanceId);
TimeSpan uptime = _lifecycle.GetServerUptime(instanceId);
return Ok(new { logs, players, uptimeSeconds = uptime.TotalSeconds });
}
}
```
#### 常用实例服务方法速查表
| 方法签名 | 说明 |
| :--- | :--- |
| `IsServerRunning(uint instanceId)` | 检查指定实例是否在运行 |
| `GetServerStatus(uint instanceId)` | 获取详细状态 (0:未启动, 1:启动中, 2:运行中, 3:停止中, 4:重启中) |
| `StartServer(uint instanceId, bool isAutoRestart, bool skipEulaCheck)` | 启动服务端 (非阻塞) |
| `StopServer(uint instanceId)` | 安全停止服务端 |
| `ForceKillServer(uint instanceId)` | 强制杀死服务端进程 |
| `RestartServer(uint instanceId)` | 异步重启服务端 |
| `SendCommand(uint instanceId, string command, bool repeatCommandToLog)` | 发送控制台指令 |
| `GetLogs(uint instanceId)` | 读取当前服务器控制台输出日志 |
| `GetOnlinePlayers(uint instanceId)` | 获取在线玩家列表 |
| `GetServerUptime(uint instanceId)` | 获取已运行时长 `TimeSpan` |
| `AgreeEULA(uint instanceId, bool agree)` | 自动签署 EULA 协议 |
### 2. FRP 进程控制服务 (`IFrpProcessService`)
用于控制宿主内 FRP 进程的独立拉起与日志获取。
```c#
using MSLX.SDK.IServices;
public class FrpControlService
{
private readonly IFrpProcessService _frpService;
public FrpControlService(IFrpProcessService frpService)
{
_frpService = frpService;
}
public void ToggleFrp(int frpId)
{
if (_frpService.IsFrpRunning(frpId))
{
_frpService.StopFrp(frpId);
}
else
{
var (success, msg) = _frpService.StartFrp(frpId);
List logs = _frpService.GetLogs(frpId);
}
}
}
```
### 3. 环境扫描服务 (`IJavaScannerService` / `IPythonScannerService`)
获取宿主系统中安装的 Java 环境或 Python/MCDReforged 环境。
```c#
using MSLX.SDK.IServices;
public async Task CheckEnvironments(IJavaScannerService javaService, IPythonScannerService pythonService)
{
// 扫描系统中的 Java
List javaList = await javaService.ScanJavaAsync(forceRefresh: false);
// 扫描系统中的 Python (及检测是否安装 MCDR)
List pythonList = await pythonService.ScanPythonAsync(forceRefresh: false);
// 校验特定 Python 路径
PythonInfo? inspectRes = await pythonService.InspectPythonAsync("python3");
}
```
***
## 更多资源
完整源码接口定义见:
* [MSLX.SDK.Interfaces](https://github.com/MSLTeam/MSLX/tree/dev/MSLX.SDK/Interfaces){.readmore}
* [MSLX.SDK.IServices](https://github.com/MSLTeam/MSLX/tree/dev/MSLX.SDK/IServices){.readmore}
---
---
url: /plugin-dev/backend/configdata/index.md
---
# 插件配置 & 数据目录
## 概述
MSLX SDK为插件的数据存储提供了一套方便使用的方法进行简单的配置文件读写。也提供了方法直接获取当前插件的数据存储目录。
如无其他必要,请不要随意在其他位置进行数据的存储。
示例插件有一些示例:[mslx-plugin-demo/MSLXPluginEntry.cs at main · MSLTeam/mslx-plugin-demo](https://github.com/MSLTeam/mslx-plugin-demo/blob/main/MSLXPluginEntry.cs)
调用相关功能均需要引用SDK命名空间,下文不再赘述。
```c#
using MSLX.SDK;
```
## 插件入口类暴露全局实例
在您的插件主类(实现 `IPlugin` 的类)中,新增一个公开的静态属性 `Instance`,并在插件的 `OnLoad` 生命周期中将当前实例(`this`)挂载给它。
```c#
public static MSLXPluginEntry Instance { get; private set; }
```
```c#
public void OnLoad()
{
Instance = this;
}
```
完整实例请查看:[MSLXPluginEntry.cs](https://github.com/MSLTeam/mslx-plugin-demo/blob/main/MSLXPluginEntry.cs)
::: important 以下文档均以主类为`MSLXPluginEntry`,静态属性为`Instance`作为示例。若您挂在的位置/名字不同,请自行同步更改即可。
:::
## 获取插件的数据目录
插件的所有数据均应该存储在此目录下,并且建议使用`Path.Combine();`函数进行拼接路径。
```c#
MSLXPluginEntry.Instance.Config().GetDataPath();
```
## 简易读写插件配置文件
快速读取写入键值。
```c#
MSLXPluginEntry.Instance.Config().WriteConfigKey("author", "xiaoyu");
MSLXPluginEntry.Instance.Config().WriteConfigKey("magicNumber", 1027);
int count = (int?)MSLXPluginEntry.Instance.Config().ReadConfigKey("magicNumber") ?? 0;
```
## 完整读取配置文件
读取和写入配置的类型均为 [Newtonsoft.Json](https://www.nuget.org/packages/Newtonsoft.Json/) 的`JObject`类型。
```c#
var allConfig = MSLXPluginEntry.Instance.Config().ReadConfig();
MSLXPluginEntry.Instance.Config().WriteConfig(allConfig);
```
---
---
url: /plugin-dev/backend/events/index.md
---
# 事件系统与生命周期钩子
## 概述
从 MSLX v1.6.4 开始,SDK 引入了**全局事件总线(Event Hooks System)**。
插件可以通过静态入口 `SDK.MSLX.Events` 监听 Minecraft 服务端、备份系统、计划任务、内网穿透(FRP 隧道)以及宿主守护进程的核心生命周期。无需侵入修改宿主代码,即可实现诸如**分层灾备归档、群服聊天互通、自动崩溃告警、敏感指令拦截、隧道状态与日志流监控**等高级功能。
### 零心智负担的防泄漏机制
由于 MSLX 插件运行在独立的 `AssemblyLoadContext` 中,传统 C# 事件监听若在卸载时未注销易导致内存泄漏与无法卸载。\
**在 MSLX 中,宿主插件管理器会在插件卸载时自动剔除该插件注册的所有事件监听器**,开发者可放心在 `OnLoad()` 中订阅,无需担心生命周期悬挂问题。
```c#
using MSLX.SDK;
using MSLX.SDK.Events;
public class MyPlugin : IPlugin
{
public void OnLoad()
{
// 监听备份完成
SDK.MSLX.Events.OnBackupCompleted += (sender, e) =>
{
SDK.MSLX.Logger.Info($"[备份通知] 实例 {e.InstanceId} 备份完成: {e.BackupFileName}");
};
}
}
```
***
## 备份事件(Backup Events)
备份事件涵盖了从准备备份、打包完成、异常失败到备份删除的完整生命周期。
### 1. 事件列表与参数
| 事件名称 | 触发时机 | 参数类型 | 关键属性 |
| :--- | :--- | :--- | :--- |
| `OnBackupStarting` | 准备压缩存档前 | `BackupStartingEventArgs` | `InstanceId`, `ServerInfo`, `BackupDirectory`, `Cancel`, `CancelReason` |
| `OnBackupCompleted` | 备份 zip 写入完成 | `BackupCompletedEventArgs` | `InstanceId`, `ServerInfo`, `BackupFilePath`, `BackupFileName`, `FileSizeBytes`, `FormattedSize`, `Duration` |
| `OnBackupFailed` | 找不到世界或压缩异常 | `BackupFailedEventArgs` | `InstanceId`, `ServerInfo`, `ErrorMessage`, `Exception` |
| `OnBackupDeleted` | 备份文件被删除 | `BackupDeletedEventArgs` | `InstanceId`, `BackupFilePath`, `BackupFileName`, `IsAutoRoll` (是否滚动清理) |
::: tip 拦截备份
在 `OnBackupStarting` 中将 `e.Cancel = true;` 并附带 `e.CancelReason`,即可打断宿主原生备份流程,适合需要完全由插件接管自定义备份引擎的场景。
:::
### 2. 实战示例:编写 GFS 分层备份归档插件
很多服主希望实现 **GFS(Grandfather-Father-Son)分层保留策略**:即高频定时备份(如每小时一份)保留 24 小时,同时将每天的第一份备份提取为“日归档”保留 10 天,每月的第一份提取为“月归档”长期保存。
借助 `OnBackupCompleted` 钩子,仅需几十行代码即可实现一个功能完备的归档插件:
```c#
using System.IO.Compression;
using MSLX.SDK;
using MSLX.SDK.Events;
public class GfsArchivePlugin : IPlugin
{
public string Id => "mslx-plugin-gfs-archive";
public string Name => "GFS 分层归档插件";
public void OnLoad()
{
SDK.MSLX.Events.OnBackupCompleted += (sender, e) =>
{
// 在后台任务中执行,避免阻塞事件线程
Task.Run(async () =>
{
try
{
await ProcessGfsArchiveAsync(e);
}
catch (Exception ex)
{
SDK.MSLX.Logger.Error($"[GFS归档] 处理异常: {ex.Message}");
}
});
};
}
private async Task ProcessGfsArchiveAsync(BackupCompletedEventArgs e)
{
if (e.ServerInfo == null) return;
string archiveRootDir = Path.Combine(e.ServerInfo.Base, "mslx-archives");
string dailyDir = Path.Combine(archiveRootDir, "daily");
Directory.CreateDirectory(dailyDir);
// 判定是否是当天的第一份归档(检查今天是否已经提取过)
string todayTag = e.Timestamp.ToString("yyyyMMdd");
string dailyTarget = Path.Combine(dailyDir, $"daily-{todayTag}.zip");
if (!File.Exists(dailyTarget))
{
SDK.MSLX.Logger.Info($"[GFS归档] 提取实例 [{e.InstanceId}] 当日首个备份作为日归档: {e.BackupFileName}");
File.Copy(e.BackupFilePath, dailyTarget, overwrite: false);
// 清理超过 10 天的旧日归档
PruneOldArchives(dailyDir, keepDays: 10);
}
}
private void PruneOldArchives(string dirPath, int keepDays)
{
var dir = new DirectoryInfo(dirPath);
var cutoff = DateTime.Now.AddDays(-keepDays);
foreach (var file in dir.GetFiles("daily-*.zip"))
{
if (file.CreationTime < cutoff)
{
file.Delete();
SDK.MSLX.Logger.Info($"[GFS归档] 清理已过期日归档: {file.Name}");
}
}
}
}
```
***
## 服务器生命周期事件(Server Lifecycle Events)
涵盖服务端实例从准备启动、启动完成、准备停止到完全退出或崩溃的运行状态监控。
### 1. 事件列表与参数
| 事件名称 | 触发时机 | 参数类型 | 关键属性 |
| :--- | :--- | :--- | :--- |
| `OnServerStarting` | 点击启动或自动重启前 | `ServerStartingEventArgs` | `InstanceId`, `ServerInfo`, `IsAutoRestart`, `Cancel`, `CancelReason` |
| `OnServerStarted` | 进程成功创建并获得 PID | `ServerStartedEventArgs` | `InstanceId`, `ServerInfo`, `ProcessId`, `Timestamp` |
| `OnServerStopping` | 正在发送停止指令前 | `ServerStoppingEventArgs` | `InstanceId`, `ServerInfo`, `StopCommand`, `Timestamp` |
| `OnServerStopped` | 进程完全退出 | `ServerStoppedEventArgs` | `InstanceId`, `ServerInfo`, `ExitCode`, `Uptime` |
| `OnServerCrashed` | 进程异常非 0 退出 | `ServerCrashedEventArgs` | `InstanceId`, `ServerInfo`, `ExitCode`, `CrashMessage` |
### 2. 代码示例:启动校验与崩溃报警
```c#
public void OnLoad()
{
// 启动前校验(例如:禁止在特定时间段启动)
SDK.MSLX.Events.OnServerStarting += (sender, e) =>
{
if (DateTime.Now.Hour >= 2 && DateTime.Now.Hour < 6)
{
e.Cancel = true;
e.CancelReason = "凌晨 2:00 - 6:00 为系统维护窗口,禁止启动服务器";
}
};
// 监控崩溃并发送告警
SDK.MSLX.Events.OnServerCrashed += (sender, e) =>
{
SDK.MSLX.Logger.Error($"⚠️ 严重警告:实例 [{e.InstanceId}] 发生异常崩溃!退出码: {e.ExitCode}");
// 可在此处调用 Webhook 推送消息至 QQ群 / 钉钉 / 飞书 / Discord
};
}
```
***
## 控制台日志与指令事件(Console & Command Events)
### 1. 控制台日志监听 (`OnServerLogReceived`)
每当 Minecraft 服务端输出一行日志(包括标准输出流与 PTY 伪终端输出),都会触发此事件。
```c#
SDK.MSLX.Events.OnServerLogReceived += (sender, e) =>
{
// e.InstanceId 为产生日志的实例ID
// e.LogLine 为原始日志行
if (e.LogLine.Contains("Can't keep up!"))
{
SDK.MSLX.Logger.Warning($"实例 [{e.InstanceId}] 出现掉 tick 告警!");
}
// 监听聊天输出转发到机器人
if (e.LogLine.Contains("<") && e.LogLine.Contains(">"))
{
// 群服互通逻辑...
}
};
```
### 2. 控制台指令拦截 (`OnServerCommandExecuting`)
通过开服器发送命令(无论来自 WebPanel、计划任务还是 RCON)前触发,支持拦截。
```c#
SDK.MSLX.Events.OnServerCommandExecuting += (sender, e) =>
{
// 禁止在后台执行危险指令
if (e.Command.TrimStart().StartsWith("op ", StringComparison.OrdinalIgnoreCase))
{
SDK.MSLX.Logger.Warning($"已拦截对实例 [{e.InstanceId}] 执行的高危指令: {e.Command}");
e.Cancel = true; // 拦截并取消执行
}
};
```
***
## 计划任务事件(Task Events)
监听 MSLX 内部定时任务调度器的执行状态。
| 事件名称 | 触发时机 | 参数类型 | 关键属性 |
| :--- | :--- | :--- | :--- |
| `OnTaskExecuting` | 定时任务即将触发前 | `TaskExecutingEventArgs` | `TaskId`, `TaskName`, `TaskType`, `InstanceId`, `Cancel` |
| `OnTaskExecuted` | 定时任务触发完成 | `TaskExecutedEventArgs` | `TaskId`, `TaskName`, `TaskType`, `InstanceId`, `Success`, `ErrorMessage` |
```c#
SDK.MSLX.Events.OnTaskExecuting += (sender, e) =>
{
SDK.MSLX.Logger.Info($"[任务追踪] 任务 [{e.TaskName}] ({e.TaskType}) 即将执行于实例: {e.InstanceId}");
};
SDK.MSLX.Events.OnTaskExecuted += (sender, e) =>
{
if (!e.Success)
{
SDK.MSLX.Logger.Error($"[任务追踪] 任务 [{e.TaskName}] 执行失败: {e.ErrorMessage}");
}
};
```
***
## 内网穿透 / FRP 隧道事件(FRP Tunnel Events)
监听 MSLX 穿透服务中 FRP 隧道的生命周期状态及控制台日志流输出。
| 事件名称 | 触发时机 | 参数类型 | 关键属性 |
| :--- | :--- | :--- | :--- |
| `OnFrpStarting` | 隧道准备启动或后台下载核心前 | `FrpStartingEventArgs` | `TunnelId`, `TunnelName`, `Service`, `ConfigType`, `Config` |
| `OnFrpStarted` | Frpc 进程成功启动并获得 PID | `FrpStartedEventArgs` | `TunnelId`, `TunnelName`, `ProcessId`, `Timestamp` |
| `OnFrpStopping` | 隧道正在停止前 | `FrpStoppingEventArgs` | `TunnelId`, `TunnelName`, `Timestamp` |
| `OnFrpStopped` | Frpc 进程完全退出 | `FrpStoppedEventArgs` | `TunnelId`, `TunnelName`, `ExitCode`, `Timestamp` |
| `OnFrpLogReceived` | Frpc 控制台输出日志时 | `FrpLogEventArgs` | `TunnelId`, `LogLine`, `Timestamp` |
```c#
public void OnLoad()
{
// 监听隧道启动完成
SDK.MSLX.Events.OnFrpStarted += (sender, e) =>
{
SDK.MSLX.Logger.Info($"[FRP 监控] 隧道 [{e.TunnelName}] (ID: {e.TunnelId}) 启动就绪,PID: {e.ProcessId}");
};
// 监听隧道停止/异常退出
SDK.MSLX.Events.OnFrpStopped += (sender, e) =>
{
SDK.MSLX.Logger.Warning($"[FRP 监控] 隧道 [{e.TunnelName}] (ID: {e.TunnelId}) 已停止,退出码: {e.ExitCode}");
};
// 监听隧道控制台日志(可用于解析远程映射端口或错误排查)
SDK.MSLX.Events.OnFrpLogReceived += (sender, e) =>
{
if (e.LogLine.Contains("start proxy success"))
{
SDK.MSLX.Logger.Info($"[FRP 日志捕获] 隧道 [{e.TunnelId}] 代理映射建立成功!");
}
};
}
```
***
## 最佳实践与注意事项
1. **避免阻塞事件线程**:\
事件处理器是在宿主内部执行流中同步调用的。若需要进行耗时的网络请求(HTTP/Webhook)、磁盘 IO 拷贝或压缩,请务必使用 `Task.Run(async () => { ... })` 转移到后台线程执行。
2. **异常保护**:\
MSLX 事件总线内部已对每个监听委托做了异常隔离保护,单个插件抛出的未捕获异常不会波及宿主或其他插件,但仍建议在插件内部做好 `try-catch` 处理,并使用 `SDK.MSLX.Logger` 记录详细错误堆栈。
---
---
url: /plugin-dev/backend/functions/index.md
---
# SDK函数方法
## 日志方法
统一使用SDK提供的ASP.NET的Logger。
```c#
SDK.MSLX.Logger.Info("mslx-plugin-demo 载入成功~");
```
## 文件下载
MSLX SDK映射了守护进程中的下载管理器,可以按照示例进行调用。
```c#
// ===== 下载器调用示例 =====
SDK.MSLX.Logger.Info("准备下载文件...");
string targetPath = Path.Combine(this.Config().GetDataPath(), "server.jar");
var result = await SDK.MSLX.Downloader.DownloadFileAsync(
"https://example.com/server.jar",
targetPath,
(progress, speed) =>
{
SDK.MSLX.Logger.Debug($"\r下载中: {progress:0.0}% [{speed}]");
});
if (result.Success)
{
SDK.MSLX.Logger.Info("下载完成,可以开始搞事情了!");
}
else
{
SDK.MSLX.Logger.Error($"下载失败: {result.ErrorMessage}");
}
```
## GET/POST请求
```c#
// get请求示例
var response = await SDK.MSLX.Http.GetAsync("https://api.mslmc.cn/v3/query/notice?query=id");
if (response.IsSuccessStatusCode)
{
JObject jobj = JObject.Parse(response.Content ?? "{}");
string content = jobj["data"]?["noticeID"]?.ToString() ?? "";
SDK.MSLX.Logger.Info($"获取到的MSL公告编号: {content}");
}
// post
var postResponse = await SDK.MSLX.Http.PostAsync(
"https://example.cn/post-api",
PluginHttpContentType.Json,
new { username = "admin", action = "start" }
);
```
## 系统与路径助手
SDK 提供了访问宿主数据目录及当前插件独立存储目录的工具方法。
```c#
// 获取 MSLX 宿主全局 AppData 数据目录路径
string appDataPath = SDK.MSLX.Config.GetAppDataPath();
// 获取 MSLX 宿主主配置文件路径
string appConfigPath = SDK.MSLX.Config.GetAppConfigPath();
// 获取当前插件专属的独立数据存储目录 (插件实例扩展方法)
string pluginDataPath = this.Config().GetDataPath();
```
## 全局后台任务与进度条
MSLX 提供了全局的后台任务池,插件可以通过 `SDK.MSLX.Tasks` 接口将耗时操作扔进全局任务池,从而在 WebPanel 右上角的“后台任务”抽屉里展示带进度条的任务。
```c#
// 1. 创建任务 (用户ID可以通过上下文或保留为空,实例ID通常填0,TaskType.Plugin 代表插件任务)
var (task, token) = SDK.MSLX.Tasks.CreateTask(
userId: "",
instanceId: 0,
type: MSLX.SDK.Models.Files.TaskType.Plugin,
title: "正在备份插件数据",
targetName: "my-plugin-backup.zip"
);
Task.Run(async () =>
{
try
{
for (int i = 0; i <= 100; i += 10)
{
// 响应用户在前端点击的“取消”操作
if (token.IsCancellationRequested)
{
// 收到取消信号后,清理垃圾并退出
SDK.MSLX.Tasks.SetFailed(task.Id, "用户已取消");
return;
}
// 2. 更新任务进度
SDK.MSLX.Tasks.UpdateProgress(task.Id, i, $"正在处理第 {i}% 的数据...");
await Task.Delay(500); // 模拟耗时
}
// 3. 标记任务完成
SDK.MSLX.Tasks.SetSuccess(task.Id, "备份完成!");
}
catch (Exception ex)
{
// 标记任务失败
SDK.MSLX.Tasks.SetFailed(task.Id, ex.Message);
}
});
```
---
---
url: /plugin-dev/entry/index.md
---
# 插件入口声明
## 插件入口完整示例
这是 STUN 插件的入口文件。(部分方法需要 `V1.5.2+` 版本的MSLX支持)。详细说明见后文。
入口文件主要是从 `MSLX.SDK` 导出 `IPlugin` 对象然后填写相关的信息和实现相关声明周期方法。
```c#
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using MSLX.Plugin.Stun.Hubs;
using MSLX.Plugin.Stun.Managers;
using MSLX.SDK;
[assembly: ApplicationPart("MSLX.Plugin.Stun")]
namespace MSLX.Plugin.Stun;
public class MSLXPluginEntry : IPlugin
{
public static MSLXPluginEntry Instance { get; private set; } = null!;
public string Id => "mslx-plugin-stun";
public string Name => "STUN 隧道";
public string Description => "利用 STUN 技术,在 NAT1 环境下获取公网端口,支持多开与流量监控。";
public string Version => "1.0.2";
public string Icon => "icon.png";
public string MinSDKVersion => "1.5.2";
public string Developer => "xiaoyu";
public string AuthorUrl => "https://github.com/luluxiaoyu";
public string PluginUrl => "https://mslx-plugins.mslmc.net/plugins/mslx-plugin-stun";
public void OnPluginInitialize(IServiceProvider serviceProvider)
{
Instance = this;
SDK.MSLX.Logger.Info("[STUN] 隧道插件开始初始化...");
string dataDir = this.Config().GetDataPath();
if (!Directory.Exists(dataDir)) Directory.CreateDirectory(dataDir);
var tunnelManager = serviceProvider.GetRequiredService();
tunnelManager.Initialize(dataDir);
SDK.MSLX.Logger.Info($"[STUN] 插件载入成功,当前已加载 {tunnelManager.GetConfigs().Count} 个隧道配置。");
}
/*
public void OnUnload()
{
} */
public void OnRegisterEndpoints(IEndpointRouteBuilder endpoints)
{
endpoints.MapHub("/api/hubs/plugins/mslx-plugin-stun/stun");
}
public void OnRegisterServices(IServiceCollection services)
{
services.AddSingleton();
}
}
```
## 插件入口元数据
:::: field-group
::: field Id
@type string
@required
插件的唯一ID,格式为`mslx-plugin-xxx`
:::
::: field Name
@type string
@required
插件名字
:::
::: field Description
@type string
@default 这个开发者很懒,什么都没写。
插件描述
:::
::: field Version
@type string
@required
插件版本号
:::
::: field Icon
@type string
@default https://www.mslmc.cn/logo.png
插件图标,支持在线地址和本地文件(本地文件把图片文件放在前端Public即可)
:::
::: field MinSDKVersion
@type string
@required
最低SDK版本要求(其实就是最低MSLX版本要求)
:::
::: field Developer
@type string
@default 不知道哇!
开发者名字
:::
::: field AuthorUrl
@type string
@default https://github.com/MSLTeam
开发者主页地址
:::
::: field PluginUrl
@type string
@default https://github.com/MSLTeam
插件地址(建议填写MSLX插件中心的地址)
:::
::::
## 插件生命周期方法
:::: field-group
::: field OnPluginInitialize(IServiceProvider serviceProvider)
@type void()
插件初始化的生命周期方法,执行时序早于 `OnLoad()`
:::
::: field OnLoad()
@type void()
插件加载完成的生命周期方法
:::
::: field OnUnload()
@type void()
插件卸载的生命周期方法(其实就是MSLX关闭)
:::
::: field OnRegisterEndpoints(IEndpointRouteBuilder endpoints)
@type void()
插件向宿主注册高级路由的生命周期
约定:如果需要注册 `SignalR` 路由,前缀请注册为:`/api/hubs/plugins/mslx-plugin-xxx/xxx`
即 `/api/hubs/plugins/{插件ID}` 前缀是不变的
:::
::: field OnRegisterServices(IServiceCollection services)
@type void()
插件向宿主注册依赖注入(DI)服务的生命周期。宿主会自动将 `IInstanceLifecycleService`、`IFrpProcessService` 等系统级服务注入全局容器,插件注册的服务或 Controller 可直接在构造函数中声明并使用这些宿主服务:
```c#
public void OnRegisterServices(IServiceCollection services)
{
// 注册插件自己的服务
services.AddSingleton();
}
```
:::
::::
## API 路由与 ApplicationPart 声明
若插件内包含提供 Web API 接口的 Controller(控制器),必须在入口文件顶部(命名空间外)声明 `[assembly: ApplicationPart("程序集名称")]`:
```c#
using Microsoft.AspNetCore.Mvc.ApplicationParts;
[assembly: ApplicationPart("MSLX.Plugin.Stun")]
```
::: tip 为什么需要 ApplicationPart?
MSLX 宿主通过反射动态加载外部插件时,ASP.NET Core MVC 依赖 `ApplicationPart` 检索程序集内的 Controller 控制器。若未声明,会导致 Controller 路由无法被宿主注册。
:::
---
---
url: /plugin-dev/frontend/components/index.md
---
# 插入组件
## 概述
::: important 使用插槽注入自定义组件时,请尽量让您的设计样式和原页面保持一致。
:::
MSLX 的插件系统允许您在原有页面的一些槽位新增组件/插入下拉菜单,效果如下:

新增的组件注入均在插件的 ==入口文件== 中导出的 `pluginConfig` 集合中的 `extensions` 数组。
具体示例可参考 ==mslx-plugin-demo== 插件的插件入口示例:[mslx-plugin-demo/Frontend/src/pluginEntry.ts at main · MSLTeam/mslx-plugin-demo](https://github.com/MSLTeam/mslx-plugin-demo/blob/main/Frontend/src/pluginEntry.ts)
本文档将展示所有支持的插槽。其中徽章指示代表该插槽支持的最低MSLX SDK版本。
## 配置示例
:::: field-group
::: field name="extensions\[i].slot" type="string" required
插槽名字(见本文档)
:::
::: field name="extensions\[i].component" type="string" required
嵌入的组件(需要在上方import)
:::
::::
以上两项为插槽的通用配置,如插槽有其他配置项(例如`label`),会在下方文档补充说明。
```ts
extensions: [
{
slot: 'instance-console-dropdown', // 注入到实例控制台更多功能的下拉菜单
component: InstanceDropDownItemInject, // 弹窗组件
label: '插件弹窗', // 下拉子菜单名
icon: GitBranchIcon, // 下拉子菜单Icon
},
{
slot: 'instance-console-overview-bottom', // 注入到实例控制台玩家卡片下方
component: InstanceCardInject, // 组件
}
]
```
## 服务端管理-实例控制台-更多功能菜单插槽
插槽名:`instance-console-dropdown`
在此页面的 ==更多功能== 下拉菜单处新增一个菜单项,点击该菜单应该新显示一个 `t-dialog` 组件。
此插槽需要新增以下配置项:
:::: field-group
::: field name="extensions\[i].label" type="string" required
新增的下拉菜单的名字
:::
::: field name="extensions\[i].icon" type="component" required
嵌入的图标组件(需要是TDesign的图标组件)
:::
::::
```ts
{
slot: 'instance-console-dropdown', // 注入到实例控制台更多功能的下拉菜单
component: InstanceDropDownItemInject, // 弹窗组件
label: '插件弹窗', // 下拉子菜单名
icon: GitBranchIcon, // 下拉子菜单Icon
},
```

此外,为了能正常触发`t-dialog`的显示,需要在插入的组件中暴露一个`open`方法给宿主。
```ts
// 暴露接口给宿主
defineExpose({
open: () => {
console.log('👉 [插件内部] open 方法被成功触发!');
visible.value = true; // 显示弹窗
}
});
```
可接收props:
```ts
const props = defineProps({
serverId: Number
});
```
简单的弹窗组件示例在这里:[mslx-plugin-demo/Frontend/src/views/InstanceDropDownItemInject.vue at main · MSLTeam/mslx-plugin-demo](https://github.com/MSLTeam/mslx-plugin-demo/blob/main/Frontend/src/views/InstanceDropDownItemInject.vue)
## 服务端管理-实例控制台-左侧控制栏下方插槽
插槽名:`instance-console-overview-bottom`

可接收props:
```ts
const props = defineProps({
serverId: {
type: Number,
required: true
},
status: {
type: Number,
default: 0
}
});
```
示例插入组件:[mslx-plugin-demo/Frontend/src/views/InstanceCardInject.vue at main · MSLTeam/mslx-plugin-demo](https://github.com/MSLTeam/mslx-plugin-demo/blob/main/Frontend/src/views/InstanceCardInject.vue)
## 服务端管理-实例控制台-实例设置-更多功能插槽
插槽名:`instance-setting-more`

可接收props:
```ts
const props = defineProps({
serverId: {
type: Number,
required: true
}
});
```
## 服务端管理-实例控制台-实例设置-自定义选项卡插槽
插槽名:`instance-settings-tab`
在实例配置侧边栏最底部新增一个选项卡(Tab),点击后右侧展示对应的组件内容。
此插槽需要新增以下配置项:
:::: field-group
::: field name="extensions\[i].label" type="string" required
新增选项卡的名称(显示在左侧菜单栏)
:::
::: field name="extensions\[i].icon" type="component | string" required
选项卡的图标,支持传入 TDesign 的图标组件(如 `SettingIcon`)或 Emoji / 文本字符串(如 `'🧩'`)
:::
::::
```ts
{
slot: 'instance-settings-tab', // 注入到实例配置侧边栏选项卡
component: InstanceSettingsPluginTab, // 选项卡内容组件
label: '插件配置', // 选项卡名字
icon: SettingIcon, // 选项卡图标,可使用 TDesign 图标组件或 Emoji 字符串
},
```
可接收props:
```ts
const props = defineProps({
serverId: {
type: Number,
required: true
},
instanceId: {
type: Number,
required: true
}
});
```
支持触发的事件(Emits):
```ts
const emits = defineEmits<{
(e: 'success'): void;
(e: 'saved'): void;
}>();
```
## 仪表盘-系统状态监控卡片下方插槽
插槽名:`dashboard-index-after-system-status`

## 隧道管理-隧道控制台-隧道信息下方插槽
插槽名:`frp-console-control-panel-bottom`

可接收props:
```ts
const props = defineProps({
frpId: {
type: Number,
required: true
},
isRunning: {
type: Boolean,
default: false
}
});
```
## 隧道管理-创建隧道-隧道服务商插槽
插槽名:`frp-create-provider`
此插槽需要新增以下配置项:
:::: field-group
::: field name="extensions\[i].label" type="string" required
新增的隧道服务商名字(会显示在切换按钮)
:::
::::
```ts
{
slot: 'frp-create-provider', // 注入到创建Frp的选项卡
component: DemoPage, // 组件,
label: '插件扩展服务', // 选项卡名字
}
```

## 设置-基础设置下方卡片插槽
插槽名:`settings-profile-bottom`

## 设置-系统设置下方卡片插槽
插槽名:`settings-daemon-bottom`

---
---
url: /plugin-dev/frontend/host-api/index.md
---
# 宿主 API 与状态透传
## 概述
MSLX 宿主项目在全局 `window` 对象上暴露了底层核心依赖库、请求实例及 Pinia 状态库。插件可以在前端代码中直接通过 `window` 对象(或导入 `mslx-request` 机制)直接调用宿主的能力。
前端 Demo 完整示例代码参见:[mslx-plugin-demo/DemoPage.vue](https://github.com/MSLTeam/mslx-plugin-demo/blob/main/Frontend/src/views/DemoPage.vue)
## 宿主暴露的全局对象
宿主在入口打包时挂载了以下全局属性:
```ts
(window as any).Vue = Vue;
(window as any).VueRouter = VueRouter;
(window as any).Pinia = Pinia;
(window as any).TDesign = TDesign;
(window as any).mslxRequest = request;
(window as any).MSLX_Stores = MSLXStores;
```
***
## 宿主 Pinia 状态库 (MSLX\_Stores)
插件可以通过 `(window as any).MSLX_Stores` 读取宿主挂载的所有 Pinia Store。
### 宿主 Pinia Store 完整清单
| Store 名称 | 导出的 Hook / 函数 | 作用与内部常用状态/方法 |
| :--- | :--- | :--- |
| **user** | `useUserStore()`, `getUserStore()` | **用户与系统状态**:`userInfo`(包含用户名 `name`、头像 `avatar`、角色 `roles`、操作系统 `systemInfo`)、`token`、`baseUrl`、`isAdmin`、`getUserInfo()`、`logout()` 等。 |
| **setting** | `useSettingStore()`, `getSettingStore()` | **外观与主题**:`mode` ('dark' | 'light' | 'auto')、`displayMode`、`brandTheme` (主色调)、`changeMode()`、`updateConfig()` 等。 |
| **permission** | `usePermissionStore()`, `getPermissionStore()` | **路由权限管理**:`routers` (已授权路由列表)、`whiteListRouters`、`initRoutes()`、`clearRoutes()` 等。 |
| **webpanel** | `useWebpanelStore()` | **面板样式与文件上传**:`settings` (背景透明度、毛玻璃模糊度等)、`uploadImage(file)` 文件上传等。 |
| **instance** | `useInstanceListStore()` | **实例列表**:`instanceList` (全量实例数组)、`totalInstanceCount`、`onlineInstanceCount`、`refreshInstanceList()` 等。 |
| **frp** | `useTunnelsStore()` | **FRP 隧道列表**:`frpList` (隧道列表数组)、`getTunnels()` 刷新数据等。 |
| **node** | `useNodeStore()` | **子节点管理**:`slaveNodes` (节点列表)、`activeNodeId` (当前激活节点)、`setActiveNode()`、`fetchNodes()` 等。 |
| **pluginUI** | `usePluginUIStore()` | **插件 UI 扩展槽**:`extensions` 插槽注册表、`registerExtension()` 等。 |
| **update** | `useUpdateStore()` | **主程序更新**:`updateInfo` (最新版本信息)、`checkAppUpdate()` 等。 |
### 代码示例:获取当前登录用户信息
```ts
import { computed } from 'vue';
// 1. 获取宿主状态集合
const stores = (window as any).MSLX_Stores;
// 2. 调用对应的 store
const userStore = stores?.getUserStore?.() || stores?.useUserStore?.();
// 3. 结合 computed 绑定状态
const userInfo = computed(() => userStore?.userInfo || { name: '未登录', avatar: '' });
const isAdmin = computed(() => userStore?.isAdmin || false);
console.log('当前登录用户:', userInfo.value.name);
```
### 代码示例:获取并刷新服务端实例列表
```ts
const stores = (window as any).MSLX_Stores;
const instanceStore = stores?.useInstanceListStore?.();
// 刷新实例列表数据
await instanceStore?.refreshInstanceList();
console.log('总实例数:', instanceStore?.totalInstanceCount);
console.log('在线实例列表:', instanceStore?.instanceList);
```
***
## 宿主请求实例 (mslxRequest / request)
宿主将配置好的 Axios 实例挂载在 `(window as any).mslxRequest` 上(插件项目通常可以通过 `import request from 'mslx-request'` 引用)。
::: tip 自动解包说明
宿主内置了响应拦截器(`transformRequestHook`)。当后端接口返回标准的 `{ code: 200, data: ..., message: ... }` 格式时,`request.get/post` **会自动解包并直接返回 `data` 字段**。在插件调用时**直接接收 `res` 即可拿到目标数据,无需再写 `res.data`**。
:::
### 类型定义
#### 1. RequestOptions (请求配置扩展参数)
```ts
export interface RequestOptions {
apiUrl?: string;
isJoinPrefix?: boolean;
urlPrefix?: string;
joinParamsToUrl?: boolean;
formatDate?: boolean;
isTransformResponse?: boolean;
isReturnNativeResponse?: boolean;
ignoreRepeatRequest?: boolean;
joinTime?: boolean;
withToken?: boolean;
/**
* 是否发送到子节点,默认为 'auto'。
* - 'auto': 自动通过正则匹配路径 (如 /instance/, /files/, /frp/ 等) 判定是否路由到当前激活的子节点。
* - true: 强制路由到当前激活的子节点。
* - false: 强制发送到主节点。
*/
requestToSlaveNode?: boolean | 'auto';
retry?: {
count: number;
delay: number;
};
}
```
#### 2. Result\ (后端原始标准响应结构)
后端接口在服务端返回的标准格式定义如下(宿主拦截器会在 `code === 200` 时自动抽取 `data` 属性):
```ts
export interface Result {
code: number;
data: T;
message?: string;
}
```
#### 3. AxiosRequestConfigRetry (配置重试扩展)
```ts
import { AxiosRequestConfig } from 'axios';
export interface AxiosRequestConfigRetry extends AxiosRequestConfig {
retryCount?: number;
}
```
### 代码示例:发起 GET 请求
```ts
import request from 'mslx-request';
// 或 const request = (window as any).mslxRequest;
const fetchDemoData = async () => {
try {
// 宿主拦截器已自动解包解出 data,res 直接为接口数据本体
const res = await request.get({
url: '/api/plugins/mslx-plugin-demo/demo'
});
// 直接使用 res,不需要写 res.data
console.log('数据内容:', res);
} catch (err: any) {
console.error('请求失败:', err.message);
}
};
```
### 代码示例:发起 POST 请求(配置子节点路由与重试)
```ts
import request from 'mslx-request';
const submitPluginConfig = async (data: Record) => {
try {
const res = await request.post({
url: '/api/plugins/mslx-plugin-demo/config',
data,
}, {
// requestToSlaveNode 默认为 'auto';若需强制请求主节点可设为 false
requestToSlaveNode: false,
retry: {
count: 3, // 失败自动重试 3 次
delay: 1000 // 重试延迟 1000ms
}
});
console.log('提交成功,响应数据:', res);
} catch (err) {
console.error('提交失败:', err);
}
};
```
---
---
url: /plugin-dev/frontend/routes/index.md
---
# 新增菜单路由
## 概述
MSLX 的插件系统允许您在网页控制台的前端新增菜单路由,效果如下:

新增的菜单配置均在插件的 ==入口文件== 中导出的 `pluginConfig` 集合中的 `routes` 数组。
具体示例可参考 ==mslx-plugin-demo== 插件的插件入口示例:[mslx-plugin-demo/Frontend/src/pluginEntry.ts at main · MSLTeam/mslx-plugin-demo](https://github.com/MSLTeam/mslx-plugin-demo/blob/main/Frontend/src/pluginEntry.ts)
## 新增一级菜单
:::: field-group
::: field name="path" type="string" required
新增的路由地址
:::
::: field name="name" type="string" required
路由名字(建议带上插件名字,以防和其他插件或宿主冲突)
:::
::: field name="component" type="string" required default="HOST\_LAYOUT"
新增一级菜单请填写 ==HOST\_LAYOUT== 即可
:::
::: field name="meta.title" type="string" required
新增的菜单标题
:::
::: field name="meta.icon" type="string" required
新增菜单的icon (仅支持使用tdesign的icon组件哦)
:::
::: field name="meta.roleCode" type="array"
新增菜单的可见范围,默认是所有用户可见
:::
::: field name="children\[0].path" type="string" required
新增的路由地址(因为是新增一级菜单,这里一般留空即可)
:::
::: field name="children\[0].name" type="string" required
子路由名字(建议带上插件名字,以防和其他插件或宿主冲突)
:::
::: field name="children\[0].component" type="string" required
插入的组件(需要在插件入口顶部Import相应组件)
:::
::: field name="children\[0].meta.title" type="string" required
新增的菜单标题
:::
::: field name="children\[0].meta.hidden" type="boolean" required
由于是只有一级菜单,这里直接填 `true`。(注:将子路由设为 hidden 是为了在侧边栏仅显示一级菜单项,而点击时渲染该子路由组件。)
:::
::: field name="children\[0].meta.roleCode" type="array"
新增菜单的可见范围,默认是所有用户可见
:::
::::
```ts
{
path: '/plugin-single',
name: 'PluginSingleBase',
component: 'HOST_LAYOUT',
meta: { title: '插件单页', icon: 'app', roleCode: ['admin', 'user'] },
children: [
{
path: '',
name: 'PluginSingle',
component: DemoPage,
meta: { title: '插件单页', hidden: true, roleCode: ['admin', 'user'] },
},
],
},
```
## 新增一级和二级菜单
:::: field-group
::: field name="path" type="string" required
新增的一级路由前缀地址
:::
::: field name="name" type="string" required
一级路由名字(建议带上插件名字,以防和其他插件或宿主冲突)
:::
::: field name="component" type="string" required default="HOST\_LAYOUT"
新增一级菜单请填写 ==HOST\_LAYOUT== 即可
:::
::: field name="meta.title" type="string" required
新增的一级菜单标题
:::
::: field name="meta.icon" type="string" required
新增一级菜单的icon (仅支持使用tdesign的icon组件哦)
:::
::: field name="meta.roleCode" type="array"
新增一级菜单的可见范围,默认是所有用户可见
:::
::: field name="children\[i].path" type="string" required
新增的二级菜单路由地址
:::
::: field name="children\[i].name" type="string" required
二级菜单路由名字(建议带上插件名字,以防和其他插件或宿主冲突)
:::
::: field name="children\[i].component" type="string" required
插入的组件(需要在插件入口顶部Import相应组件)
:::
::: field name="children\[i].meta.title" type="string" required
新增的二级菜单标题
:::
::: field name="children\[i].meta.icon" type="string"
新增二级菜单的icon (仅支持使用tdesign的icon组件哦)
:::
::: field name="children\[i].meta.roleCode" type="array"
新增菜单的可见范围,默认是所有用户可见
:::
::::
```ts
{
path: '/plugin-multi',
name: 'PluginMultiBase',
component: 'HOST_LAYOUT',
meta: { title: '插件多页', icon: 'layers', roleCode: ['admin', 'user'] },
children: [
{
path: 'page-a',
name: 'PluginMultiA',
component: DemoPage,
meta: { title: '子页面A', roleCode: ['admin', 'user'] },
},
{
path: 'page-b',
name: 'PluginMultiB',
component: DemoPage,
meta: { title: '子页面B', roleCode: ['admin', 'user'] },
},
],
},
```
## 插入原有一级菜单
:::: field-group
::: field name="parentName" type="string" required
需要插入的一级菜单的名字,可以在这里查询可选值,下面也列出来常见的三个一级菜单:
[MSLX/MSLX.WebPanel/src/router/modules at dev · MSLTeam/MSLX](https://github.com/MSLTeam/MSLX/tree/dev/MSLX.WebPanel/src/router/modules)
* `instance` (服务端管理)
* `frp` (隧道管理)
* `settingsBase` (设置)
:::
::: field name="path" type="string" required
插入的二级菜单路由地址
:::
::: field name="name" type="string" required
路由名字(建议带上插件名字,以防和其他插件或宿主冲突)
:::
::: field name="component" type="string" required
导入组件(记得import哦)
:::
::: field name="meta.title" type="string" required
新增的二级路由菜单标题
:::
::: field name="meta.icon" type="string" required
新增二级菜单的icon (仅支持使用tdesign的icon组件哦)
:::
::: field name="meta.roleCode" type="array"
新增菜单的可见范围,默认是所有用户可见
:::
::::
```ts
{
parentName: 'instance',
path: 'plugin-extra',
name: 'PluginNestedSetting',
component: DemoPage,
meta: { title: '插件子菜单', icon: 'control-platform', roleCode: ['admin', 'user'] },
}
```
---
---
url: /plugin-dev/init/publish/index.md
---
# 发布插件到MSLX插件市场
## 发布插件到MSLX插件市场
::: tip 目前插件市场独立站点的UI做的比较粗糙,后续会优化,目前能用就行QWQ
:::
:::: steps
1. ### 登录到MSLX插件市场
点击左下角 ==登录== 会自动跳转到 ==MSL用户中心== 进行授权登录,若没有账号需要注册下。

2. ### 填写插件信息
登录后,进入 ==插件管理-插件发布== 页面。填写插件的信息。
插件ID必须以`mslx-plugin-`开头,否则无法提交。
名称,图标,介绍(支持Markdown)自己填写即可。(支持使用图片,但是只能通过图床上传)。
如果没有图标,请填写:`https://www.mslmc.cn/logo.png`。

3. ### 发布第一个版本
点击 ==创建并进入下一步== 后进入版本页面,填写插件版本号(请和插件内填写的元数据一致)。
以及填写更新日志和下载地址。!!修复了一些BUG,增强了稳定性。!!
下载地址 ==不允许填写网盘地址== ,可以是直链,也可以是Github Release复制的文件地址。

4. ### 等待审核完成
提交后会跳转到预览到插件详情页面,等待审核即可。
::: important 每次修改插件详情都需要进入审核阶段,但是发布新版本只会审核新版本,不影响现有插件详情和老版本的展示。
:::

如果不通过,那么会在 ==我的插件== 页面显示原因,可根据原因再次进行修改提交。

5. ### 迭代发布新版本
进入插件的编辑页面,进入 ==版本与发布== ,==发布新版== 。
填写信息后提交即可。


::::
---
---
url: /plugin-dev/init/start/index.md
---
# MSLX 插件开发规范
## 概要
::: important 第一次写这种文档,如果有写的不好,不明白的地方,可以提出issue / pr修正 / 进群交流。如果觉得项目中提供的方法不够用,无法实现相应的功能,也欢迎来交流~
:::
MSLX 插件目前目前由后端插件+前端UI组件组成。(桌面客户端版本尚在开发中)。
插件开发需要您对 C# 和 Vue 有一定的了解。!!当然,你可以去改模板项目随便玩玩。!!
后端采用的是 ==ASP.NET (C#)== ,前端采用 ==Vue + TDesign + UnoCSS== 。
插件的Github仓库约定规范命名方式为:`mslx-plugin-xxx`。
::: tip MSLX 的前端项目用的 TailwindCSS ,但是测试发现会存在样式污染,故改换使用 UnoCSS 。
:::
## AI喜欢阅读的内容
!!以下内容不适合人类阅读!!\
[llms.txt](/llms.txt) | [llms-full.txt](/llms-full.txt)\
把这两文件丢给AI,再给AI一个 `demo` 插件模板,想做一个插件是十分容易的事情。
## 后端开发规范
前端UI与后端的通信均使用 ==标准HTTP接口== 通讯。
路由规范:`/api/plugin/{plugin-id}/[controller]/具体API接口`。
其中 `/api/plugin/{plugin-id}/` 这个前缀 ==不允许== 变更。
另外,如果需要较强的实时通讯,建议使用 ASP.NET 的 `SignalR` 通讯(底层是ws)。
同样路由规范:`/api/hubs/plugin/{plugin-id}/具体路由`。
::: tip 提示
若插件包含 Controller,入口文件顶部需声明 `[assembly: ApplicationPart("程序集名称")]`。
:::
## 前端UI开发规范
前端UI目前支持在菜单上新增页面,原有页面插入组件仍在开发中。
在使用CSS务必注意一个原则:==不能污染主项目的样式== 。
Vue组件内的`style`请添加`scope`范围限制。且 ==不应当随意引入全局样式== 。(除非你想尝试通过此方法魔改样式,那么您可以尝试,但是也请确保主项目其他位置UI正常)。
---
---
url: /plugin-dev/init/template/index.md
---
# 从示例模板创建插件项目
## 插件示例示例项目
插件的示例项目提供了简单的路由案例 + MSLX 内一些方法的调用示例 + MSLX 的配置读取示例。
!!随便改改模板就是一个新的插件是吧QWQ。!!

## 必须修改的地方
如果您想简单一点直接使用插件模板进行二次开发,那么根据以下步骤修改插件信息即可。
### 插件元数据与 ApplicationPart
在插件的入口文件 `MSLXPluginEntry.cs` 中,对 `Id` 等信息进行修改。
Id 是必须要改的,规范为:`mslx-plugin-xxx`。起名前建议到 Github 查询是否存在同名插件,以防撞车。
若您的插件包含 API 控制器(Controller),请同步将文件顶部的 `[assembly: ApplicationPart("MSLX.Plugin.Demo")]` 修改为您重命名后的程序集名称,确保宿主能够正确发现并注册路由。

### 前端项目名
进入 `Frontend/package.json`,修改 `name` 参数,和上述元数据的 `Id` 一致即可。
::: important 这里很重要,必须修改,否则可能造成CSS污染
:::

## 开始开发
改完上述内容后就可以开始对插件进行定制想要的功能了。
后端可供调用的方法可以查阅:[MSLX.SDK](https://github.com/MSLTeam/MSLX/tree/dev/MSLX.SDK) 。
路由都应该写在`Controllers`命名空间下,具体写法也可以参考`DemoController`。

前端插件的注册入口在`PluginEntry.js`。可以参考路由组件是如何进行注册的。

---
---
url: /sponsor/index.md
---
# 赞助我们的开发
::: important 赞助我们的开发
\==MSLX=={.important}是一款全新的跨平台开服软件,由MSLTeam开发,旨在帮助各位服主轻松开启一个属于您自己的MC服务器。
如果觉得MSLX还不错,可以给个[✨Star](https://github.com/MSLTeam/MSLX)呀~
如果您有能力,可以小小的赞助一下我们的开发~
:::
---
---
url: /third-party/lolia-frp/callback.md
---
# Lolia FRP 授权返回