nonebot-plugin-werewolf 1.1.10__py3-none-any.whl → 1.1.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nonebot_plugin_werewolf/__init__.py +1 -1
- nonebot_plugin_werewolf/config.py +57 -35
- nonebot_plugin_werewolf/constant.py +0 -19
- nonebot_plugin_werewolf/dead_channel.py +79 -0
- nonebot_plugin_werewolf/game.py +48 -117
- nonebot_plugin_werewolf/matchers/_prepare_game.py +223 -0
- nonebot_plugin_werewolf/matchers/depends.py +4 -4
- nonebot_plugin_werewolf/matchers/edit_behavior.py +2 -2
- nonebot_plugin_werewolf/matchers/edit_preset.py +20 -20
- nonebot_plugin_werewolf/matchers/message_in_game.py +5 -1
- nonebot_plugin_werewolf/matchers/poke/__init__.py +2 -1
- nonebot_plugin_werewolf/matchers/poke/chronocat_poke.py +7 -12
- nonebot_plugin_werewolf/matchers/poke/ob11_poke.py +8 -11
- nonebot_plugin_werewolf/matchers/start_game.py +23 -233
- nonebot_plugin_werewolf/matchers/superuser_ops.py +16 -12
- nonebot_plugin_werewolf/models.py +19 -0
- nonebot_plugin_werewolf/player.py +35 -31
- nonebot_plugin_werewolf/player_set.py +10 -0
- nonebot_plugin_werewolf/players/guard.py +2 -2
- nonebot_plugin_werewolf/players/prophet.py +2 -2
- nonebot_plugin_werewolf/players/shooter.py +2 -2
- nonebot_plugin_werewolf/players/werewolf.py +18 -19
- nonebot_plugin_werewolf/players/witch.py +4 -4
- nonebot_plugin_werewolf/utils.py +18 -56
- {nonebot_plugin_werewolf-1.1.10.dist-info → nonebot_plugin_werewolf-1.1.12.dist-info}/METADATA +122 -58
- nonebot_plugin_werewolf-1.1.12.dist-info/RECORD +37 -0
- {nonebot_plugin_werewolf-1.1.10.dist-info → nonebot_plugin_werewolf-1.1.12.dist-info}/WHEEL +1 -1
- nonebot_plugin_werewolf-1.1.10.dist-info/RECORD +0 -35
- {nonebot_plugin_werewolf-1.1.10.dist-info → nonebot_plugin_werewolf-1.1.12.dist-info}/licenses/LICENSE +0 -0
- {nonebot_plugin_werewolf-1.1.10.dist-info → nonebot_plugin_werewolf-1.1.12.dist-info}/top_level.txt +0 -0
@@ -5,23 +5,23 @@ from typing_extensions import override
|
|
5
5
|
import anyio
|
6
6
|
from nonebot_plugin_alconna.uniseg import UniMessage
|
7
7
|
|
8
|
-
from ..
|
8
|
+
from ..config import stop_command_prompt
|
9
|
+
from ..constant import STOP_COMMAND
|
9
10
|
from ..models import Role, RoleGroup
|
10
11
|
from ..player import InteractProvider, NotifyProvider, Player
|
11
|
-
from ..utils import
|
12
|
+
from ..utils import as_player_set, check_index
|
12
13
|
|
13
14
|
if TYPE_CHECKING:
|
14
15
|
from ..player_set import PlayerSet
|
15
16
|
|
16
17
|
|
17
18
|
class WerewolfInteractProvider(InteractProvider["Werewolf"]):
|
18
|
-
stream: ObjectStream[str | UniMessage]
|
19
|
-
|
20
19
|
@override
|
21
20
|
async def before(self) -> None:
|
22
21
|
self.game.state.werewolf_start()
|
23
22
|
|
24
23
|
async def handle_interact(self, players: "PlayerSet") -> None:
|
24
|
+
stream = self.stream[0]
|
25
25
|
self.selected = None
|
26
26
|
|
27
27
|
while True:
|
@@ -32,30 +32,31 @@ class WerewolfInteractProvider(InteractProvider["Werewolf"]):
|
|
32
32
|
self.selected = players[index - 1]
|
33
33
|
msg = f"当前选择玩家: {self.selected.name}"
|
34
34
|
await self.p.send(
|
35
|
-
f"🎯{msg}\n发送 “{stop_command_prompt
|
35
|
+
f"🎯{msg}\n发送 “{stop_command_prompt}” 结束回合",
|
36
36
|
stop_btn_label="结束回合",
|
37
37
|
select_players=players,
|
38
38
|
)
|
39
|
-
await
|
39
|
+
await stream.send(f"📝队友 {self.p.name} {msg}")
|
40
40
|
if text == STOP_COMMAND:
|
41
41
|
if self.selected is not None:
|
42
42
|
await self.p.send("✅你已结束当前回合")
|
43
|
-
await
|
44
|
-
|
43
|
+
await stream.send(f"📝队友 {self.p.name} 结束当前回合")
|
44
|
+
stream.close()
|
45
45
|
return
|
46
46
|
await self.p.send(
|
47
47
|
"⚠️当前未选择玩家,无法结束回合",
|
48
48
|
select_players=players,
|
49
49
|
)
|
50
50
|
else:
|
51
|
-
await
|
51
|
+
await stream.send(
|
52
52
|
UniMessage.text(f"💬队友 {self.p.name}:\n") + input_msg
|
53
53
|
)
|
54
54
|
|
55
55
|
async def handle_broadcast(self, partners: "PlayerSet") -> None:
|
56
|
-
|
56
|
+
stream = self.stream[1]
|
57
|
+
while True:
|
57
58
|
try:
|
58
|
-
message = await
|
59
|
+
message = await stream.receive()
|
59
60
|
except anyio.EndOfStream:
|
60
61
|
return
|
61
62
|
|
@@ -77,19 +78,17 @@ class WerewolfInteractProvider(InteractProvider["Werewolf"]):
|
|
77
78
|
msg.text("💫请选择今晚的目标:\n")
|
78
79
|
.text(players.show())
|
79
80
|
.text("\n\n🔪发送编号选择玩家")
|
80
|
-
.text(f"\n❌发送 “{stop_command_prompt
|
81
|
+
.text(f"\n❌发送 “{stop_command_prompt}” 结束回合")
|
81
82
|
.text("\n\n⚠️意见未统一将空刀"),
|
82
83
|
select_players=players,
|
83
84
|
)
|
84
85
|
|
85
|
-
self.stream =
|
86
|
+
self.stream = anyio.create_memory_object_stream[str | UniMessage](8)
|
87
|
+
send, recv = self.stream
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
tg.start_soon(self.handle_broadcast, partners)
|
91
|
-
finally:
|
92
|
-
del self.stream
|
89
|
+
async with send, recv, anyio.create_task_group() as tg:
|
90
|
+
tg.start_soon(self.handle_interact, players)
|
91
|
+
tg.start_soon(self.handle_broadcast, partners)
|
93
92
|
|
94
93
|
async def finalize(self) -> None:
|
95
94
|
w = self.game.players.alive().select(RoleGroup.WEREWOLF)
|
@@ -2,7 +2,7 @@ from typing_extensions import override
|
|
2
2
|
|
3
3
|
from nonebot_plugin_alconna.uniseg import UniMessage
|
4
4
|
|
5
|
-
from ..
|
5
|
+
from ..config import stop_command_prompt
|
6
6
|
from ..models import Role, RoleGroup
|
7
7
|
from ..player import InteractProvider, Player
|
8
8
|
from ..utils import as_player_set
|
@@ -28,7 +28,7 @@ class WitchInteractProvider(InteractProvider["Witch"]):
|
|
28
28
|
await self.p.send(msg.text("⚙️你已经用过解药了"))
|
29
29
|
return False
|
30
30
|
|
31
|
-
msg.text(f"✏️使用解药请发送 “1”\n❌不使用解药请发送 “{stop_command_prompt
|
31
|
+
msg.text(f"✏️使用解药请发送 “1”\n❌不使用解药请发送 “{stop_command_prompt}”")
|
32
32
|
await self.p.send(
|
33
33
|
msg,
|
34
34
|
stop_btn_label="不使用解药",
|
@@ -38,7 +38,7 @@ class WitchInteractProvider(InteractProvider["Witch"]):
|
|
38
38
|
if not await self.p.select_player(
|
39
39
|
as_player_set(killed),
|
40
40
|
on_stop=f"ℹ️你选择不对 {killed.name} 使用解药",
|
41
|
-
on_index_error=f"⚠️输入错误: 请输入 “1” 或 “{stop_command_prompt
|
41
|
+
on_index_error=f"⚠️输入错误: 请输入 “1” 或 “{stop_command_prompt}”",
|
42
42
|
stop_btn_label="不使用解药",
|
43
43
|
):
|
44
44
|
return False
|
@@ -64,7 +64,7 @@ class WitchInteractProvider(InteractProvider["Witch"]):
|
|
64
64
|
"玩家列表:\n"
|
65
65
|
f"{players.show()}\n\n"
|
66
66
|
"🧪发送玩家编号使用毒药\n"
|
67
|
-
f"❌发送 “{stop_command_prompt
|
67
|
+
f"❌发送 “{stop_command_prompt}” 结束回合(不使用药水)",
|
68
68
|
stop_btn_label="结束回合",
|
69
69
|
select_players=players,
|
70
70
|
)
|
nonebot_plugin_werewolf/utils.py
CHANGED
@@ -6,7 +6,6 @@ from collections.abc import Iterable
|
|
6
6
|
from typing import TYPE_CHECKING, Any, ClassVar, Generic, ParamSpec, TypeVar
|
7
7
|
|
8
8
|
import anyio
|
9
|
-
import anyio.streams.memory
|
10
9
|
from nonebot.adapters import Bot, Event
|
11
10
|
from nonebot.internal.matcher import current_bot
|
12
11
|
from nonebot_plugin_alconna.uniseg import (
|
@@ -19,8 +18,8 @@ from nonebot_plugin_alconna.uniseg import (
|
|
19
18
|
)
|
20
19
|
from nonebot_plugin_uninfo import Session
|
21
20
|
|
22
|
-
from .config import config
|
23
|
-
from .constant import STOP_COMMAND
|
21
|
+
from .config import config, stop_command_prompt
|
22
|
+
from .constant import STOP_COMMAND
|
24
23
|
|
25
24
|
if TYPE_CHECKING:
|
26
25
|
from .player import Player
|
@@ -118,55 +117,7 @@ def as_player_set(*player: "Player") -> "PlayerSet":
|
|
118
117
|
return cached_player_set()(player)
|
119
118
|
|
120
119
|
|
121
|
-
|
122
|
-
class Unset: ...
|
123
|
-
|
124
|
-
__UNSET: ClassVar[Unset] = Unset()
|
125
|
-
|
126
|
-
_send: anyio.streams.memory.MemoryObjectSendStream[T]
|
127
|
-
_recv: anyio.streams.memory.MemoryObjectReceiveStream[T]
|
128
|
-
_closed: anyio.Event
|
129
|
-
|
130
|
-
def __init__(self, max_buffer_size: float = 0) -> None:
|
131
|
-
self._send, self._recv = anyio.create_memory_object_stream(max_buffer_size)
|
132
|
-
self._closed = anyio.Event()
|
133
|
-
|
134
|
-
async def send(self, obj: T) -> None:
|
135
|
-
await self._send.send(obj)
|
136
|
-
|
137
|
-
async def recv(self) -> T:
|
138
|
-
result: Any = self.__UNSET
|
139
|
-
|
140
|
-
async def _recv() -> None:
|
141
|
-
nonlocal result
|
142
|
-
result = await self._recv.receive()
|
143
|
-
tg.cancel_scope.cancel()
|
144
|
-
|
145
|
-
async def _cancel() -> None:
|
146
|
-
await self._closed.wait()
|
147
|
-
tg.cancel_scope.cancel()
|
148
|
-
|
149
|
-
async with anyio.create_task_group() as tg:
|
150
|
-
tg.start_soon(_recv)
|
151
|
-
tg.start_soon(_cancel)
|
152
|
-
|
153
|
-
if result is self.__UNSET:
|
154
|
-
raise anyio.EndOfStream
|
155
|
-
|
156
|
-
return result
|
157
|
-
|
158
|
-
def close(self) -> None:
|
159
|
-
self._closed.set()
|
160
|
-
|
161
|
-
@property
|
162
|
-
def closed(self) -> bool:
|
163
|
-
return self._closed.is_set()
|
164
|
-
|
165
|
-
async def wait_closed(self) -> None:
|
166
|
-
await self._closed.wait()
|
167
|
-
|
168
|
-
|
169
|
-
def _btn(label: str, text: str, /) -> Button:
|
120
|
+
def btn(label: str, text: str, /) -> Button:
|
170
121
|
return Button(flag="input", label=label, text=text)
|
171
122
|
|
172
123
|
|
@@ -174,8 +125,8 @@ def add_stop_button(msg: str | UniMessage, label: str | None = None) -> UniMessa
|
|
174
125
|
if isinstance(msg, str):
|
175
126
|
msg = UniMessage.text(msg)
|
176
127
|
|
177
|
-
stop = stop_command_prompt
|
178
|
-
return msg.keyboard(
|
128
|
+
stop = stop_command_prompt
|
129
|
+
return msg.keyboard(btn(label or stop, stop))
|
179
130
|
|
180
131
|
|
181
132
|
def add_players_button(msg: str | UniMessage, players: "PlayerSet") -> UniMessage:
|
@@ -184,7 +135,7 @@ def add_players_button(msg: str | UniMessage, players: "PlayerSet") -> UniMessag
|
|
184
135
|
|
185
136
|
it = enumerate(players, 1)
|
186
137
|
while line := tuple(itertools.islice(it, 3)):
|
187
|
-
msg.keyboard(*(
|
138
|
+
msg.keyboard(*(btn(p.name, str(i)) for i, p in line))
|
188
139
|
return msg
|
189
140
|
|
190
141
|
|
@@ -207,6 +158,15 @@ class SendHandler(abc.ABC, Generic[P]):
|
|
207
158
|
self.bot = bot or current_bot.get()
|
208
159
|
self.target = target
|
209
160
|
|
161
|
+
@functools.cached_property
|
162
|
+
def _is_dc(self) -> bool:
|
163
|
+
try:
|
164
|
+
from nonebot.adapters.discord import Bot
|
165
|
+
except ImportError:
|
166
|
+
return False
|
167
|
+
|
168
|
+
return isinstance(self.bot, Bot)
|
169
|
+
|
210
170
|
async def _edit(self) -> None:
|
211
171
|
last = self.last_receipt
|
212
172
|
if (
|
@@ -214,6 +174,7 @@ class SendHandler(abc.ABC, Generic[P]):
|
|
214
174
|
and self.last_msg is not None
|
215
175
|
and last is not None
|
216
176
|
and last.editable
|
177
|
+
and not self._is_dc
|
217
178
|
):
|
218
179
|
await last.edit(self.last_msg.exclude(Keyboard))
|
219
180
|
|
@@ -221,7 +182,8 @@ class SendHandler(abc.ABC, Generic[P]):
|
|
221
182
|
if self.target is None:
|
222
183
|
raise RuntimeError("Target cannot be None when sending a message.")
|
223
184
|
|
224
|
-
if not config.enable_button:
|
185
|
+
if not config.enable_button or self._is_dc:
|
186
|
+
# TODO: support discord button
|
225
187
|
message = message.exclude(Keyboard)
|
226
188
|
receipt = await message.send(
|
227
189
|
target=self.target,
|
{nonebot_plugin_werewolf-1.1.10.dist-info → nonebot_plugin_werewolf-1.1.12.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nonebot-plugin-werewolf
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.12
|
4
4
|
Summary: 适用于 Nonebot2 的狼人杀插件
|
5
5
|
Author-email: wyf7685 <wyf7685@163.com>
|
6
6
|
License: MIT
|
@@ -10,11 +10,11 @@ Project-URL: bug-tracker, https://github.com/wyf7685/nonebot-plugin-werewolf/iss
|
|
10
10
|
Requires-Python: >=3.10
|
11
11
|
Description-Content-Type: text/markdown
|
12
12
|
License-File: LICENSE
|
13
|
-
Requires-Dist: nonebot2>=2.
|
14
|
-
Requires-Dist: nonebot-plugin-alconna>=0.
|
13
|
+
Requires-Dist: nonebot2>=2.4.0
|
14
|
+
Requires-Dist: nonebot-plugin-alconna>=0.58.0
|
15
15
|
Requires-Dist: nonebot-plugin-localstore>=0.7.1
|
16
|
-
Requires-Dist: nonebot-plugin-uninfo>=0.
|
17
|
-
Requires-Dist: nonebot-plugin-waiter>=0.
|
16
|
+
Requires-Dist: nonebot-plugin-uninfo>=0.8.0
|
17
|
+
Requires-Dist: nonebot-plugin-waiter>=0.8.0
|
18
18
|
Requires-Dist: anyio>=4.6.0
|
19
19
|
Dynamic: license-file
|
20
20
|
|
@@ -39,7 +39,8 @@ _✨ 简单的狼人杀插件 ✨_
|
|
39
39
|
[](https://results.pre-commit.ci/latest/github/wyf7685/nonebot-plugin-werewolf/master)
|
40
40
|
[](https://github.com/wyf7685/nonebot-plugin-werewolf/actions/workflows/lint.yml)
|
41
41
|
|
42
|
-
<!-- https://github.com/lgc2333/nonebot-registry-badge -->
|
42
|
+
<!-- ref: https://github.com/lgc2333/nonebot-registry-badge -->
|
43
|
+
|
43
44
|
[](https://registry.nonebot.dev/plugin/nonebot-plugin-werewolf:nonebot_plugin_werewolf)
|
44
45
|
[](https://registry.nonebot.dev/plugin/nonebot-plugin-werewolf:nonebot_plugin_werewolf)
|
45
46
|
|
@@ -49,11 +50,26 @@ _✨ 简单的狼人杀插件 ✨_
|
|
49
50
|
|
50
51
|
和朋友们来一场紧张刺激的狼人杀游戏
|
51
52
|
|
53
|
+
<!-- ref: https://github.com/KomoriDev/Starify -->
|
54
|
+
|
55
|
+
> [!IMPORTANT]
|
56
|
+
> **收藏项目**,你将从 GitHub 上无延迟地接收所有发布通知~⭐️
|
57
|
+
|
58
|
+
<img width="100%" src="https://starify.komoridevs.icu/api/starify?owner=wyf7685&repo=nonebot-plugin-werewolf" alt="starify" />
|
59
|
+
|
60
|
+
<details>
|
61
|
+
<summary><kbd>Star History</kbd></summary>
|
62
|
+
<picture>
|
63
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=wyf7685/nonebot-plugin-werewolf&theme=dark&type=Date" />
|
64
|
+
<img width="100%" src="https://star-history.com/#wyf7685/nonebot-plugin-werewolf&Date" />
|
65
|
+
</picture>
|
66
|
+
</details>
|
67
|
+
|
52
68
|
## 💿 安装
|
53
69
|
|
54
70
|
> [!note]
|
55
71
|
>
|
56
|
-
> 请确保 NoneBot2 使用的 Python 解释器版本 >=3.10
|
72
|
+
> 请确保 [NoneBot2](https://nonebot.dev/) 使用的 Python 解释器版本 >=3.10
|
57
73
|
|
58
74
|
<details open>
|
59
75
|
<summary>使用 nb-cli 安装</summary>
|
@@ -65,12 +81,14 @@ _✨ 简单的狼人杀插件 ✨_
|
|
65
81
|
|
66
82
|
<details>
|
67
83
|
<summary>使用包管理器安装</summary>
|
84
|
+
<!-- 会用包管理器的用户真的需要这节吗 -->
|
85
|
+
|
68
86
|
在 nonebot2 项目的插件目录下, 打开命令行, 根据你使用的包管理器, 输入相应的安装命令
|
69
87
|
|
70
|
-
<details>
|
71
|
-
<summary>
|
88
|
+
<details open>
|
89
|
+
<summary>uv</summary>
|
72
90
|
|
73
|
-
|
91
|
+
uv add nonebot-plugin-werewolf
|
74
92
|
|
75
93
|
</details>
|
76
94
|
<details>
|
@@ -90,6 +108,12 @@ _✨ 简单的狼人杀插件 ✨_
|
|
90
108
|
|
91
109
|
conda install nonebot-plugin-werewolf
|
92
110
|
|
111
|
+
</details>
|
112
|
+
<details>
|
113
|
+
<summary>pip</summary>
|
114
|
+
|
115
|
+
pip install nonebot-plugin-werewolf
|
116
|
+
|
93
117
|
</details>
|
94
118
|
|
95
119
|
打开 nonebot2 项目根目录下的 `pyproject.toml` 文件, 在 `[tool.nonebot]` 部分追加写入
|
@@ -102,17 +126,41 @@ _✨ 简单的狼人杀插件 ✨_
|
|
102
126
|
|
103
127
|
在 nonebot2 项目的 `.env` 文件中添加如下配置:
|
104
128
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
129
|
+
| 配置项 | 必填 | 默认值 | 类型 | 说明 |
|
130
|
+
| :--------------------------: | :--: | :-----: | :-----------------------: | :----------------------------: |
|
131
|
+
| `werewolf__enable_poke` | 否 | `True` | `bool` | 是否使用戳一戳简化操作流程 |
|
132
|
+
| `werewolf__enable_button` | 否 | `False` | `bool` | 是否在交互中添加按钮 |
|
133
|
+
| `werewolf__stop_command` | 否 | `stop` | `str \| set[str]` | 修改游戏进程中的 `stop` 命令 |
|
134
|
+
| `werewolf__require_at` | 否 | `True` | `bool \| RequireAtConfig` | 部分命令是否需要 at 机器人触发 |
|
135
|
+
| `werewolf__matcher_priority` | 否 | - | `MatcherPriorityConfig` | 配置插件 matcher 注册的优先级 |
|
110
136
|
|
111
137
|
`werewolf__enable_poke` 仅在 `OneBot V11` 适配器 / `Satori/chronocat` 下生效
|
112
138
|
|
113
|
-
`werewolf__enable_button` 仅在 `Telegram`
|
139
|
+
`werewolf__enable_button` 仅在 `Telegram` 适配器下通过测试,不保证在其他适配器的可用性,如有疑问欢迎提出。
|
114
140
|
|
115
|
-
|
141
|
+
<details>
|
142
|
+
<summary> werewolf__require_at 示例 </summary>
|
143
|
+
|
144
|
+
```ini
|
145
|
+
# 所有命令均需 at 触发
|
146
|
+
werewolf__require_at=true
|
147
|
+
|
148
|
+
# 所有命令均不需 at 触发
|
149
|
+
werewolf__require_at=false
|
150
|
+
|
151
|
+
# 狼人杀命令需要 at, 中止游戏命令不需要 at
|
152
|
+
werewolf__require_at='{"start": true, "terminate": false}'
|
153
|
+
```
|
154
|
+
|
155
|
+
</details>
|
156
|
+
|
157
|
+
`werewolf__matcher_priority` 的 matcher 优先级参考 [官方文档](https://nonebot.dev/docs/advanced/matcher#%E5%93%8D%E5%BA%94%E4%BC%98%E5%85%88%E7%BA%A7)
|
158
|
+
|
159
|
+
- 一般情况下不需要修改此配置, 插件的默认优先级可以参考 [这里](./nonebot_plugin_werewolf/config.py) 的 `MatcherPriorityConfig`
|
160
|
+
- 如果遇到与其他插件的命令冲突, 可考虑修改此处的优先级配置
|
161
|
+
- 配置应填入 JSON 对象, 可用键: `start` `terminate` `preset` `behavior` `in_game` `stop`
|
162
|
+
|
163
|
+
## 🚀 使用
|
116
164
|
|
117
165
|
> [!note]
|
118
166
|
>
|
@@ -133,32 +181,33 @@ _✨ 简单的狼人杀插件 ✨_
|
|
133
181
|
|
134
182
|
</details>
|
135
183
|
|
136
|
-
### 指令表
|
184
|
+
### 📋 指令表
|
137
185
|
|
138
|
-
| 指令 | 权限 | 需要@ |
|
139
|
-
| :-----------------: | :-----------------: | :---: |
|
140
|
-
| `werewolf`/`狼人杀` | 群员 | 是 |
|
141
|
-
| `开始游戏` | 游戏发起者 | 否 | 群聊
|
142
|
-
| `结束游戏` | 游戏发起者/超级用户 | 否 | 群聊
|
143
|
-
| `当前玩家` | 群员 | 否 | 群聊
|
144
|
-
| `加入游戏` | 群员 | 否 | 群聊
|
145
|
-
| `退出游戏` | 群员 | 否 | 群聊
|
146
|
-
| `中止游戏` | 超级用户 | 是 |
|
147
|
-
| `狼人杀预设` | 超级用户 | 否 |
|
148
|
-
| `狼人杀配置` | 超级用户 | 否 |
|
186
|
+
| 指令 | 权限 | 需要@ | 范围 | 说明 |
|
187
|
+
| :-----------------: | :-----------------: | :---: | :---------------: | :--------------------------: |
|
188
|
+
| `werewolf`/`狼人杀` | 群员 | 是 | 群聊 _[游戏外]_ | 发起游戏 (进入准备阶段) |
|
189
|
+
| `开始游戏` | 游戏发起者 | 否 | 群聊 _[准备阶段]_ | 游戏发起者开始游戏 |
|
190
|
+
| `结束游戏` | 游戏发起者/超级用户 | 否 | 群聊 _[准备阶段]_ | 游戏发起者/超级用户 结束游戏 |
|
191
|
+
| `当前玩家` | 群员 | 否 | 群聊 _[准备阶段]_ | 列出参与游戏的玩家列表 |
|
192
|
+
| `加入游戏` | 群员 | 否 | 群聊 _[准备阶段]_ | 玩家加入游戏 |
|
193
|
+
| `退出游戏` | 群员 | 否 | 群聊 _[准备阶段]_ | 玩家退出游戏 |
|
194
|
+
| `中止游戏` | 超级用户 | 是 | 群聊 _[游戏内]_ | 超级用户强制中止游戏 |
|
195
|
+
| `狼人杀预设` | 超级用户 | 否 | 任意 _[游戏外]_ | 超级用户编辑游戏预设 |
|
196
|
+
| `狼人杀配置` | 超级用户 | 否 | 任意 _[游戏外]_ | 超级用户编辑游戏配置 |
|
149
197
|
|
150
|
-
|
198
|
+
- `超级用户` 为 nonebot2 配置项中的 `SUPERUSERS`, 配置说明参考 [官方文档](https://nonebot.dev/docs/appendices/config#superusers)
|
151
199
|
|
152
|
-
|
200
|
+
- 发起游戏时添加 `restart`/`重开`, 可加载上一次游戏的玩家列表, 快速发起游戏。例: `werewolf restart`/`狼人杀 重开`
|
153
201
|
|
154
|
-
|
202
|
+
- `狼人杀预设` 命令用法可通过 `狼人杀预设 --help` 获取,或参考 [游戏内容](#游戏内容) 部分的介绍
|
155
203
|
|
156
|
-
|
204
|
+
- `狼人杀配置` 命令用法可通过 `狼人杀预设 --help` 获取
|
157
205
|
|
158
|
-
|
206
|
+
- 对于 `OneBot V11` 适配器和 `Satori` 适配器的 `chronocat`, 启用配置项 `werewolf__enable_poke` 后, 可以使用戳一戳代替 _准备阶段_ 的 `加入游戏` 操作 和 游戏内的 `stop` 命令
|
159
207
|
|
208
|
+
- _其他交互参考游戏内提示_
|
160
209
|
|
161
|
-
### 游戏内容
|
210
|
+
### 🎭 游戏内容
|
162
211
|
|
163
212
|
> [!note]
|
164
213
|
>
|
@@ -169,23 +218,23 @@ _✨ 简单的狼人杀插件 ✨_
|
|
169
218
|
插件中保存了一份 [职业预设](./nonebot_plugin_werewolf/constant.py), 内容如下
|
170
219
|
|
171
220
|
| 总人数 | 狼人 | 神职 | 平民 |
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
221
|
+
| :----: | :--: | :--: | :--: |
|
222
|
+
| 6 | 1 | 2 | 3 |
|
223
|
+
| 7 | 2 | 2 | 3 |
|
224
|
+
| 8 | 2 | 3 | 3 |
|
225
|
+
| 9 | 2 | 4 | 3 |
|
226
|
+
| 10 | 3 | 4 | 3 |
|
227
|
+
| 11 | 3 | 5 | 3 |
|
228
|
+
| 12 | 4 | 5 | 3 |
|
180
229
|
|
181
230
|
职业预设可以通过命令 `狼人杀预设 职业 ...` 修改
|
182
231
|
|
183
232
|
<details>
|
184
233
|
<summary>示例</summary>
|
185
234
|
|
186
|
-
|
235
|
+
- 命令: `狼人杀预设 职业 6 1 3 2`
|
187
236
|
|
188
|
-
|
237
|
+
- 上述命令指定当总人数为 6 时,狼人、神职、平民的数量分别为 1、3、2
|
189
238
|
|
190
239
|
</details>
|
191
240
|
<br/>
|
@@ -202,36 +251,42 @@ _✨ 简单的狼人杀插件 ✨_
|
|
202
251
|
|
203
252
|
#### 命令 `狼人杀预设 狼人`
|
204
253
|
|
205
|
-
|
254
|
+
- 命令: `狼人杀预设 狼人 狼 狼王 狼 狼`
|
206
255
|
|
207
|
-
|
256
|
+
- 上述命令指定狼人的职业优先级为 `狼人`, `狼王`, `狼人`, `狼人`
|
208
257
|
|
209
258
|
#### 命令 `狼人杀预设 神职`
|
210
259
|
|
211
|
-
|
260
|
+
- 命令: `狼人杀预设 神职 预言家 女巫 猎人 守卫 白痴`
|
212
261
|
|
213
|
-
|
262
|
+
- 上述命令指定神职的职业优先级为 `预言家`, `女巫`, `猎人`, `守卫`, `白痴`
|
214
263
|
|
215
264
|
> [!note]
|
216
265
|
>
|
217
|
-
> 以上两条命令均支持交互式输入
|
266
|
+
> 以上两条命令均支持交互式输入 ~~waiter 真好用~~
|
218
267
|
>
|
219
268
|
> 例:向机器人发送命令 `狼人杀预设 狼人`,在接下来的一条消息中发送 `狼人 狼王 狼人 狼人`
|
220
269
|
>
|
221
270
|
> 其效果等同于以上描述中的单条命令 `狼人杀预设 狼人 狼人 狼王 狼人 狼人`
|
222
271
|
|
223
272
|
</details>
|
224
|
-
<br/>
|
225
273
|
|
226
|
-
对于 `小丑` 职业,当预设中的平民数量大于或等于 2 时,将有
|
274
|
+
对于 `小丑` 职业,当预设中的平民数量大于或等于 2 时,将有 _一定概率_ 将其中一个平民替换为小丑。
|
227
275
|
|
228
276
|
小丑属于第三方阵营,胜利条件为在投票阶段被票出,在预言家查验及游戏进程判断时视作平民。
|
229
277
|
|
230
278
|
小丑生成概率可以通过命令 `狼人杀预设 小丑 <概率>` 设置,默认值为 0 (不生成小丑)。
|
231
279
|
|
232
|
-
### 已知问题
|
280
|
+
### 🔧 已知问题
|
233
281
|
|
234
|
-
|
282
|
+
<details>
|
283
|
+
<summary>已知问题</summary>
|
284
|
+
|
285
|
+
- 截止 chronocat [v0.2.19](https://github.com/chrononeko/chronocat/tree/v0.2.19), 调用 [`guild.member.get`](https://github.com/chrononeko/chronocat/blob/8558ad9ff4319395d86abbfda22136939bf66780/packages/engine-chronocat-api/src/api/guild/member/get.ts) / [`user.get`](https://github.com/chrononeko/chronocat/blob/8558ad9ff4319395d86abbfda22136939bf66780/packages/engine-chronocat-api/src/api/user/get.ts) 均无法获取用户名,这将导致在交互过程中的玩家名显示为用户 ID
|
286
|
+
|
287
|
+
- v1.1.6 添加的按钮操作在 `discord` 适配器中不可用, 已在 v1.1.12 禁用 (2e31d43)
|
288
|
+
|
289
|
+
</details>
|
235
290
|
|
236
291
|
## 📝 更新日志
|
237
292
|
|
@@ -240,16 +295,25 @@ _✨ 简单的狼人杀插件 ✨_
|
|
240
295
|
|
241
296
|
<!-- CHANGELOG -->
|
242
297
|
|
298
|
+
- 2025.06.01 v1.1.12
|
299
|
+
|
300
|
+
- 禁用 `discord` 适配器中的按钮操作 ~~以后会写适配的...吗?~~
|
301
|
+
|
302
|
+
- 2025.04.20 v1.1.11
|
303
|
+
|
304
|
+
- 添加配置项 `werewolf__require_at`, 用于配置命令是否需要 at 机器人触发
|
305
|
+
- 添加配置项 `werewolf__matcher_priority`, 用于配置插件 matcher 注册优先级
|
306
|
+
|
243
307
|
- 2025.04.17 v1.1.10
|
244
308
|
|
245
309
|
- 添加狼人多选目标配置项显示
|
246
|
-
- 在游戏开始时打乱并固定轮流发言模式的发言顺序
|
310
|
+
- 在游戏开始时打乱并固定轮流发言模式的发言顺序 (#20)
|
247
311
|
|
248
312
|
- 2025.04.15 v1.1.9
|
249
313
|
|
250
314
|
- 添加游戏行为配置 `werewolf_multi_select`
|
251
315
|
- 重构玩家类
|
252
|
-
- 添加轮流发言模式缺失的 at 消息段
|
316
|
+
- 添加轮流发言模式缺失的 at 消息段 (#19)
|
253
317
|
|
254
318
|
- 2025.02.13 v1.1.8
|
255
319
|
|
@@ -259,7 +323,7 @@ _✨ 简单的狼人杀插件 ✨_
|
|
259
323
|
|
260
324
|
- 2024.10.31 v1.1.7
|
261
325
|
|
262
|
-
-
|
326
|
+
- _Bug fix_
|
263
327
|
|
264
328
|
- 2024.10.31 v1.1.6
|
265
329
|
|
@@ -319,7 +383,7 @@ _✨ 简单的狼人杀插件 ✨_
|
|
319
383
|
|
320
384
|
</details>
|
321
385
|
|
322
|
-
## 鸣谢
|
386
|
+
## 🎉 鸣谢
|
323
387
|
|
324
388
|
- [`nonebot/nonebot2`](https://github.com/nonebot/nonebot2): 跨平台 Python 异步机器人框架
|
325
389
|
- [`nonebot/plugin-alconna`](https://github.com/nonebot/plugin-alconna): 跨平台的消息处理接口
|
@@ -0,0 +1,37 @@
|
|
1
|
+
nonebot_plugin_werewolf/__init__.py,sha256=i29POIWhdp2Ev3yu8Q5IFgxEi8jYTqsVbSY1IuggAew,932
|
2
|
+
nonebot_plugin_werewolf/config.py,sha256=EVitkkXL4Dv_LfePjknCa2uoeYt-e6aw_CRzTMbaEhQ,3736
|
3
|
+
nonebot_plugin_werewolf/constant.py,sha256=DqGgUfzsXt1Ls0tTHSSaYrUOZNuv6lgjfhfvdLR5DoM,1641
|
4
|
+
nonebot_plugin_werewolf/dead_channel.py,sha256=Dzs9E-jU_alZgCnZzFbvJwgIXrSHSxyNy1yLb_6-0Oo,2720
|
5
|
+
nonebot_plugin_werewolf/exception.py,sha256=SP9RdzsREB6PtpRfhZjxqybtvO0aw48hpN9QMU9jDZY,366
|
6
|
+
nonebot_plugin_werewolf/game.py,sha256=MsntnifA5zn1VxLDvPAsVRSaM7cm2dtj7IvFWwnabCA,17152
|
7
|
+
nonebot_plugin_werewolf/models.py,sha256=D_ajiDllT3WUhLxK1XlTpqBEr7fyLdszX422wgJ_7JM,2739
|
8
|
+
nonebot_plugin_werewolf/player.py,sha256=mrORov_uZhOSLe9IwdQH_64mwvBGYt0FPHHR4XkzcCY,11309
|
9
|
+
nonebot_plugin_werewolf/player_set.py,sha256=S2To4-YW-Geh-Jrol6IsqIvJmf5a7lNGMl4rlngD3Gc,3375
|
10
|
+
nonebot_plugin_werewolf/utils.py,sha256=V3JcguIHFxyOhkGE4vbc5Sd5g4oJAzxs69bLHuO-v-A,6142
|
11
|
+
nonebot_plugin_werewolf/matchers/__init__.py,sha256=lQ9AZDEWgtbP-W8KWvjkEYc_UfTHSUwjaGdZ7PT3z0E,219
|
12
|
+
nonebot_plugin_werewolf/matchers/_prepare_game.py,sha256=Cmzffbo79ecIJFzhTeOY8isOK7mvVJZr02AV7Zt-aBE,7855
|
13
|
+
nonebot_plugin_werewolf/matchers/depends.py,sha256=DVc9Ewzja9ywJ8MyYxST8pnfpVNJhLXafhbZhEMuxt8,1350
|
14
|
+
nonebot_plugin_werewolf/matchers/edit_behavior.py,sha256=8gTSnvJNqKGjmOts_5zYR4f5Qn-NxUlAvUsOCk6LYDw,7262
|
15
|
+
nonebot_plugin_werewolf/matchers/edit_preset.py,sha256=DXd5v9TtpwCGxqhivUgz2AqwXSE9evE0lc2Z7OrEjV8,8056
|
16
|
+
nonebot_plugin_werewolf/matchers/message_in_game.py,sha256=xpnUanxa-reVlaXnwBTwfoDWQc-MhsMq03tHFKjeEkQ,1052
|
17
|
+
nonebot_plugin_werewolf/matchers/start_game.py,sha256=fYOPdxnE9xe9wr8tSecvypXF-ZwqZnNPNyNH2x8M7ws,4069
|
18
|
+
nonebot_plugin_werewolf/matchers/superuser_ops.py,sha256=KLl1cJHogk3DAtEXfu_r-iqA6kggwE5lNVPuyZNyHos,833
|
19
|
+
nonebot_plugin_werewolf/matchers/poke/__init__.py,sha256=LhWYvAYZsmJbnYMFj7Q032pvq5_P6FYRCzvnwuBvsb0,272
|
20
|
+
nonebot_plugin_werewolf/matchers/poke/chronocat_poke.py,sha256=FEelbSnx8-44K3G24Zv059fxei1MjrnZaaUtlTUb7lc,3934
|
21
|
+
nonebot_plugin_werewolf/matchers/poke/ob11_poke.py,sha256=fnRiy7INcz0Y_Awqd-J0wW2taXABHIDUfluE9rgAzw8,2542
|
22
|
+
nonebot_plugin_werewolf/players/__init__.py,sha256=lDHCYkk6h_1Bl9DKIqF6vPAcLXNhCGlxBFQzPH4NvUQ,345
|
23
|
+
nonebot_plugin_werewolf/players/civilian.py,sha256=Y6A5yB74Ckn_U0vAOoRJhpwhm3MyG6m47TalQ2mjhtw,151
|
24
|
+
nonebot_plugin_werewolf/players/guard.py,sha256=D_1GqnL_EBYCOERQ6xVaargG_t-RKHyUbnuw_5gw-j4,1350
|
25
|
+
nonebot_plugin_werewolf/players/hunter.py,sha256=iYeM2srPaoncBrft2LRuyNVUeGyeBF-rs0BAHl7RP7s,228
|
26
|
+
nonebot_plugin_werewolf/players/idiot.py,sha256=OfbLuSLhXNJueB9IYheNT7OpenqaFQjKaAKBlOH3hE0,1659
|
27
|
+
nonebot_plugin_werewolf/players/jester.py,sha256=aErVfQS30hS0t2KiQSNFfTHmC2_hqtaHdQvQ4U1Ts_Y,1016
|
28
|
+
nonebot_plugin_werewolf/players/prophet.py,sha256=U4piex-QpI_GaDbJsp9hNyuMHLmvhaPCezKiSKhRhKA,1080
|
29
|
+
nonebot_plugin_werewolf/players/shooter.py,sha256=XtTKspxodeqYwnxtBIwmgxaQEDXcfCuPLrM3WefawLc,1942
|
30
|
+
nonebot_plugin_werewolf/players/werewolf.py,sha256=M-_OZ_E2drx7I0G7Ld8FJ7QjaRfAxOCCnI6YL4SDWYw,5325
|
31
|
+
nonebot_plugin_werewolf/players/witch.py,sha256=5qeWI1FOi3iUuzMhuTSJVo8Izc0KHseMKvncucvRFSE,3041
|
32
|
+
nonebot_plugin_werewolf/players/wolfking.py,sha256=CMZ5Tq74wupcRPjAzXHEF2Gts4z3thsD57q64uGp_-c,628
|
33
|
+
nonebot_plugin_werewolf-1.1.12.dist-info/licenses/LICENSE,sha256=B_WbEqjGr6GYVNfEJPY31T1Opik7OtgOkhRs4Ig3e2M,1064
|
34
|
+
nonebot_plugin_werewolf-1.1.12.dist-info/METADATA,sha256=_4tEZWDYjQqwkhnlTsbQA8Aik7fb1nUjpMxBMPMJ3Zs,14787
|
35
|
+
nonebot_plugin_werewolf-1.1.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
36
|
+
nonebot_plugin_werewolf-1.1.12.dist-info/top_level.txt,sha256=wLTfg8sTKbH9lLT9LtU118C9cTspEBJareLsrYM52YA,24
|
37
|
+
nonebot_plugin_werewolf-1.1.12.dist-info/RECORD,,
|