diff --git a/.cursor/rules/core.mdc b/.cursor/rules/core.mdc index 19965a9..7003c2d 100644 --- a/.cursor/rules/core.mdc +++ b/.cursor/rules/core.mdc @@ -10,7 +10,7 @@ alwaysApply: true 语言设置:除非用户另有指示,所有常规交互响应都应该使用中文。然而,模式声明(例如\[MODE: RESEARCH\])和特定格式化输出(例如代码块、清单等)应保持英文,以确保格式一致性。 -**工具调用: 你应该使用工具调用而不是通过命令行编辑文件** +**工具调用: 你应该使用edit_file而不是通过命令行编辑文件** 你必须完全理解这个项目, 并明白文件夹PWF里的文件你没有权力更改 diff --git a/.tasks/2025-11-12_4_battle-username-target.md b/.tasks/2025-11-12_4_battle-username-target.md new file mode 100644 index 0000000..6fb93c9 --- /dev/null +++ b/.tasks/2025-11-12_4_battle-username-target.md @@ -0,0 +1,34 @@ +# 背景 +文件名: 2025-11-12_4_battle-username-target.md +创建于: 2025-11-13_00:10:51 +创建者: LIUBAI095 +主分支: main +任务分支: 未创建 +Yolo模式: Off +# 任务描述 +挑战插件需支持通过用户ID或用户名发起PVP挑战。 +# 项目概览 +WPSCombatSystem 负责玩家战斗流程,当前挑战命令仅接受数值型用户ID,用户基础资料由 WPSConfigAPI 管理。 +# 分析 +- `WPSCombatBattle._handle_challenge` 在解析目标参数时仅执行 `int()` 转换,失败即判定格式错误。 +- `combat_service.create_pvp_challenge` 函数签名也要求目标ID为整数。 +- `user_info` 表包含 `username` 字段,且其他插件存在根据用户名反查 `user_id` 的逻辑。 +# 提议的解决方案 +待定 +# 当前执行步骤:"1. 创建任务文件" +# 任务进度 +2025-11-13_00:19:55 +- 已修改: Plugins/WPSCombatSystem/combat_plugin_battle.py +- 更改: 挑战命令支持按用户名优先解析并更新帮助信息 +- 原因: 允许用户通过用户名或ID发起挑战 +- 阻碍因素: 无 +- 状态: 未确认 + +2025-11-13_00:21:27 +- 已修改: Plugins/WPSCombatSystem/combat_plugin_battle.py Plugins/WPSConfigSystem.py +- 更改: 通过 Architecture 获取 WPSConfigAPI 实现用户名解析,新增接口并去除直接数据库访问 +- 原因: 避免插件直接访问数据库,统一通过配置接口解析用户 +- 阻碍因素: 无 +- 状态: 未确认 + +# 最终审查 diff --git a/Plugins/WPSCombatSystem/combat_plugin_battle.py b/Plugins/WPSCombatSystem/combat_plugin_battle.py index 3755618..c1ff498 100644 --- a/Plugins/WPSCombatSystem/combat_plugin_battle.py +++ b/Plugins/WPSCombatSystem/combat_plugin_battle.py @@ -4,9 +4,11 @@ from __future__ import annotations from typing import Optional, Sequence +from PWF.Convention.Runtime.Architecture import Architecture from PWF.Convention.Runtime.GlobalConfig import ConsoleFrontColor, ProjectConfig from Plugins.WPSAPI import GuideEntry +from Plugins.WPSConfigSystem import WPSConfigAPI from .combat_plugin_base import WPSCombatBase @@ -23,7 +25,7 @@ class WPSCombatBattle(WPSCombatBase): return ( GuideEntry( title="挑战", - identifier="挑战 <目标用户ID>", + identifier="挑战 <目标用户>", description="向指定玩家发起 PVP 挑战。", metadata={"别名": "challenge"}, icon="⚔️", @@ -103,7 +105,7 @@ class WPSCombatBattle(WPSCombatBase): 处理PVP命令 命令格式: - - 挑战 <目标用户ID> + - 挑战 <目标用户> - 接受挑战 <挑战ID> - 拒绝挑战 <挑战ID> - 战斗 <战斗ID> <技能名> @@ -147,30 +149,28 @@ class WPSCombatBattle(WPSCombatBase): """处理挑战命令""" if not args: return await self.send_markdown_message( - "❌ 请指定目标用户ID\n用法:`挑战 <目标用户ID>`", + "❌ 请指定目标用户\n用法:`挑战 <目标用户名|用户ID>`", chat_id, user_id ) - - try: - target_id = int(args[0]) - except ValueError: + target_identifier = args[0] + target_id, error_message = self._resolve_target_user(target_identifier) + if error_message: + return await self.send_markdown_message(error_message, chat_id, user_id) + if target_id is None: return await self.send_markdown_message( - "❌ 用户ID格式错误", + "❌ 未找到目标用户,请确认用户名或ID", chat_id, user_id ) - if target_id == user_id: return await self.send_markdown_message( "❌ 不能挑战自己", chat_id, user_id ) - service = self.service() success, msg, challenge_id = service.create_pvp_challenge(user_id, target_id) - return await self.send_markdown_message(msg, chat_id, user_id) async def _handle_accept( @@ -291,7 +291,7 @@ class WPSCombatBattle(WPSCombatBase): """帮助信息""" return """# ⚔️ PVP对战系统 **命令格式:** -- `挑战 <目标用户ID>`:发起PVP挑战 +- `挑战 <目标用户名|用户ID>`:发起PVP挑战 - `接受挑战 <挑战ID>`:接受挑战 - `拒绝挑战 <挑战ID>`:拒绝挑战 - `战斗 <战斗ID> <技能名>`:执行战斗动作 @@ -305,11 +305,38 @@ class WPSCombatBattle(WPSCombatBase): - 可随时投降 **示例:** +- `挑战 玩家A`:向用户名为玩家A的用户发起挑战 - `挑战 12345`:向用户12345发起挑战 - `接受挑战 1`:接受挑战ID为1的挑战 - `战斗 1 攻击`:在战斗1中使用"攻击"技能 - `投降 1`:在战斗1中投降 """ + def _resolve_target_user(self, identifier: str) -> tuple[Optional[int], Optional[str]]: + text = identifier.strip() + if not text: + return None, "❌ 请指定目标用户" + try: + config_api: WPSConfigAPI = Architecture.Get(WPSConfigAPI) + except Exception as exc: + logger.Log( + "Error", + f"{ConsoleFrontColor.RED}获取 WPSConfigAPI 实例失败: {exc}{ConsoleFrontColor.RESET}", + ) + return None, "❌ 系统繁忙,请稍后重试" + try: + resolved_id = config_api.find_user_id_by_username(text) + if resolved_id is not None: + return resolved_id, None + except Exception as exc: + logger.Log( + "Error", + f"{ConsoleFrontColor.RED}解析用户名 {text} 失败: {exc}{ConsoleFrontColor.RESET}", + ) + return None, "❌ 系统繁忙,请稍后重试" + if text.isdigit(): + return int(text), None + return None, None + __all__ = ["WPSCombatBattle"] diff --git a/Plugins/WPSConfigSystem.py b/Plugins/WPSConfigSystem.py index 9971462..bae4b63 100644 --- a/Plugins/WPSConfigSystem.py +++ b/Plugins/WPSConfigSystem.py @@ -202,6 +202,18 @@ class WPSConfigAPI(WPSAPI): value = record.get("username") return str(value) if value else f"user_{user_id}" + def find_user_id_by_username(self, username: str) -> Optional[int]: + text = (username or "").strip() + if not text: + return None + cursor = get_db().conn.cursor() + cursor.execute( + "SELECT user_id FROM user_info WHERE username = ? COLLATE NOCASE", + (text,), + ) + row = cursor.fetchone() + return int(row["user_id"]) if row else None + def get_user_url(self, user_id: int) -> Optional[str]: record = self._get_user_record(user_id) if not record: