Skip to content

Commit d447c30

Browse files
authored
Merge pull request #34 from xieyuen/dev/kill_server
KillServer v1.0.0
2 parents 3be34f0 + 8daa6b3 commit d447c30

4 files changed

Lines changed: 102 additions & 36 deletions

File tree

src/KillServer/README.md

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,22 @@
55
> [!WARNING]
66
> 此插件使用 [dowhen](http://github.com/gaogaotiantian/dowhen/) 模块实现, 可能不够稳定
77
8+
> [!TIP]
9+
> BUG Report: [GitHub issues](https://github.com/xieyuen/MCDR-Plugins/issues/new)
10+
811
## 介绍
912

10-
对于下面的两种情况(实际可能还有更多适用的情况):
13+
对于下面的情况(实际可能还有更多适用的情况):
1114

1215
1. Fabric 服务器卡死不关闭
13-
- [MCDReforged/MCDReforged#150](https://github.com/MCDReforged/MCDReforged/issues/150)
14-
- [EngineHub/WorldEdit#2459](https://github.com/EngineHub/WorldEdit/issues/2459)
16+
- [MCDReforged/MCDReforged#150](https://github.com/MCDReforged/MCDReforged/issues/150)
17+
- [EngineHub/WorldEdit#2459](https://github.com/EngineHub/WorldEdit/issues/2459)
1518
2. `pause` 命令诱发用户Ctrl+C操作,导致 MCDR 关闭与存档恢复冲突,最终致使存档损坏
16-
- [TISUnion/PrimeBackup#85](https://github.com/TISUnion/PrimeBackup/issues/85)
17-
19+
- [TISUnion/PrimeBackup#85](https://github.com/TISUnion/PrimeBackup/issues/85)
20+
- [MCDReforged/MCDReforged#394](https://github.com/MCDReforged/MCDReforged/issues/394)
1821

1922
本插件提供监听服务器关闭并且在这些情况下强制关闭服务器的功能, 给小白腐竹们提供一个简单且无脑的解决方案
2023

21-
## 配置
22-
23-
| 配置项 | 类型 | 默认值 | 含义 | 注释 |
24-
|:--------------:|:-------:|:------:|:-------------------|:--------|
25-
| `enable` | `bool` | `True` | 是否启用插件 | 不影响事件分发 |
26-
| `waiting_time` | `float` | `60` | 等待服务器关闭的时间, 超时强制关闭 | 单位为秒 |
27-
2824
## 使用方法
2925

3026
直接安装到 MCDR 的插件文件夹下即可, 可以从 [GitHub](https://github/xieyuen/MCDR-Plugins)
@@ -42,40 +38,68 @@
4238
> 你都用 MCDR 了竟然还不知道原生 `/stop` 会让 MCDR 关闭吗?<br>
4339
> 你都用 MCDR 了竟然还用不支持运行时回档的备份模组而不是 PrimeBackup、QuickBackupM 吗?
4440
41+
## 配置
42+
43+
| 配置项 | 类型 | 默认值 | 含义 | 注释 |
44+
|:--------------:|:-------:|:-------:|:----------------------------------------------------------------|:--------|
45+
| `enable` | `bool` | `True` | 是否启用插件 | 不影响事件分发 |
46+
| `waiting_time` | `float` | `60` | 等待服务器关闭的时间, 超时强制关闭 | 单位为秒 |
47+
| `mcdr_only` | `bool` | `False` | 是否只监听 [`PluginStoppingServerEvent`](#PluginStoppingServerEvent) | |
48+
4549
## 新的事件
4650

4751
KillServer 创建了三个字面量事件 [`ServerStoppingEvent`](#serverstoppingevent),
4852
[`PluginStoppingServerEvent`](#pluginstoppingserverevent)
49-
[`WorldSavedEvent`](#worldsavedevent)
53+
[`WorldSavedEvent`](#worldsavedevent) 用以监听服务器控制事件
54+
55+
你可以通过下面的方式在自己的插件中使用这些事件
5056

5157
```python
5258
from kill_server import ServerStoppingEvent, PluginStoppingServerEvent, WorldSavedEvent
59+
from mcdreforged import event_listener, PluginServerInterface
60+
61+
62+
# import
63+
@event_listener(ServerStoppingEvent)
64+
def on_server_stopping(server: PluginServerInterface):
65+
pass
66+
67+
68+
# or id
69+
@event_listener("kill_server.server_stopping") # also
70+
def on_server_stopping(server: PluginServerInterface):
71+
pass
5372
```
5473

74+
> [!TIP]
75+
> 如果你只是需要各个事件而不需要强制关闭功能的话可以把配置中的 `enable` 项设定为 `false`,
76+
> 该配置只会影响强制关闭功能而不会停止事件分发
77+
5578
### ServerStoppingEvent
5679

57-
KillServer 创建了一个字面量事件 `ServerStoppingEvent = LiteralEvent("kill_server.server_stopping")`
58-
用以监听服务器关闭, 这个事件会在服务器关闭时 (例如 `/stop` 被调用时) 分发
80+
字面量事件 `ServerStoppingEvent = LiteralEvent("kill_server.server_stopping")`
81+
用以监听服务器关闭, 这个事件会在服务器开始关闭时 (例如 `/stop` 被调用时) 触发
5982

6083
- **事件 ID**: `kill_server.server_stopping`
6184
- **回调参数**: `PluginServerInterface`
6285

6386
### PluginStoppingServerEvent
6487

65-
KillServer 创建了一个字面量事件 `PluginStoppingServerEvent = LiteralEvent("kill_server.plugin_stopping_server")`
66-
用以监听 ***由插件或调用 MCDR 命令*** 导致的服务器关闭, 这个事件会在服务器关闭时 (例如 `!!MCDR server stop` 被调用时) 分发
88+
事件 `PluginStoppingServerEvent = LiteralEvent("kill_server.plugin_stopping_server")`
89+
用以监听 ***由插件调用 `ServerInterface.stop()` 或调用 MCDR 命令*** 导致的服务器开始关闭,
90+
这个事件会在服务器关闭时 (例如 `!!MCDR server stop` 被调用时) 触发
91+
92+
> [!IMPORTANT]
93+
> 1. 该事件同时会引发 [`ServerStoppingEvent`](#serverstoppingevent)
94+
> 2. `ServerInterface.kill()` 不会触发该事件, 因为服务器此时不是正常开始关闭而是进程组被 kill
6795
6896
- **事件 ID**: `kill_server.plugin_stopping_server`
6997
- **回调参数**: `PluginServerInterface`
7098

7199
### WorldSavedEvent
72100

73101
KillServer 创建了一个字面量事件 `WorldSavedEvent = LiteralEvent("kill_server.world_saved")`
74-
用以监听服务器是否将世界保存好, 这个事件会在服务器保存世界完成时 (例如 `/save` 被调用之后) 分发
102+
用以监听服务器是否将世界保存好, 这个事件会在服务器保存世界完成时 (例如 `/save` 被调用之后) 触发
75103

76104
- **事件 ID**: `kill_server.world_saved`
77105
- **回调参数**: `PluginServerInterface`
78-
79-
> [!TIP]
80-
> 如果你只是需要各个事件而不需要强制关闭功能的话可以把配置中的 `enable` 项设定为 `false`,
81-
> 该配置只会影响强制关闭功能而不会停止事件分发

src/KillServer/kill_server/__init__.py

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,42 +15,81 @@
1515
PluginStoppingServerEvent = LiteralEvent("kill_server.plugin_stopping_server")
1616
WorldSavedEvent = LiteralEvent("kill_server.world_saved")
1717

18+
__all__ = ["ServerStoppingEvent", "PluginStoppingServerEvent", "WorldSavedEvent"]
19+
20+
is_world_saved: bool = False
21+
22+
23+
def on_server_startup(_server: PluginServerInterface):
24+
global is_world_saved
25+
is_world_saved = False
26+
27+
28+
@event_listener(WorldSavedEvent)
29+
def on_world_saved(_server: PluginServerInterface):
30+
global is_world_saved
31+
is_world_saved = True
32+
1833

19-
@event_listener(ServerStoppingEvent)
2034
@new_thread("KillServer")
21-
def force_kill_server():
35+
def force_kill_server(server: PluginServerInterface):
2236
"""强制关闭服务器"""
23-
if not config.enable:
24-
return
25-
26-
psi.logger.info("检测到服务器关闭命令执行, 等待服务器自动关闭")
37+
server.logger.info("检测到服务器关闭命令执行, 等待服务器自动关闭")
2738

2839
time.sleep(config.waiting_time)
29-
if not psi.is_server_running():
40+
if not server.is_server_running():
3041
return
31-
psi.logger.info("等待服务器关闭超时, 正在强制关闭服务器")
42+
server.logger.info("等待服务器关闭超时, 正在强制关闭服务器")
3243
# TODO: 检查世界是否保存
33-
psi.kill()
44+
if not is_world_saved:
45+
server.logger.warning("世界仍未保存完成, 建议增加等待时间")
46+
server.kill()
3447

3548

3649
def dispatch(event: PluginEvent):
3750
psi.dispatch_event(event, ())
3851

3952

40-
def on_load(server: PluginServerInterface, prev_module):
53+
def on_load(server: PluginServerInterface, _prev_module):
4154
global psi, config, handler
4255
psi = server
4356
config = server.load_config_simple(target_class=Config)
4457

45-
if prev_module is not None:
46-
prev_module.handler.remove()
58+
if not config.enable:
59+
server.logger.info("强制关闭功能已关闭")
60+
elif config.mcdr_only:
61+
server.logger.info("配置 mcdr_only 已启用")
62+
server.register_event_listener(PluginStoppingServerEvent, force_kill_server)
63+
else:
64+
server.register_event_listener(ServerStoppingEvent, force_kill_server)
4765

4866
# noinspection PyTypeChecker
4967
handler = when(server.stop, "return").do(lambda: dispatch(PluginStoppingServerEvent))
5068

5169

52-
def on_info(_server: PluginServerInterface, info: Info):
70+
def on_unload(_server: PluginServerInterface):
71+
handler.remove()
72+
73+
74+
def on_info(server: PluginServerInterface, info: Info):
5375
if re.fullmatch(r"Stopping the server", info.content):
5476
dispatch(ServerStoppingEvent)
77+
return
5578
if re.fullmatch(r".*All dimensions are saved", info.content):
5679
dispatch(WorldSavedEvent)
80+
return
81+
if any(
82+
i == "请按任意键继续. . . "
83+
for i in (info.raw_content, info.content)
84+
):
85+
msgs = [
86+
"检测到 pause 命令的输出",
87+
"请检查 MCDR 配置文件内的 start_command 配置项和(如果存在)启动脚本内有没有 pause 命令",
88+
"如果存在, 请尽快删除",
89+
"pause 引起的一些 issue:",
90+
"https://github.com/MCDReforged/MCDReforged/issues/394",
91+
"https://github.com/TISUnion/PrimeBackup/issues/85",
92+
]
93+
for msg in msgs:
94+
server.logger.critical(msg)
95+
return

src/KillServer/kill_server/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ class Config(Serializable):
1212
waiting_time: float = 60
1313
"""等待时间, 超时之后才强制关闭服务器, 单位为秒"""
1414

15+
mcdr_only: bool = False
16+
"""是否只监听由 MCDR 或插件调用 ``ServerInterface.stop()`` 引起的关闭"""
17+
1518
def validate_attribute(self, attr_name: str, attr_value: Any, **kwargs):
1619
if attr_name == "waiting_time":
1720
if attr_value <= 0:

src/KillServer/mcdreforged.plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "kill_server",
3-
"version": "0.1.2",
3+
"version": "1.0.0",
44
"name": "KillServer",
55
"description": {
66
"en_us": "Force to kill mc server",

0 commit comments

Comments
 (0)