Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,5 @@ toollib/frame.csv
old/
发布流程.txt
src/plugins/*/*.json
src/plugins/*/*.db
.vscode/
6 changes: 2 additions & 4 deletions src/CheckUpdateGui.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,9 @@ def initUi(self):
row1.addWidget(QLabel(self.release.tag_name))
row1.addItem(QSpacerItem(
20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
self.dateTimeLabel.hide()
if self.release.assets_created_at != "":
self.dateTimeLabel.setText(QDateTime.fromString(
self.release.assets_created_at, "yyyy-MM-ddThh:mm:ssZ").toString("yyyy-MM-dd hh:mm:ss"))
self.dateTimeLabel.show()
row1.addWidget(self.dateTimeLabel)
row1.addItem(QSpacerItem(
20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
Expand Down Expand Up @@ -337,11 +335,11 @@ def checkUpdate(self, releases: list[ReleaseInfo]):
layout.setSpacing(2)
for release in releases:
frame = ReleaseFrame(
release, self.github.compareVersion(release.tag_name), r_path=self.r_path)
release, self.github.compareVersion(release.tag_name), r_path=self.r_path, parent=self)
layout.addWidget(frame)
frame.downLoadFile.connect(self.github.downloadRelease)
# 底部加一个空白区域
panel = QWidget()
panel = QWidget(self)
panel.setContentsMargins(0, 0, 0, 0)
panel.setFixedHeight(100)
layout.addWidget(panel)
Expand Down
104 changes: 104 additions & 0 deletions src/gen_plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import os
import sys
from pathlib import Path


def is_valid_class_name(name: str) -> bool:
"""检查是否为有效的Python类名"""
if not name or not isinstance(name, str):
return False
if not name.isidentifier():
return False
if name[0].islower():
return False
return True


def build_py_file_content(name: str) -> str:
"""生成Python文件内容"""
template = f'''
import sys
import os
import msgspec
import zmq

if getattr(sys, "frozen", False): # 检查是否为pyInstaller生成的EXE
application_path = os.path.dirname(sys.executable)
sys.path.append(application_path + "/../../")
print(application_path + "/../../")
else:
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/../../")
from mp_plugins import BasePlugin, BaseConfig
from mp_plugins.base.config import *
from mp_plugins.context import AppContext
from mp_plugins.events import *

class {name}Config(BaseConfig):
pass


class {name}(BasePlugin):
def __init__(
self,
) -> None:
super().__init__()
self._context: AppContext
self._config = {name}Config()

def build_plugin_context(self) -> None:
self._plugin_context.name = "{name}"
self._plugin_context.display_name = "{name}"
self._plugin_context.version = "1.0.0"
self._plugin_context.description = "{name}"
self._plugin_context.author = ""

def initialize(self) -> None:
return super().initialize()

def shutdown(self) -> None:
return super().shutdown()



if __name__ == "__main__":
try:
import sys

args = sys.argv[1:]
host = args[0]
port = int(args[1])
plugin = {name}()
# 捕获退出信号,优雅关闭
import signal

def signal_handler(sig, frame):
plugin.stop()
sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
plugin.run(host, port)
except Exception:
pass
'''
return template


if __name__ == "__main__":
print("Building plugin...")
args = sys.argv[1:]
if len(args) != 1:
print("Usage: gen_plugin.py <plugin_name>")
exit(1)
name = args[0]
if not is_valid_class_name(name):
print("Invalid plugin name")
exit(1)
current_path = os.path.dirname(os.path.abspath(__file__))
plugin_path = Path(current_path) / "plugins" / name
plugin_path.mkdir(parents=True, exist_ok=True)
plugin_file = plugin_path / f"{name}.py"
with open(plugin_file, "w", encoding="utf-8") as f:
context = build_py_file_content(name)
f.write(context)
print("gen py file success")
12 changes: 7 additions & 5 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ def on_ready_read(socket: QLocalSocket):
socket.disconnectFromServer() # 断开连接



def cli_check_file(file_path: str) -> int:
if not os.path.exists(file_path):
print("ERROR: file not found")
Expand Down Expand Up @@ -132,7 +131,8 @@ def cli_check_file(file_path: str) -> int:
else:
if videos.len() <= 0:
evf_evfs_files[ide] = (e, 2)
checksum = ui.checksum_guard.get_checksum(videos[0].evf_video.raw_data)
checksum = ui.checksum_guard.get_checksum(
videos[0].evf_video.raw_data)
if video.checksum != checksum:
evf_evfs_files[ide] = (e, 1)
continue
Expand Down Expand Up @@ -160,7 +160,10 @@ def cli_check_file(file_path: str) -> int:
exit_code = cli_check_file(args.check)
sys.exit(exit_code)
env = patch_env()
context = AppContext("Metasweeper", "1.0.0", "元扫雷")
context = AppContext(name="Metasweeper", version="1.0.0", display_name="元扫雷",
plugin_dir=(Path(get_paths()) / "plugins").as_posix(),
app_dir=get_paths()
)
PluginManager.instance().context = context

PluginManager.instance().start(Path(get_paths()) / "plugins", env)
Expand Down Expand Up @@ -195,9 +198,8 @@ def cli_check_file(file_path: str) -> int:
hwnd, 0x00000011) else 1/0
ui.enable_screenshot = lambda: ... if SetWindowDisplayAffinity(
hwnd, 0x00000000) else 1/0

app.aboutToQuit.connect(PluginManager.instance().stop)
sys.exit(app.exec_())
PluginManager.instance().stop()
...
# except:
# pass
Expand Down
46 changes: 25 additions & 21 deletions src/mineSweeperGUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import gameAbout
import gameSettings
import gameSettingShortcuts
import captureScreen, mine_num_bar, gameRecordPop
import captureScreen
import mine_num_bar
import gameRecordPop
from CheckUpdateGui import CheckUpdateGui
from githubApi import GitHub, SourceManager
import win32con
Expand All @@ -32,6 +34,7 @@
from mp_plugins import PluginManager, PluginContext
from mp_plugins.events import GameEndEvent


class MineSweeperGUI(MineSweeperVideoPlayer):
def __init__(self, MainWindow: MainWindow, args):
self.mainWindow = MainWindow
Expand Down Expand Up @@ -80,7 +83,7 @@ def save_evf_file_integrated():
lambda: self.trans_language("pl_PL"))
self.german_action.triggered.connect(
lambda: self.trans_language("de_DE"))

# 查看菜单
self.action_open_replay.triggered.connect(
lambda: QDesktopServices.openUrl(
Expand Down Expand Up @@ -253,7 +256,8 @@ def game_state(self, game_state: str):
"column": self.column,
"minenum": self.minenum,
})
self.score_board_manager.show(self.label.ms_board, index_type=1)
self.score_board_manager.show(
self.label.ms_board, index_type=1)
case "study":
self.num_bar_ui.QWidget.close()
self._game_state = game_state
Expand Down Expand Up @@ -292,7 +296,7 @@ def minenum(self, minenum):
self._minenum = minenum

def layMine(self, i, j):

xx = self.row
yy = self.column
num = self.minenum
Expand All @@ -301,13 +305,13 @@ def layMine(self, i, j):
if self.gameMode == 5 or self.gameMode == 6 or self.gameMode == 9:
# 根据模式生成局面
Board, _ = utils.laymine_solvable(self.board_constraint,
self.attempt_times_limit, (xx, yy, num, i, j))
self.attempt_times_limit, (xx, yy, num, i, j))
elif self.gameMode == 0 or self.gameMode == 7 or self.gameMode == 8 or self.gameMode == 10:
Board, _ = utils.laymine(self.board_constraint,
self.attempt_times_limit, (xx, yy, num, i, j))
self.attempt_times_limit, (xx, yy, num, i, j))
elif self.gameMode == 4:
Board, _ = utils.laymine_op(self.board_constraint,
self.attempt_times_limit, (xx, yy, num, i, j))
self.attempt_times_limit, (xx, yy, num, i, j))

self.label.ms_board.board = Board

Expand Down Expand Up @@ -362,22 +366,22 @@ def ai(self, i, j):
self.label.ms_board.board = board
elif code == 2:
board, flag = utils.enumerateChangeBoard(self.label.ms_board.board,
self.label.ms_board.game_board, [(i, j)])
self.label.ms_board.game_board, [(i, j)])
self.label.ms_board.board = board
return
elif self.gameMode == 8:
code = ms.is_guess_while_needless(
self.label.ms_board.game_board, (i, j))
if code == 2:
board, flag = utils.enumerateChangeBoard(self.label.ms_board.board,
self.label.ms_board.game_board, [(i, j)])
self.label.ms_board.game_board, [(i, j)])
self.label.ms_board.board = board
return
elif self.gameMode == 9 or self.gameMode == 10:
if self.label.ms_board.board[i][j] == -1:
# 可猜调整的核心逻辑
board, flag = utils.enumerateChangeBoard(self.label.ms_board.board,
self.label.ms_board.game_board, [(i, j)])
self.label.ms_board.game_board, [(i, j)])

self.label.ms_board.board = board
return
Expand Down Expand Up @@ -435,8 +439,8 @@ def chording_ai(self, i, j):
break
if must_guess:
board, flag = utils.enumerateChangeBoard(board,
self.label.ms_board.game_board,
not_mine_round + is_mine_round)
self.label.ms_board.game_board,
not_mine_round + is_mine_round)
self.label.ms_board.board = board
else:
for (x, y) in is_mine_round + not_mine_round:
Expand All @@ -452,13 +456,13 @@ def chording_ai(self, i, j):
break
if must_guess:
board, flag = utils.enumerateChangeBoard(board,
self.label.ms_board.game_board,
not_mine_round + is_mine_round)
self.label.ms_board.game_board,
not_mine_round + is_mine_round)
self.label.ms_board.board = board
elif self.gameMode == 9 or self.gameMode == 10:
board, flag = utils.enumerateChangeBoard(board,
self.label.ms_board.game_board,
not_mine_round + is_mine_round)
self.label.ms_board.game_board,
not_mine_round + is_mine_round)
self.label.ms_board.board = board

