import sqlite3 import tkinter as tk from tkinter import ttk import os import json class TeamSwitchPacketGenerator: def __init__(self): # 检查数据库文件是否存在 db_file = 'aola.sqlite' if not os.path.exists(db_file): raise FileNotFoundError(f"数据库文件 {db_file} 未找到,请确保文件在 {os.getcwd()} 目录下!") print(f"数据库文件路径: {os.path.abspath(db_file)}") self.conn = sqlite3.connect(db_file) self.cursor = self.conn.cursor() self.root = tk.Tk() self.root.title("阵容切换封包生成器") # 创建下拉框 self.team_var = tk.StringVar() self.team_dropdown = ttk.Combobox(self.root, textvariable=self.team_var) self.team_dropdown['values'] = self.get_team_names() self.team_dropdown.pack(pady=10) self.team_dropdown.set("请选择阵容") # 创建按钮框架,包含“刷新”和“生成封包”按钮 button_frame = tk.Frame(self.root) button_frame.pack(pady=5) # 刷新按钮 tk.Button(button_frame, text="刷新", command=self.refresh_dropdown).pack(side=tk.LEFT, padx=5) # 生成按钮 tk.Button(button_frame, text="生成封包(第一次生成请先解锁二级密码)", command=self.generate_packets).pack(side=tk.LEFT, padx=5) # 创建 Frame 包含封包输出框和复制按钮 output_frame = tk.Frame(self.root) output_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) # 封包输出框 tk.Label(output_frame, text="封包输出:").pack(anchor=tk.W) self.output_text = tk.Text(output_frame, height=15, width=60) self.output_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) # 复制按钮(放在右侧) tk.Button(output_frame, text="复制脚本", command=self.copy_output).pack(side=tk.RIGHT, padx=5) # 信息提示框 tk.Label(self.root, text="提示信息:").pack(anchor=tk.W) self.info_text = tk.Text(self.root, height=5, width=80, fg="red") self.info_text.pack(pady=5) def get_team_names(self): """从数据库获取所有阵容名称""" try: self.cursor.execute("SELECT team_name FROM aolaer_team order by team_name") return [row[0] for row in self.cursor.fetchall()] except sqlite3.Error as e: self.info_text.insert(tk.END, f"获取阵容名称失败: {e}\n") return [] def refresh_dropdown(self): """刷新下拉框数据""" # 重新获取阵容名称 team_names = self.get_team_names() # 更新下拉框选项 self.team_dropdown['values'] = team_names # 重置选择 self.team_dropdown.set("请选择阵容") # 在提示框中显示刷新成功 self.info_text.insert(tk.END, "下拉框数据已刷新!\n") def copy_output(self): """复制脚本输出框的内容到剪贴板""" content = self.output_text.get(1.0, tk.END).strip() if content: self.root.clipboard_clear() self.root.clipboard_append(content) self.info_text.insert(tk.END, "脚本内容已复制到剪贴板!\n") else: self.info_text.insert(tk.END, "脚本输出框为空,无法复制!\n") def validate_ids(self, ids_str): """验证 ids 数组,确保格式正确""" try: ids = json.loads(ids_str) if not isinstance(ids, list) or len(ids) != 5: return False, "ids 必须是长度为 5 的数组" for x in ids: if not isinstance(x, int) or x < 0: return False, "ids 中的值必须是非负整数" return True, ids except json.JSONDecodeError: return False, "ids 格式不正确" def generate_packets(self): """生成封包代码""" self.output_text.delete(1.0, tk.END) self.info_text.delete(1.0, tk.END) packets = [] selected_team = self.team_var.get() if not selected_team or selected_team == "请选择阵容": self.info_text.insert(tk.END, "请先选择一个阵容!\n") return try: # 获取 team_code 和 team_set self.cursor.execute("SELECT team_code, team_set FROM aolaer_team WHERE team_name = ?", (selected_team,)) result = self.cursor.fetchone() if not result: self.info_text.insert(tk.END, f"未找到阵容 {selected_team} 的 team_code!\n") return team_code, team_set = result packets.append(f'|#send={{"id":13,"param":{{"pms":"{team_code}"}},"cmd":"1222"}}|') # 处理 is_set = 1 的记录(重置魂卡) self.cursor.execute("SELECT id FROM aolaer_id WHERE is_set = 1") set_ids = [row[0] for row in self.cursor.fetchall()] for set_id in set_ids: packets.append( f'|#send={{"id":42,"param":{{"bk":1,"petId":{set_id},"ids":[0,0,0,0,0]}},"cmd":"ASC221104_2"}}|') self.cursor.execute("UPDATE aolaer_id SET is_set = 0 WHERE id = ?", (set_id,)) self.conn.commit() # 处理 team_code 中的 ID team_ids = team_code.split('#') team_ids = [id for id in team_ids if id] # 处理 team_set team_set_codes = None if team_set: team_set_codes = team_set.split('#') if len(team_set_codes) != len(team_ids): self.info_text.insert(tk.END, f"警告:team_set 的长度 ({len(team_set_codes)}) 与 team_code 的 ID 数量 ({len(team_ids)}) 不匹配!\n") return # 查询 aolaer_id 表 self.cursor.execute( "SELECT id, div_weapon, aolaer_typecode FROM aolaer_id WHERE id IN ({})".format( ','.join('?' for _ in team_ids) ), team_ids ) id_to_typecode = {row[0]: row for row in self.cursor.fetchall()} # 分组生成封包,确保顺序:子宠物 → 魂艺 → 魂卡 sub_pet_packets = [] soul_art_packets = [] soul_card_packets = [] for idx, id in enumerate(team_ids): id = int(id) if id not in id_to_typecode: self.info_text.insert(tk.END, f"警告:ID {id} 在 aolaer_id 表中不存在!\n") continue div_weapon = id_to_typecode[id][1] typecode = id_to_typecode[id][2] if team_set_codes and team_set_codes[idx] != '0': typecode = team_set_codes[idx] # 生成子宠物封包(即使 div_weapon 为空,也生成占位封包) if div_weapon is not None and str(div_weapon).strip(): sub_pet_packets.append( f'|#send={{"id":42,"param":{{"subPetId":{id},"petId":{div_weapon}}},"cmd":"ASBS230623_con"}}|') else: sub_pet_packets.append( f'|#send={{"id":42,"param":{{"subPetId":{id},"petId":0}},"cmd":"ASBS230623_con"}}|') self.info_text.insert(tk.END, f"提示:ID {id} 的 div_weapon 为空,使用默认值 0 生成子宠物封包!\n") # 获取 soul_art 和 soul_card self.cursor.execute("SELECT soul_art, soul_card FROM aolaer_type WHERE aolaer_typecode = ?", (typecode,)) result = self.cursor.fetchone() if not result: self.info_text.insert(tk.END, f"警告:typecode {typecode} 在 aolaer_type 表中不存在!\n") continue soul_art, soul_card = result # 生成魂艺封包(即使 soul_art 为空,也生成占位封包) if soul_art and soul_art.strip(): try: sid1, sid2 = soul_art.split(',') soul_art_packets.append( f'|#send={{"id":42,"param":{{"ui":{sid1},"petId":{id}}},"cmd":"ATT231229_1"}}|') soul_art_packets.append( f'|#send={{"id":42,"param":{{"ui":{sid2},"petId":{id}}},"cmd":"ATT231229_1"}}|') except ValueError: self.info_text.insert(tk.END, f"错误:soul_art 格式不正确 for typecode {typecode}!\n") continue else: soul_art_packets.append(f'|#send={{"id":42,"param":{{"ui":0,"petId":{id}}},"cmd":"ATT231229_1"}}|') soul_art_packets.append(f'|#send={{"id":42,"param":{{"ui":0,"petId":{id}}},"cmd":"ATT231229_1"}}|') self.info_text.insert(tk.END, f"提示:typecode {typecode} 的 soul_art 为空,使用默认值 0 生成魂艺封包!\n") # 生成魂卡封包 if soul_card and soul_card.strip(): is_valid, ids_or_error = self.validate_ids(soul_card) if is_valid: soul_card_packets.append( f'|#send={{"id":42,"param":{{"bk":1,"petId":{id},"ids":{soul_card}}},"cmd":"ASC221104_2"}}|') self.cursor.execute("UPDATE aolaer_id SET is_set = 1 WHERE id = ?", (id,)) self.conn.commit() else: self.info_text.insert(tk.END, f"警告:typecode {typecode} 的 soul_card {soul_card} 无效({ids_or_error}),已跳过处理!\n") else: self.info_text.insert(tk.END, f"提示:typecode {typecode} 的 soul_card 为空,已跳过处理!\n") # 按顺序添加封包:子宠物 → 魂艺 → 魂卡 packets.extend(sub_pet_packets) packets.extend(soul_art_packets) packets.extend(soul_card_packets) if packets: self.output_text.insert(tk.END, '\n'.join(packets)) else: self.info_text.insert(tk.END, "未生成任何封包,请检查数据!\n") except sqlite3.Error as e: self.info_text.insert(tk.END, f"数据库操作失败: {e}\n") def run(self): """运行程序""" self.root.mainloop() def __del__(self): """清理数据库连接""" self.conn.close() if __name__ == "__main__": app = TeamSwitchPacketGenerator() app.run()