|
7 | 7 | # from PyQt5.QtWidgets import QApplication, QFileDialog, QWidget |
8 | 8 | import gameDefinedParameter |
9 | 9 | from plugin_sdk.server_bridge import GameServerBridge |
10 | | -from shared_types.events import VideoSaveEvent |
| 10 | +from shared_types.events import VideoSaveEvent, BoardUpdateEvent, GameStatusChangeEvent |
11 | 11 | import superGUI |
12 | 12 | import gameAbout |
13 | 13 | import gameSettings |
@@ -219,6 +219,8 @@ def game_state(self): |
219 | 219 | @game_state.setter |
220 | 220 | def game_state(self, game_state: str): |
221 | 221 | # print(self._game_state, " -> " ,game_state) |
| 222 | + last_state = self._game_state |
| 223 | + |
222 | 224 | match self._game_state: |
223 | 225 | case "playing": |
224 | 226 | self.try_append_evfs(game_state) |
@@ -252,7 +254,29 @@ def game_state(self, game_state: str): |
252 | 254 | self.label.paint_cursor = False |
253 | 255 | self.label.paintProbability = False |
254 | 256 | self.num_bar_ui.QWidget.close() |
| 257 | + |
255 | 258 | self._game_state = game_state |
| 259 | + |
| 260 | + # 发送游戏状态变化事件 |
| 261 | + state_map = { |
| 262 | + "ready": 1, |
| 263 | + "playing": 2, |
| 264 | + "win": 3, |
| 265 | + "fail": 4, |
| 266 | + "joking": 2, # joking 也视为游戏中 |
| 267 | + "jowin": 3, |
| 268 | + "jofail": 4, |
| 269 | + "show": 5, |
| 270 | + "study": 6, |
| 271 | + "display": 7, |
| 272 | + "showdisplay": 8, |
| 273 | + } |
| 274 | + if last_state != game_state: |
| 275 | + event = GameStatusChangeEvent( |
| 276 | + last_status=state_map.get(last_state, 0), |
| 277 | + current_status=state_map.get(game_state, 0), |
| 278 | + ) |
| 279 | + GameServerBridge.instance().send_event(event) |
256 | 280 |
|
257 | 281 | @property |
258 | 282 | def row(self): |
@@ -477,6 +501,100 @@ def mineNumWheel(self, i): |
477 | 501 | # self.timer_mine_num.setSingleShot(True) |
478 | 502 | # self.timer_mine_num.start(3000) |
479 | 503 |
|
| 504 | + def _send_board_update_event(self): |
| 505 | + """发送棋盘更新事件给插件""" |
| 506 | + try: |
| 507 | + ms_board = self.label.ms_board |
| 508 | + # 将 game_board 转换为列表格式 |
| 509 | + game_board_list = [] |
| 510 | + for row in ms_board.game_board: |
| 511 | + game_board_list.append(list(row)) |
| 512 | + |
| 513 | + event = BoardUpdateEvent( |
| 514 | + rows=self.row, |
| 515 | + cols=self.column, |
| 516 | + game_board=game_board_list, |
| 517 | + mines_remaining=self.mineUnFlagedNum, |
| 518 | + game_time=ms_board.time if hasattr(ms_board, 'time') else 0.0, |
| 519 | + ) |
| 520 | + GameServerBridge.instance().send_event(event) |
| 521 | + except Exception: |
| 522 | + pass # 忽略发送失败 |
| 523 | + |
| 524 | + def execute_cell_click(self, row: int, col: int, button: int) -> bool: |
| 525 | + """ |
| 526 | + 执行格子点击(供外部命令调用) |
| 527 | + |
| 528 | + Args: |
| 529 | + row: 行索引(从 0 开始) |
| 530 | + col: 列索引(从 0 开始) |
| 531 | + button: 鼠标按钮(0=左键, 2=右键) |
| 532 | + |
| 533 | + Returns: |
| 534 | + True 表示成功执行 |
| 535 | + """ |
| 536 | + # 检查游戏状态 |
| 537 | + if self.game_state not in ('ready', 'playing', 'joking'): |
| 538 | + return False |
| 539 | + |
| 540 | + # 检查坐标有效性 |
| 541 | + if row < 0 or row >= self.row or col < 0 or col >= self.column: |
| 542 | + return False |
| 543 | + |
| 544 | + # 转换为像素坐标(中心点) |
| 545 | + i = row * self.pixSize + self.pixSize // 2 |
| 546 | + j = col * self.pixSize + self.pixSize // 2 |
| 547 | + |
| 548 | + try: |
| 549 | + if button == 0: # 左键 |
| 550 | + # 模拟点击流程:按下 -> 抬起 |
| 551 | + self.label.ms_board.step('lc', (i, j)) |
| 552 | + |
| 553 | + # 处理第一次点击埋雷 |
| 554 | + if self.game_state == 'ready': |
| 555 | + if self.label.ms_board.mouse_state == 4: |
| 556 | + if self.board_constraint: |
| 557 | + self.game_state = 'joking' |
| 558 | + else: |
| 559 | + self.game_state = 'playing' |
| 560 | + if self.player_identifier[:6] != "[live]": |
| 561 | + self.disable_screenshot() |
| 562 | + if self.cursor_limit: |
| 563 | + self.limit_cursor() |
| 564 | + self.start_time_unix_2 = QtCore.QDateTime.currentDateTime().toMSecsSinceEpoch() |
| 565 | + self.timer_10ms.start() |
| 566 | + self.score_board_manager.editing_row = -2 |
| 567 | + # 埋雷 |
| 568 | + self.layMine(row, col) |
| 569 | + |
| 570 | + self.label.ms_board.step('lr', (i, j)) |
| 571 | + |
| 572 | + # 检查游戏结束 |
| 573 | + if self.label.ms_board.game_board_state == 3: |
| 574 | + self.gameWin() |
| 575 | + elif self.label.ms_board.game_board_state == 4: |
| 576 | + self.gameFailed() |
| 577 | + |
| 578 | + elif button == 2: # 右键 |
| 579 | + # 更新剩余雷数 |
| 580 | + cell_state = self.label.ms_board.game_board[row][col] |
| 581 | + if cell_state == 11: # 已标旗,取消标旗 |
| 582 | + self.mineUnFlagedNum += 1 |
| 583 | + self.showMineNum(self.mineUnFlagedNum) |
| 584 | + elif cell_state == 10: # 未揭开,标旗 |
| 585 | + self.mineUnFlagedNum -= 1 |
| 586 | + self.showMineNum(self.mineUnFlagedNum) |
| 587 | + |
| 588 | + self.label.ms_board.step('rc', (i, j)) |
| 589 | + self.label.ms_board.step('rr', (i, j)) |
| 590 | + |
| 591 | + self.label.update() |
| 592 | + self._send_board_update_event() |
| 593 | + return True |
| 594 | + |
| 595 | + except Exception: |
| 596 | + return False |
| 597 | + |
480 | 598 | def gameStart(self): |
481 | 599 | # 画界面,但是不埋雷。等价于点脸、f2、设置确定后的效果 |
482 | 600 | self.mineUnFlagedNum = self.minenum # 没有标出的雷,显示在左上角 |
@@ -570,6 +688,9 @@ def gameFinished(self): |
570 | 688 | data[key] = getattr(ms_board, key) |
571 | 689 | event = VideoSaveEvent(**data) |
572 | 690 | GameServerBridge.instance().send_event(event) |
| 691 | + |
| 692 | + # 发送棋盘更新事件,让插件知道最终状态 |
| 693 | + self._send_board_update_event() |
573 | 694 |
|
574 | 695 | def gameWin(self): # 成功后改脸和状态变量,停时间 |
575 | 696 | self.timer_10ms.stop() |
|
0 commit comments