def mineNumWheel(self, i):
Expand Down Expand Up @@ -688,7 +692,8 @@ def save_evfs_file(self):
if self.old_evfs_filename:
file_name = self.old_evfs_filename + str(self.evfs.len())
self.evfs.save_evfs_file(file_name)
old_evfs_filename = self.old_evfs_filename + str(self.evfs.len() - 1) + ".evfs"
old_evfs_filename = self.old_evfs_filename + \
str(self.evfs.len() - 1) + ".evfs"
if os.path.exists(old_evfs_filename):
# 进一步确认是文件而不是目录
if os.path.isfile(old_evfs_filename):
Expand Down Expand Up @@ -928,13 +933,13 @@ def try_append_evfs(self, new_game_state):
# self.evfs[0].checksum
checksum = self.checksum_guard.get_checksum(
self.label.ms_board.raw_data)
self.evfs.push(self.label.ms_board.raw_data,
self.evfs.push(self.label.ms_board.raw_data,
self.cal_evf_filename(absolute=False), checksum)
else:
evfs_len = self.evfs.len()
checksum = self.checksum_guard.get_checksum(
self.label.ms_board.raw_data + self.evfs[evfs_len - 1].checksum)
self.evfs.push(self.label.ms_board.raw_data,
self.evfs.push(self.label.ms_board.raw_data,
self.cal_evf_filename(absolute=False), checksum)
self.evfs.generate_evfs_v0_raw_data()
self.save_evfs_file()
Expand Down Expand Up @@ -1479,6 +1484,5 @@ def closeEvent_(self):
self.record_setting.sync()

def action_OpenPluginDialog(self):
contexts = list(PluginManager.instance().plugin_contexts)
dialog = PluginManagerUI(contexts)
dialog = PluginManagerUI(PluginManager.instance().Get_Plugin_Names())
dialog.exec()
1 change: 0 additions & 1 deletion src/mp_plugins/base/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ class SelectSetting(BaseSetting):

class BaseConfig(_BaseData):
""" """

pass


Expand Down
2 changes: 2 additions & 0 deletions src/mp_plugins/base/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class BaseContext(_BaseData):

name: str = ""
version: str = ""
plugin_dir: str = ""
app_dir: str = ""


class PluginContext(BaseContext):
Expand Down
3 changes: 3 additions & 0 deletions src/mp_plugins/base/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ def __eq__(self, value: object) -> bool:
return self.value == value.value
return self.value == value # 支持直接比较 value

def __str__(self) -> str:
return self.name


class PluginStatus(ValueEnum):
"""
Expand Down
Loading