From 740e4fecd02e81ccc1e4744b3070e602740f4725 Mon Sep 17 00:00:00 2001 From: liuwei Date: Wed, 19 Nov 2025 08:59:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E8=80=81=E7=9A=84=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/levels_db.py | 37 ++-- plugins/xiuxian/main.py | 369 ++++++++++++++++++++++------------------ 2 files changed, 223 insertions(+), 183 deletions(-) diff --git a/db/levels_db.py b/db/levels_db.py index f144bd0..0a73cda 100644 --- a/db/levels_db.py +++ b/db/levels_db.py @@ -96,27 +96,24 @@ class LevelsDBOperator(BaseDBOperator): return max(1, lvl - 1) def level_title(self, level: int) -> str: + # 统一使用xiuxian插件的境界定义 + # 与 plugins/xiuxian/config.toml 中的 realm_score 保持一致 titles = [ - "凡人", - "练气期", - "炼体期", - "筑基期", - "结丹期", - "元婴期", - "化神期", - "炼虚期", - "合体期", - "大乘期", - "渡劫期", - "散仙", - "地仙", - "天仙", - "真仙", - "金仙", - "玄仙", - "太乙金仙", - "大罗金仙", - "圣人", + "凡人", # 0 + "炼气", # 1 (原"练气期") + "筑基", # 2 (原"炼体期"、"筑基期"合并) + "金丹", # 3 (原"结丹期") + "元婴", # 4 + "化神", # 5 + "合体", # 6 (原"炼虚期"、"合体期"合并) + "大乘", # 7 + "渡劫", # 8 + "真仙", # 9 (原"散仙"、"地仙"、"天仙"、"真仙"合并) + "金仙", # 10 + "玄仙", # 11 + "太乙金仙", # 12 + "大罗金仙", # 13 + "圣人", # 14 ] if level <= 0: return titles[0] diff --git a/plugins/xiuxian/main.py b/plugins/xiuxian/main.py index da89374..cf405a8 100644 --- a/plugins/xiuxian/main.py +++ b/plugins/xiuxian/main.py @@ -43,32 +43,63 @@ class XiuxianRedisDB: def get_redis(self): return self.db_manager.get_redis_connection() - def get_player(self, user_id: str) -> Optional[Dict[str, Any]]: + def get_player(self, user_id: str, group_id: str) -> Optional[Dict[str, Any]]: + """读取玩家数据,兼容旧格式(无group_id)和新格式(有group_id)""" try: with self.get_redis() as r: - data = r.get(f"{self.player_prefix}{user_id}") + # 优先尝试新格式:xiuxian:cache:player:{group_id}:{user_id} + new_key = f"{self.player_prefix}{group_id}:{user_id}" + data = r.get(new_key) if data: if isinstance(data, bytes): data = data.decode("utf-8") return json.loads(data) + + # 兼容旧格式:xiuxian:cache:player:{user_id} + old_key = f"{self.player_prefix}{user_id}" + data = r.get(old_key) + if data: + if isinstance(data, bytes): + data = data.decode("utf-8") + player = json.loads(data) + # 如果旧数据没有 group_id,使用传入的 group_id + if not player.get("group_id"): + player["group_id"] = group_id + # 迁移到新格式并删除旧格式 + r.set(new_key, json.dumps(player, ensure_ascii=False)) + r.delete(old_key) + return player return None except Exception as e: logger.error(f"读取玩家数据失败: {e}") return None def save_player(self, player: Dict[str, Any]) -> bool: + """保存玩家数据到新格式,同时删除旧格式(如果存在)""" try: with self.get_redis() as r: - r.set(f"{self.player_prefix}{player['user_id']}", json.dumps(player, ensure_ascii=False)) + user_id = player.get("user_id") + group_id = player.get("group_id", "") + new_key = f"{self.player_prefix}{group_id}:{user_id}" + old_key = f"{self.player_prefix}{user_id}" + + # 保存到新格式 + r.set(new_key, json.dumps(player, ensure_ascii=False)) + # 删除旧格式(如果存在),确保数据一致性 + r.delete(old_key) return True except Exception as e: logger.error(f"保存玩家数据失败: {e}") return False - def invalidate_player(self, user_id: str): + def invalidate_player(self, user_id: str, group_id: str): + """失效玩家缓存,同时删除新旧两种格式""" try: with self.get_redis() as r: - r.delete(f"{self.player_prefix}{user_id}") + new_key = f"{self.player_prefix}{group_id}:{user_id}" + old_key = f"{self.player_prefix}{user_id}" + r.delete(new_key) + r.delete(old_key) # 兼容删除旧格式 except Exception as e: logger.error(f"失效玩家缓存失败: {e}") @@ -422,22 +453,22 @@ class XiuxianPlugin(MessagePluginInterface): if status in ("Unstable_Qi", "Injured") and until and now >= until: player["status"] = "Idle" player["status_until"] = None - self.redis_db.save_player(player) + self._save_player(player) return player async def _cmd_register(self, bot: WechatAPIClient, sender: str, roomid: str, content: str) -> Tuple[bool, str]: dao_name = content.strip() if not dao_name: - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), f"❌命令格式错误!\n{self.command_format}", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), f"❌命令格式错误!\n{self.command_format}", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" - player = self.redis_db.get_player(sender) + player = self.redis_db.get_player(sender, roomid or "") if player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "⚠️ 已注册,无需重复注册", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) - self._rate_set(sender, "注册修仙") + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "⚠️ 已注册,无需重复注册", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # self._rate_set(sender, "注册修仙") return True, "已注册" root_name, mult = random.choice(self.spirit_roots) if self.spirit_roots else ("凡灵根", 1.0) player = { @@ -458,12 +489,7 @@ class XiuxianPlugin(MessagePluginInterface): self.xdb.create_player(player) except Exception: pass - if self.xdb: - try: - self.xdb.update_player_fields(player.get("user_id"), {"status": player.get("status"), "status_until": player.get("status_until")}) - except Exception: - pass - self.redis_db.save_player(player) + self._save_player(player) self._rate_set(sender, "注册修仙") # 初始化境界排行榜分值 self.redis_db.leaderboard_realm_add(sender, float(self._realm_score(player["realm"])) ) @@ -489,58 +515,53 @@ class XiuxianPlugin(MessagePluginInterface): lines.append("加入门派 名称") lines.append("积分购石 积分数") msg = "\n".join(lines) - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), msg, sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 30) - self._rate_set(sender, "帮助") + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), msg, sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 30) + # self._rate_set(sender, "帮助") return True, "帮助" async def _cmd_points_to_stone(self, bot: WechatAPIClient, sender: str, roomid: str, content: str) -> Tuple[bool, str]: if not self.points_db: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "系统未初始化积分模块", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "系统未初始化积分模块", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "积分未初始化" - player = self._get_player(sender) + player = self._get_player(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" try: pts = int(content.strip()) except Exception: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "命令格式:积分购石 积分数", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "命令格式:积分购石 积分数", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" if pts <= 0: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "积分数需为正整数", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "积分数需为正整数", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "非法数量" group_id = roomid or "" ok, res = self.points_db.deduct_points(sender, group_id, pts, PointSource.PLUGIN, "修仙购买灵石") if not ok: cur = res.get("current_points", 0) - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"积分不足,当前积分:{cur}", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"积分不足,当前积分:{cur}", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "积分不足" rate = int(self.point_to_stone_rate) if pts < rate: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"积分不足以兑换1灵石,至少需要{rate}积分", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"积分不足以兑换1灵石,至少需要{rate}积分", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "积分不足" stones_gain = pts // rate player["spirit_stone"] = int(player.get("spirit_stone", 0)) + stones_gain - if self.xdb: - try: - self.xdb.update_player_fields(sender, {"spirit_stone": player["spirit_stone"]}) - except Exception: - pass - self.redis_db.save_player(player) + self._save_player(player) self._rate_set(sender, "积分购石") client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"✅ 兑换成功,消耗积分{pts},获得灵石{stones_gain}({rate}积分=1灵石)", sender) if self.revoke: @@ -548,11 +569,11 @@ class XiuxianPlugin(MessagePluginInterface): return True, "积分购石" async def _cmd_status(self, bot: WechatAPIClient, sender: str, roomid: str) -> Tuple[bool, str]: - player = self.redis_db.get_player(sender) + player = self.redis_db.get_player(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" player = self._check_status_update(player) status_code = player.get("status") @@ -575,21 +596,27 @@ class XiuxianPlugin(MessagePluginInterface): return True, "状态展示" async def _cmd_cultivate(self, bot: WechatAPIClient, sender: str, roomid: str) -> Tuple[bool, str]: - player = self.redis_db.get_player(sender) + player = self.redis_db.get_player(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" player = self._check_status_update(player) status = player.get("status", "Idle") if status == "Cultivating": - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "⚠️ 已在闭关中", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "⚠️ 已在闭关中", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "重复闭关" if status not in ("Idle", "Injured"): - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), f"当前状态[{status}]不可闭关", sender) + status_cn = { + "Idle": "空闲", + "Cultivating": "闭关", + "Unstable_Qi": "气息不稳", + "Injured": "受伤保护", + }.get(status, str(status)) + client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), f"当前状态[{status_cn}]不可闭关", sender) if self.revoke: self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "状态不可闭关" @@ -603,17 +630,17 @@ class XiuxianPlugin(MessagePluginInterface): return True, "闭关成功" async def _cmd_finish_cultivate(self, bot: WechatAPIClient, sender: str, roomid: str) -> Tuple[bool, str]: - player = self.redis_db.get_player(sender) + player = self.redis_db.get_player(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" player = self._check_status_update(player) if player.get("status") != "Cultivating": - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "⚠️ 非闭关状态,无需出关", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "⚠️ 非闭关状态,无需出关", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "非闭关" start_iso = player.get("last_cultivate_time") @@ -643,24 +670,25 @@ class XiuxianPlugin(MessagePluginInterface): return True, "出关结算" async def _cmd_gather(self, bot: WechatAPIClient, sender: str, roomid: str, content: str) -> Tuple[bool, str]: - player = self.redis_db.get_player(sender) + player = self.redis_db.get_player(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" + player = self._check_status_update(player) try: qty = int(content.strip()) except Exception: - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), f"❌命令格式错误!\n{self.command_format}", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), f"❌命令格式错误!\n{self.command_format}", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" stones = int(player.get("spirit_stone", 0)) if qty <= 0 or stones < qty: - client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "⚠️ 灵石不足或数量不合法", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender), "⚠️ 灵石不足或数量不合法", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "灵石不足" player["spirit_stone"] = stones - qty player["cultivation_points"] = int(player.get("cultivation_points", 0)) + qty * 10 @@ -688,8 +716,8 @@ class XiuxianPlugin(MessagePluginInterface): self._rate_set(sender, "排行榜") return True, "排行榜" - def _get_player(self, user_id: str) -> Optional[Dict[str, Any]]: - return self.redis_db.get_player(user_id) + def _get_player(self, user_id: str, group_id: str) -> Optional[Dict[str, Any]]: + return self._get_player_with_cache(user_id, group_id) def _save_player(self, player: Dict[str, Any]): if self.xdb: @@ -703,14 +731,13 @@ class XiuxianPlugin(MessagePluginInterface): pass self.redis_db.save_player(player) - def _get_player_with_cache(self, user_id: str) -> Optional[Dict[str, Any]]: - """读取玩家:优先 Redis,未命中则读 DB 并回填缓存。""" - p = self.redis_db.get_player(user_id) + def _get_player_with_cache(self, user_id: str, group_id: str) -> Optional[Dict[str, Any]]: + p = self.redis_db.get_player(user_id, group_id) if p: return p if self.xdb: dbp = self.xdb.get_player(user_id) - if dbp: + if dbp and dbp.get("group_id", "") == group_id: dbp.setdefault("spirit_root_mult", 1.0) dbp.setdefault("inventory", {}) self.redis_db.save_player(dbp) @@ -742,7 +769,7 @@ class XiuxianPlugin(MessagePluginInterface): if self.xdb: try: self.xdb.update_player_fields(user_id, {"realm": new_realm}) - self.redis_db.invalidate_player(user_id) + self.redis_db.invalidate_player(user_id, player.get("group_id", "")) except Exception: pass self._save_player(player) @@ -762,16 +789,17 @@ class XiuxianPlugin(MessagePluginInterface): self._set_realm(user_id, player, f"{prefix}{new_layer}层") async def _cmd_signin(self, bot: WechatAPIClient, sender: str, roomid: str) -> Tuple[bool, str]: - player = self._get_player(sender) + player = self._get_player(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" + player = self._check_status_update(player) if self.redis_db.check_rate_limited(sender, "签到"): - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "今日已签到,请明日再来", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "今日已签到,请明日再来", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "已签到" reward = 50 player["spirit_stone"] = int(player.get("spirit_stone", 0)) + reward @@ -795,36 +823,37 @@ class XiuxianPlugin(MessagePluginInterface): async def _cmd_buy(self, bot: WechatAPIClient, sender: str, roomid: str, content: str) -> Tuple[bool, str]: parts = content.split() if len(parts) < 2: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"❌命令格式错误!\n购买 物品 数量", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"❌命令格式错误!\n购买 物品 数量", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" item_name = parts[0] try: qty = int(parts[1]) except Exception: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"❌命令格式错误!\n购买 物品 数量", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"❌命令格式错误!\n购买 物品 数量", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" - player = self._get_player(sender) + player = self._get_player(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" + player = self._check_status_update(player) item = next((i for i in self.shop_items if i["name"] == item_name), None) if not item: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "商品不存在", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "商品不存在", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "商品不存在" total = item["price"] * qty stones = int(player.get("spirit_stone", 0)) if qty <= 0 or stones < total: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "灵石不足", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "灵石不足", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "灵石不足" player["spirit_stone"] = stones - total inv = player.get("inventory") or {} @@ -836,7 +865,7 @@ class XiuxianPlugin(MessagePluginInterface): self.xdb.add_item(sender, item_name, item.get("type","other"), qty) except Exception: pass - self.redis_db.save_player(player) + self._save_player(player) self._rate_set(sender, "购买") client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"✅ 购买成功,{item_name} × {qty}", sender) if self.revoke: @@ -844,11 +873,11 @@ class XiuxianPlugin(MessagePluginInterface): return True, "购买成功" async def _cmd_bag(self, bot: WechatAPIClient, sender: str, roomid: str) -> Tuple[bool, str]: - player = self._get_player(sender) + player = self._get_player(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" inv = player.get("inventory") or {} items = [] @@ -870,12 +899,13 @@ class XiuxianPlugin(MessagePluginInterface): return True, "背包" async def _cmd_breakthrough(self, bot: WechatAPIClient, sender: str, roomid: str) -> Tuple[bool, str]: - player = self._get_player(sender) + player = self._get_player(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" + player = self._check_status_update(player) points = int(player.get("cultivation_points", 0)) inv = player.get("inventory") or {} # 读取当前瓶颈配置 @@ -911,7 +941,7 @@ class XiuxianPlugin(MessagePluginInterface): try: self.xdb.remove_item(sender, self.bt_pill_item, 1) self.xdb.update_player_fields(sender, {"cultivation_points": player["cultivation_points"]}) - self.redis_db.invalidate_player(sender) + self.redis_db.invalidate_player(sender, player.get("group_id", "")) except Exception: pass roll = random.random() @@ -925,6 +955,7 @@ class XiuxianPlugin(MessagePluginInterface): self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 10) return True, "突破成功" else: + # 失败时也要保存玩家数据 self._save_player(player) self._rate_set(sender, "突破") client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "❌ 突破失败", sender) @@ -933,12 +964,13 @@ class XiuxianPlugin(MessagePluginInterface): return False, "突破失败" async def _cmd_force_breakthrough(self, bot: WechatAPIClient, sender: str, roomid: str) -> Tuple[bool, str]: - player = self._get_player(sender) + player = self._get_player(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" + player = self._check_status_update(player) points = int(player.get("cultivation_points", 0)) # 读取当前瓶颈配置 cur_realm = player.get("realm", "炼气1层") @@ -965,7 +997,7 @@ class XiuxianPlugin(MessagePluginInterface): if self.xdb: try: self.xdb.update_player_fields(sender, {"cultivation_points": player["cultivation_points"]}) - self.redis_db.invalidate_player(sender) + self.redis_db.invalidate_player(sender, player.get("group_id", "")) except Exception: pass roll = random.random() @@ -978,6 +1010,7 @@ class XiuxianPlugin(MessagePluginInterface): self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 10) return True, "强行突破成功" else: + # 失败时也要保存玩家数据 self._save_player(player) self._rate_set(sender, "强行突破") client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "❌ 强行突破失败,灵气反噬!", sender) @@ -988,21 +1021,21 @@ class XiuxianPlugin(MessagePluginInterface): async def _cmd_rob(self, bot: WechatAPIClient, sender: str, roomid: str, content: str) -> Tuple[bool, str]: target = content.strip().lstrip("@") if not target: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "命令格式:劫掠 目标wxid", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "命令格式:劫掠 目标wxid", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" if target == sender: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "不可劫掠自己", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "不可劫掠自己", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "非法目标" - attacker = self._get_player(sender) - defender = self._get_player(target) + attacker = self._get_player(sender, roomid or "") + defender = self._get_player(target, roomid or "") if not attacker or not defender: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "双方需已注册", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "双方需已注册", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" attacker = self._check_status_update(attacker) defender = self._check_status_update(defender) @@ -1049,8 +1082,8 @@ class XiuxianPlugin(MessagePluginInterface): self.xdb.update_player_fields(attacker.get("user_id"), {"spirit_stone": attacker["spirit_stone"]}) except Exception: pass - self.redis_db.save_player(defender) - self.redis_db.save_player(attacker) + self._save_player(defender) + self._save_player(attacker) self._rate_set(sender, "劫掠") client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"✅ 劫掠成功,获得灵石{gain}", sender) if self.revoke: @@ -1082,8 +1115,8 @@ class XiuxianPlugin(MessagePluginInterface): if self.revoke: self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" - giver = self._get_player_with_cache(sender) - receiver = self._get_player_with_cache(target) + giver = self._get_player_with_cache(sender, roomid or "") + receiver = self._get_player_with_cache(target, roomid or "") if not giver or not receiver: client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "双方需已注册", sender) if self.revoke: @@ -1108,6 +1141,7 @@ class XiuxianPlugin(MessagePluginInterface): self.xdb.update_player_fields(target, {"spirit_stone": receiver["spirit_stone"]}) except Exception: pass + # 使用_save_player确保同时保存到Redis和MariaDB self._save_player(giver) self._save_player(receiver) self._rate_set(sender, "赠与") @@ -1119,25 +1153,25 @@ class XiuxianPlugin(MessagePluginInterface): async def _cmd_give_item(self, bot: WechatAPIClient, sender: str, roomid: str, content: str) -> Tuple[bool, str]: parts = content.strip().split() if len(parts) < 3: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "命令格式:赠送 目标wxid 物品 数量", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "命令格式:赠送 目标wxid 物品 数量", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" target = parts[0].lstrip("@") item_name = parts[1] try: qty = int(parts[2]) except Exception: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "命令格式:赠送 目标wxid 物品 数量", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "命令格式:赠送 目标wxid 物品 数量", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" - giver = self._get_player(sender) - receiver = self._get_player(target) + giver = self._get_player(sender, roomid or "") + receiver = self._get_player(target, roomid or "") if not giver or not receiver: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "双方需已注册", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "双方需已注册", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" inv_g = giver.get("inventory") or {} if inv_g.get(item_name, 0) < qty or qty <= 0: @@ -1157,8 +1191,8 @@ class XiuxianPlugin(MessagePluginInterface): if self.revoke: self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "转移失败" - self.redis_db.invalidate_player(sender) - self.redis_db.invalidate_player(target) + self.redis_db.invalidate_player(sender, giver.get("group_id", "")) + self.redis_db.invalidate_player(target, receiver.get("group_id", "")) self._save_player(giver) self._save_player(receiver) self._rate_set(sender, "赠送") @@ -1174,11 +1208,11 @@ class XiuxianPlugin(MessagePluginInterface): if self.revoke: self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" - player = self._get_player_with_cache(sender) + player = self._get_player_with_cache(sender, roomid or "") if not player: - client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) - if self.revoke: - self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) + # client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) + # if self.revoke: + # self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "未注册" prefix, _ = self._parse_realm(player.get("realm", "炼气1层")) allowed = {"元婴", "化神", "合体", "大乘", "渡劫", "真仙"} @@ -1198,8 +1232,11 @@ class XiuxianPlugin(MessagePluginInterface): if player and clan_id is not None: player["clan_id"] = int(clan_id) if self.xdb: - self.xdb.update_player_fields(sender, {"clan_id": player["clan_id"]}) - self.redis_db.invalidate_player(sender) + try: + self.xdb.update_player_fields(sender, {"clan_id": player["clan_id"]}) + self.redis_db.invalidate_player(sender, player.get("group_id", "")) + except Exception: + pass self._save_player(player) self._rate_set(sender, "创建门派") client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"✅ 门派已创建:{name}", sender) @@ -1214,7 +1251,7 @@ class XiuxianPlugin(MessagePluginInterface): if self.revoke: self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5) return False, "命令格式错误" - player = self._get_player_with_cache(sender) + player = self._get_player_with_cache(sender, roomid or "") if not player: client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) if self.revoke: @@ -1230,8 +1267,11 @@ class XiuxianPlugin(MessagePluginInterface): return False, "门派不存在" player["clan_id"] = int(cid) if isinstance(cid, str) else cid if self.xdb: - self.xdb.update_player_fields(sender, {"clan_id": player["clan_id"]}) - self.redis_db.invalidate_player(sender) + try: + self.xdb.update_player_fields(sender, {"clan_id": player["clan_id"]}) + self.redis_db.invalidate_player(sender, player.get("group_id", "")) + except Exception: + pass self._save_player(player) self._rate_set(sender, "加入门派") client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"✅ 已加入门派:{name}", sender) @@ -1240,7 +1280,7 @@ class XiuxianPlugin(MessagePluginInterface): return True, "加入门派" async def _cmd_clan_exit(self, bot: WechatAPIClient, sender: str, roomid: str) -> Tuple[bool, str]: - player = self._get_player_with_cache(sender) + player = self._get_player_with_cache(sender, roomid or "") if not player: client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "未注册,请先发送:注册修仙 道号", sender) if self.revoke: @@ -1248,8 +1288,11 @@ class XiuxianPlugin(MessagePluginInterface): return False, "未注册" player["clan_id"] = None if self.xdb: - self.xdb.update_player_fields(sender, {"clan_id": None}) - self.redis_db.invalidate_player(sender) + try: + self.xdb.update_player_fields(sender, {"clan_id": None}) + self.redis_db.invalidate_player(sender, player.get("group_id", "")) + except Exception: + pass self._save_player(player) self._rate_set(sender, "退出门派") client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "✅ 已退出门派", sender)