Skip to content

Commit a7b7049

Browse files
committed
feat: add wand tool and /mahjong room command for game room creation
1 parent 9fc5c35 commit a7b7049

15 files changed

Lines changed: 553 additions & 20 deletions

docs/wiki.zh-CN.md

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@ MahjongPaper 使用 CraftEngine 处理以下内容:
322322
| `/mahjong clear` | 管理员 | 清除展示实体 |
323323
| `/mahjong forceend [table_id]` | 管理员 | 强制结束牌桌 |
324324
| `/mahjong deletetable [table_id]` | 管理员 | 删除牌桌 |
325+
| `/mahjong room wand` | 管理员 | 获取魔棒选区工具 |
326+
| `/mahjong room create <id> [名称]` | 管理员 | 用选区或当前位置创建棋牌室 |
327+
| `/mahjong room delete <id>` | 管理员 | 删除棋牌室 |
328+
| `/mahjong room list` | 管理员 | 列出棋牌室 |
329+
| `/mahjong room info <id>` | 管理员 | 查看棋牌室详情 |
325330
| `/mahjong reload` | 管理员 | 重载配置 |
326331

327332
## 棋牌室系统
@@ -357,7 +362,62 @@ MahjongPaper 使用 CraftEngine 处理以下内容:
357362

358363
### 创建棋牌室
359364

360-
目前棋牌室通过编辑 `plugins/MahjongPaper/game-rooms.yml` 手动创建。文件格式如下:
365+
有两种方式创建棋牌室:使用游戏内魔棒工具(推荐)或手动编辑配置文件。
366+
367+
#### 方式一:魔棒工具(推荐)
368+
369+
魔棒工具类似 WorldEdit 的选区功能,通过两点选区定义棋牌室区域。
370+
371+
**获取魔棒**
372+
373+
```
374+
/mahjong room wand
375+
```
376+
377+
执行后会获得一根烈焰棒(Blaze Rod),物品名和描述会标明这是麻将选区工具。
378+
379+
**使用魔棒选区**
380+
381+
| 操作 | 效果 |
382+
| --- | --- |
383+
| 左键点击方块 | 设置选区第一点(最小角) |
384+
| 右键点击方块 | 设置选区第二点(最大角) |
385+
386+
两点确定一个长方体(AABB)区域。设置成功后会收到提示消息,显示当前选区坐标。
387+
388+
**创建棋牌室**
389+
390+
选好两点后,执行:
391+
392+
```
393+
/mahjong room create <id> [名称]
394+
```
395+
396+
- `id`:棋牌室唯一标识,只能包含小写字母、数字、下划线和短横线。
397+
- `名称`:可选的显示名称,不填则使用 id 作为名称。
398+
399+
如果已有选区,会使用选区坐标创建;如果没有选区,则以玩家当前位置为中心,按配置中的 `defaultRadius``defaultHeight` 创建。
400+
401+
**示例**
402+
403+
```
404+
/mahjong room wand # 获取魔棒
405+
# 左键点击房间一个角,右键点击对角
406+
/mahjong room create main-hall 主厅 # 用选区创建棋牌室
407+
/mahjong room create quick-room # 无选区时以玩家位置为中心创建
408+
```
409+
410+
**其他棋牌室命令**
411+
412+
| 命令 | 说明 |
413+
| --- | --- |
414+
| `/mahjong room delete <id>` | 删除指定棋牌室 |
415+
| `/mahjong room list` | 列出所有棋牌室 |
416+
| `/mahjong room info <id>` | 查看棋牌室详情(世界、坐标、大小、所有者) |
417+
418+
#### 方式二:手动编辑配置文件
419+
420+
直接编辑 `plugins/MahjongPaper/game-rooms.yml`
361421

362422
```yaml
363423
rooms:
@@ -373,16 +433,16 @@ rooms:
373433
owner: "玩家UUID" # 可选,所有者 UUID
374434
```
375435
376-
**创建步骤**:
436+
**步骤**:
377437
378438
1. 停止服务器或确保没有活跃牌桌。
379439
2. 打开 `plugins/MahjongPaper/game-rooms.yml`。
380-
3. 在 `rooms:` 下添加一个新条目,按上面的格式填写 ID、名称、世界名和区域坐标。
440+
3. 在 `rooms:` 下添加新条目,填写 ID、名称、世界名和区域坐标。
381441
4. 保存文件,重启服务器或使用 `/mahjong reload` 重载。
382442

383-
**确定区域坐标的方法**:
443+
**确定区域坐标**:
384444

385-
- 站在你想设为棋牌室的一个角落,记下 `/minecraft:tp ~ ~ ~` 显示的坐标作为 `minX/minY/minZ`。
445+
- 站在棋牌室的一个角落,记下坐标作为 `minX/minY/minZ`。
386446
- 走到对角线的另一个角落,记下坐标作为 `maxX/maxY/maxZ`。
387447
- 两个角定义一个长方体(AABB),牌桌中心必须在这个长方体内才算"在棋牌室内"。
388448

@@ -401,8 +461,6 @@ rooms:
401461
maxZ: 15
402462
```
403463

404-
> 后续版本将添加游戏内命令和选区工具来简化棋牌室的创建流程。
405-
406464
## 常见问题
407465

408466
### 为什么我不能创建牌桌?

src/main/java/top/ellan/mahjong/bootstrap/MahjongPaperPlugin.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import top.ellan.mahjong.db.DatabaseService;
1010
import top.ellan.mahjong.gb.jni.GbNativeWarmupService;
1111
import top.ellan.mahjong.gameroom.GameRoomManager;
12+
import top.ellan.mahjong.gameroom.GameRoomSelectionService;
13+
import top.ellan.mahjong.gameroom.GameRoomWandListener;
1214
import top.ellan.mahjong.i18n.MessageService;
1315
import top.ellan.mahjong.metrics.InMemoryMetricsCollector;
1416
import top.ellan.mahjong.metrics.MetricsCollector;
@@ -42,6 +44,7 @@ public final class MahjongPaperPlugin extends JavaPlugin {
4244
private CraftEngineService craftEngine;
4345
private MahjongTableManager tableManager;
4446
private GameRoomManager gameRoomManager;
47+
private GameRoomSelectionService gameRoomSelectionService;
4548

4649
@Override
4750
public void onEnable() {
@@ -78,6 +81,7 @@ public void onEnable() {
7881
this.scheduler.runGlobal(this.craftEngine::cleanupMahjongFurniture);
7982
this.tableManager.loadPersistentTables();
8083

84+
this.gameRoomSelectionService = new GameRoomSelectionService();
8185
this.gameRoomManager = new GameRoomManager(
8286
this.tableManager,
8387
this.debug,
@@ -97,7 +101,9 @@ public void onEnable() {
97101
this.async,
98102
this.scheduler,
99103
this::database,
100-
this::reloadMahjongConfiguration
104+
this::reloadMahjongConfiguration,
105+
() -> this.gameRoomManager,
106+
this.gameRoomSelectionService
101107
);
102108
if (!this.registerMahjongCommand(mahjongCommand)) {
103109
return;
@@ -106,6 +112,7 @@ public void onEnable() {
106112
this.getServer().getPluginManager().registerEvents(this.tableManager, this);
107113
if (this.gameRoomManager != null && this.settings.gameRooms().enabled()) {
108114
this.getServer().getPluginManager().registerEvents(new top.ellan.mahjong.gameroom.GameRoomListener(this.gameRoomManager, this.messages, () -> this.settings), this);
115+
this.getServer().getPluginManager().registerEvents(new GameRoomWandListener(this.gameRoomSelectionService, this.messages), this);
109116
this.scheduler.runGlobalTimer(this.gameRoomManager::tick, 20L, 20L);
110117
}
111118
this.scheduler.runGlobal(() -> {

src/main/java/top/ellan/mahjong/command/MahjongCommand.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import top.ellan.mahjong.command.subcommand.RemoveBotSubcommand;
3737
import top.ellan.mahjong.command.subcommand.RenderSubcommand;
3838
import top.ellan.mahjong.command.subcommand.RiichiSubcommand;
39+
import top.ellan.mahjong.command.subcommand.RoomSubcommand;
3940
import top.ellan.mahjong.command.subcommand.RonSubcommand;
4041
import top.ellan.mahjong.command.subcommand.RuleSubcommand;
4142
import top.ellan.mahjong.command.subcommand.SettlementSubcommand;
@@ -48,6 +49,8 @@
4849
import top.ellan.mahjong.command.subcommand.UnspectateSubcommand;
4950
import top.ellan.mahjong.db.DatabaseService;
5051
import top.ellan.mahjong.debug.DebugService;
52+
import top.ellan.mahjong.gameroom.GameRoomManager;
53+
import top.ellan.mahjong.gameroom.GameRoomSelectionService;
5154
import top.ellan.mahjong.i18n.MessageService;
5255
import top.ellan.mahjong.runtime.AsyncService;
5356
import top.ellan.mahjong.runtime.ServerScheduler;
@@ -67,9 +70,11 @@ public MahjongCommand(
6770
AsyncService async,
6871
ServerScheduler scheduler,
6972
Supplier<DatabaseService> database,
70-
Supplier<String> reloadConfiguration
73+
Supplier<String> reloadConfiguration,
74+
Supplier<GameRoomManager> gameRoomManager,
75+
GameRoomSelectionService selectionService
7176
) {
72-
this.context = new MahjongCommandContext(messages, tableManager, debug, async, scheduler, database, reloadConfiguration);
77+
this.context = new MahjongCommandContext(messages, tableManager, debug, async, scheduler, database, reloadConfiguration, gameRoomManager, selectionService);
7378
this.subcommands = this.createSubcommands();
7479
}
7580

@@ -209,6 +214,7 @@ static List<MahjongSubcommand> productionSubcommands(MahjongCommandContext conte
209214
commands.add(new ForceEndSubcommand(context).create());
210215
commands.add(new DeleteTableSubcommand(context).create());
211216
commands.add(new ReloadSubcommand(context).create());
217+
commands.add(new RoomSubcommand(context).create());
212218
return List.copyOf(commands);
213219
}
214220

src/main/java/top/ellan/mahjong/command/MahjongCommandContext.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import top.ellan.mahjong.db.DatabaseService;
1818
import top.ellan.mahjong.db.MahjongSoulRankProfile;
1919
import top.ellan.mahjong.db.MahjongSoulRankRules;
20+
import top.ellan.mahjong.gameroom.GameRoomManager;
21+
import top.ellan.mahjong.gameroom.GameRoomSelectionService;
2022
import top.ellan.mahjong.i18n.MessageService;
2123
import top.ellan.mahjong.model.SeatWind;
2224
import top.ellan.mahjong.render.layout.TableRenderLayout;
@@ -67,7 +69,8 @@ public final class MahjongCommandContext {
6769
"command.help.clear",
6870
"command.help.forceend",
6971
"command.help.deletetable",
70-
"command.help.reload"
72+
"command.help.reload",
73+
"command.help.room"
7174
);
7275
static final java.util.Set<String> ADMIN_HELP_KEY_SET = java.util.Set.of(
7376
"command.help.create",
@@ -78,7 +81,8 @@ public final class MahjongCommandContext {
7881
"command.help.clear",
7982
"command.help.forceend",
8083
"command.help.deletetable",
81-
"command.help.reload"
84+
"command.help.reload",
85+
"command.help.room"
8286
);
8387
private static final String[] HELP_KEYS = HELP_KEY_ORDER.toArray(new String[0]);
8488
private static final Set<String> ADMIN_HELP_KEYS = ADMIN_HELP_KEY_SET;
@@ -89,6 +93,8 @@ public final class MahjongCommandContext {
8993
private final ServerScheduler scheduler;
9094
private final Supplier<DatabaseService> database;
9195
private final Supplier<String> reloadConfiguration;
96+
private final Supplier<GameRoomManager> gameRoomManager;
97+
private final GameRoomSelectionService selectionService;
9298

9399
public MahjongCommandContext(
94100
MessageService messages,
@@ -97,7 +103,9 @@ public MahjongCommandContext(
97103
AsyncService async,
98104
ServerScheduler scheduler,
99105
Supplier<DatabaseService> database,
100-
Supplier<String> reloadConfiguration
106+
Supplier<String> reloadConfiguration,
107+
Supplier<GameRoomManager> gameRoomManager,
108+
GameRoomSelectionService selectionService
101109
) {
102110
this.messages = Objects.requireNonNull(messages, "messages");
103111
this.tableManager = Objects.requireNonNull(tableManager, "tableManager");
@@ -106,6 +114,8 @@ public MahjongCommandContext(
106114
this.scheduler = Objects.requireNonNull(scheduler, "scheduler");
107115
this.database = Objects.requireNonNull(database, "database");
108116
this.reloadConfiguration = Objects.requireNonNull(reloadConfiguration, "reloadConfiguration");
117+
this.gameRoomManager = gameRoomManager;
118+
this.selectionService = selectionService;
109119
}
110120

111121
public MessageService messages() {
@@ -508,4 +518,12 @@ private String formatDecimal(double value) {
508518
private DatabaseService database() {
509519
return this.database.get();
510520
}
521+
522+
public GameRoomManager gameRoomManager() {
523+
return this.gameRoomManager != null ? this.gameRoomManager.get() : null;
524+
}
525+
526+
public GameRoomSelectionService selectionService() {
527+
return this.selectionService;
528+
}
511529
}

0 commit comments

Comments
 (0)