From a83c97166c7df4ef246161491888164e11c28228 Mon Sep 17 00:00:00 2001 From: sin365 <353374337@qq.com> Date: Fri, 19 Sep 2025 18:25:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AD=98=E6=A1=A3=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Data/DataStruct.cs | 90 ++++++++++++---- Data/MH2DosSaveDataLoader.cs | 195 +++++++++++++++++++++++++++++++++++ Data/SaveDataCoverter.cs | 40 +++++++ Data/SaveDataEntity.cs | 30 ++++++ Program.cs | 89 +++++++++++++--- SQL/SQLRUN_SRC_DB.cs | 37 ++++++- 6 files changed, 445 insertions(+), 36 deletions(-) create mode 100644 Data/MH2DosSaveDataLoader.cs diff --git a/Data/DataStruct.cs b/Data/DataStruct.cs index c733eec..d59a705 100644 --- a/Data/DataStruct.cs +++ b/Data/DataStruct.cs @@ -64,6 +64,11 @@ namespace Axibug.MHFSaveAutoConverter.DataStruct { return this.ToString(); } + + public virtual bool FixedData(out string log) + { + throw new NotImplementedException(); + } } public class s_base_Byte : s_Base @@ -269,10 +274,10 @@ namespace Axibug.MHFSaveAutoConverter.DataStruct int startptr = (block * SrcCfg.block_single_len); for (int i = 0; i < SrcCfg.block_single_len; i++) { - if (i == 4) itemiddata[0] = data[startptr + i]; - if (i == 5) itemiddata[1] = data[startptr + i]; - if (i == 6) countdata[0] = data[startptr + i]; - if (i == 7) countdata[1] = data[startptr + i]; + if (i == 0) itemiddata[0] = data[startptr + i]; + if (i == 1) itemiddata[1] = data[startptr + i]; + if (i == 2) countdata[0] = data[startptr + i]; + if (i == 3) countdata[1] = data[startptr + i]; } itemdata.Add((HexHelper.bytesToInt(itemiddata, 2, 0), HexHelper.bytesToInt(countdata, 2, 0))); } @@ -280,7 +285,55 @@ namespace Axibug.MHFSaveAutoConverter.DataStruct str += $"{MHHelper.Get2MHFItemName(item.Item1)}:{item.Item2}\r\n"; return str; } + + public override bool FixedData(out string log) + { + if (!SrcVerHad) + { + log = "没有数据"; + return false; + } + + log = this.GetType().Name + "\r\n"; + byte[] itemiddata = new byte[2]; + byte[] countdata = new byte[2]; + List<(int, int)> itemdata = new List<(int, int)>(); + for (int block = 0; block < SrcCfg.block_count; block++) + { + int startptr = (block * SrcCfg.block_single_len); + for (int i = 0; i < SrcCfg.block_single_len; i++) + { + if (i == 0) itemiddata[0] = data[startptr + i]; + if (i == 1) itemiddata[1] = data[startptr + i]; + if (i == 2) countdata[0] = data[startptr + i]; + if (i == 3) countdata[1] = data[startptr + i]; + } + + uint itemid = HexHelper.bytesToUInt(itemiddata, 2, 0); + uint count = HexHelper.bytesToUInt(countdata, 2, 0); + if (itemid < 0) + continue; + + //log += $"[{block}]{itemid}:{MHHelper.Get2MHFItemName((int)itemid)}:{count}\r\n"; + + if (SrcVer == MHFVer.GG) + { + bool needfix = (itemid >= 9749); + + if (needfix) + { + //抹除数据 + for (int i = 0; i < SrcCfg.block_single_len; i++) + data[startptr + i] = 0x00; + log += $"抹除数据:[{block}]{itemid}:{MHHelper.Get2MHFItemName((int)itemid)}:{count}\r\n"; + } + } + } + + return false; + } } + public class s_pPlaytime : s_4byte_UInt32_Base { public override string ToString() @@ -340,18 +393,18 @@ namespace Axibug.MHFSaveAutoConverter.DataStruct public class s_SR_重弩 : s_4byte_UInt32_Base { } public class s_SR_弓 : s_4byte_UInt32_Base { } - public class s_SR_片手_Status1 : s_base_Byte{} - public class s_SR_双刀_Status1 :s_base_Byte{} - public class s_SR_大剑_Status1 :s_base_Byte{} - public class s_SR_太刀_Status1 :s_base_Byte{} - public class s_SR_锤子_Status1 :s_base_Byte{} - public class s_SR_笛_Status1 :s_base_Byte{} - public class s_SR_长枪_Status1 :s_base_Byte{} - public class s_SR_铳枪_Status1 :s_base_Byte{} - public class s_SR_穿龙棍_Status1 :s_base_Byte{} - public class s_SR_轻弩_Status1 :s_base_Byte{} - public class s_SR_重弩_Status1 :s_base_Byte{} - public class s_SR_弓_Status1 : s_base_Byte {} + public class s_SR_片手_Status1 : s_base_Byte { } + public class s_SR_双刀_Status1 : s_base_Byte { } + public class s_SR_大剑_Status1 : s_base_Byte { } + public class s_SR_太刀_Status1 : s_base_Byte { } + public class s_SR_锤子_Status1 : s_base_Byte { } + public class s_SR_笛_Status1 : s_base_Byte { } + public class s_SR_长枪_Status1 : s_base_Byte { } + public class s_SR_铳枪_Status1 : s_base_Byte { } + public class s_SR_穿龙棍_Status1 : s_base_Byte { } + public class s_SR_轻弩_Status1 : s_base_Byte { } + public class s_SR_重弩_Status1 : s_base_Byte { } + public class s_SR_弓_Status1 : s_base_Byte { } public class s_SR_片手_Status2 : s_base_Byte { } public class s_SR_双刀_Status2 : s_base_Byte { } @@ -412,8 +465,9 @@ namespace Axibug.MHFSaveAutoConverter.DataStruct public class s_pRP : s_2byte_Int16_Base { } public class s_pKQF : s_base_Bytesarray { } public class ExtraBox背包 : s_base_BytesarrayGroup { } - public class s_ItemPouch背包 : s_base_BytesarrayGroup { - + public class s_ItemPouch背包 : s_base_BytesarrayGroup + { + public override string ToString() { string str = string.Empty; diff --git a/Data/MH2DosSaveDataLoader.cs b/Data/MH2DosSaveDataLoader.cs new file mode 100644 index 0000000..63e604f --- /dev/null +++ b/Data/MH2DosSaveDataLoader.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.IO; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace MonsterHunterSaveBruteForce +{ + class MH2DosSaveDataLoader + { + // 已知数值常量 + private const ushort KnownMoney = 5929; // 0x1729 + private const ushort KnownExp = 6525; // 0x197D + private const ushort ItemLargePotion = 0x0008; // 回復藥・大 的ID + private const ushort ItemLargePotionQty = 5; // 回復藥・大 的数量 + + // 道具箱特征(前6个道具) + private static readonly List<(ushort id, ushort quantity)> ItemPattern = new List<(ushort, ushort)> + { + (0x0001, 1), // 調合書①入門編 + (0x0002, 1), // 調合書②初級編 + (0x0003, 1), // 調合書③中級編 + (0x0007, 3), // 回復藥 + (ItemLargePotion, ItemLargePotionQty), // 回復藥・大 + (0x0015, 2) // 冷飲 + }; + + public static void LoadSaveData() + { + Console.WriteLine("===== PS2怪物猎人2存档暴力破解工具 ====="); + Console.WriteLine("此工具使用金钱、经验和道具特征进行暴力破解"); + + // 1. 加载存档 + byte[] saveData = File.ReadAllBytes("play00.bin"); + Console.WriteLine($"存档大小: {saveData.Length} 字节"); + + // 2. 暴力破解 + BruteForceDecryption(saveData); + } + + static void BruteForceDecryption(byte[] data) + { + Console.WriteLine("开始暴力破解,这可能需要一些时间..."); + var stopwatch = System.Diagnostics.Stopwatch.StartNew(); + int totalAttempts = 0; + const int reportInterval = 100000; // 每100,000次尝试报告一次进度 + + // 限制搜索范围提高效率 + //int searchRange = Math.Min(0x10000, data.Length - 20); + int searchRange = data.Length - 20; + + // 尝试所有可能的密钥组合 (0x0000 - 0xFFFF) + for (ushort key = 0; key < ushort.MaxValue; key++) + { + // 解密整个存档 + byte[] decrypted = DecryptWithKey(data, key); + + // 验证金钱和经验值 + var (moneyFound, expFound) = ValidateMoneyAndExp(decrypted); + + // 验证道具箱特征 + //bool itemsValid = ValidateItemBox(decrypted); + + bool itemsValid = true; + + // 如果三项验证都通过 + //if (moneyFound && expFound && itemsValid) + if(ValidateName(decrypted)) + { + stopwatch.Stop(); + Console.WriteLine($"\n暴力破解成功! 密钥: 0x{key:X4}"); + Console.WriteLine($"耗时: {stopwatch.Elapsed.TotalSeconds:F2} 秒"); + Console.WriteLine($"尝试次数: {totalAttempts}"); + + // 保存解密文件 + //File.WriteAllBytes("decrypted_play00.bin", decrypted); + Console.WriteLine("解密文件已保存: decrypted_play00.bin"); + return; + } + + // 报告进度 + if (++totalAttempts % reportInterval == 0) + { + Console.WriteLine($"已尝试 {totalAttempts} 种密钥组合... 当前密钥: 0x{key:X4}"); + } + } + + stopwatch.Stop(); + Console.WriteLine($"\n暴力破解完成,但未找到有效密钥。耗时: {stopwatch.Elapsed.TotalSeconds:F2} 秒"); + Console.WriteLine($"总尝试次数: {totalAttempts}"); + } + + static byte[] DecryptWithKey(byte[] data, ushort key) + { + byte[] keyBytes = BitConverter.GetBytes(key); + byte[] decrypted = new byte[data.Length]; + + for (int i = 0; i < data.Length; i++) + { + decrypted[i] = (byte)(data[i] ^ keyBytes[i % 2]); + } + return decrypted; + } + + static (bool moneyFound, bool expFound) ValidateMoneyAndExp(byte[] decrypted) + { + bool moneyFound = false; + bool expFound = false; + + // 扫描整个文件寻找金钱和经验值 + for (int i = 0; i < decrypted.Length - 1; i++) + { + ushort value = BitConverter.ToUInt16(decrypted, i); + + // 检查是否是金钱值 + if (value == KnownMoney) + { + moneyFound = true; + } + + // 检查是否是经验值 + if (value == KnownExp) + { + expFound = true; + } + + // 如果两个都已找到,提前退出 + if (moneyFound && expFound) + { + break; + } + } + + return (moneyFound, expFound); + } + + static bool ValidateName(byte[] data) + { + byte[] checkdata = new byte[4] { 0xE1, 0xA9, 0x8C, 0x8E }; + // 扫描整个文件寻找道具箱特征 + for (int offset = 0; offset < data.Length - checkdata.Length; offset++) + { + for (int i = 0; i < checkdata.Length; i++) + { + if (data[0] == checkdata[0] + && data[1] == checkdata[1] + && data[2] == checkdata[2] + && data[3] == checkdata[3]) + return true; + } + } + + return false; + } + + static bool ValidateItemBox(byte[] decrypted) + { + // 尝试不同的道具结构 (4字节和8字节) + return ValidateItemStructure(decrypted, 4) || ValidateItemStructure(decrypted, 8); + } + + static bool ValidateItemStructure(byte[] data, int slotSize) + { + // 扫描整个文件寻找道具箱特征 + for (int offset = 0; offset < data.Length - (slotSize * 6); offset++) + { + bool patternMatch = true; + + // 检查前6个道具是否匹配已知模式 + for (int slot = 0; slot < 6; slot++) + { + int slotOffset = offset + (slot * slotSize); + + // 获取道具ID和数量 + ushort itemId = BitConverter.ToUInt16(data, slotOffset); + ushort quantity = BitConverter.ToUInt16(data, slotOffset + 2); + + // 检查是否匹配预期值 + if (itemId != ItemPattern[slot].id || quantity != ItemPattern[slot].quantity) + { + patternMatch = false; + break; + } + } + + // 如果找到匹配模式 + if (patternMatch) + { + return true; + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/Data/SaveDataCoverter.cs b/Data/SaveDataCoverter.cs index 7a713f7..39fcf38 100644 --- a/Data/SaveDataCoverter.cs +++ b/Data/SaveDataCoverter.cs @@ -1,5 +1,7 @@ using Axibug.MHFSaveAutoConverter.DataStruct; using Axibug.MHFSaveAutoConverter.SQL; +using Npgsql; +using NpgsqlTypes; using System.Data; using System.Text; using static Axibug.MHFSaveAutoConverter.DataStruct.MHFSaveDataCfg; @@ -8,6 +10,24 @@ namespace Axibug.MHFSaveAutoConverter.Data { public class SaveDataCoverter { + + public static bool InsertTargetDB_new(long uid, bool is_female, string name, byte[] targetdata) + { + string str = "INSERT INTO \"public\".\"characters\" (\"user_id\", \"is_female\", \"is_new_character\", \"name\", \"unk_desc_string\", \"gr\", \"hr\", \"weapon_type\", \"last_login\", \"savedata\", \"decomyset\", \"hunternavi\", \"otomoairou\", \"partner\", \"platebox\", \"platedata\", \"platemyset\", \"rengokudata\", \"savemercenary\", \"restrict_guild_scout\", \"minidata\", \"gacha_items\", \"daily_time\", \"house_info\", \"login_boost\", \"skin_hist\", \"kouryou_point\", \"gcp\", \"guild_post_checked\", \"time_played\", \"weapon_id\", \"scenariodata\", \"savefavoritequest\", \"friends\", \"blocked\", \"deleted\", \"cafe_time\", \"netcafe_points\", \"boost_time\", \"cafe_reset\", \"bonus_quests\", \"daily_quests\", \"promo_points\", \"rasta_id\", \"pact_id\", \"stampcard\", \"mezfes\") " + + $"VALUES ({uid}, '{(is_female ? "t" : "f")}', 'f', '{name}', '', 0, 0, 0, 1750087006, @savedata, NULL, NULL, NULL, E'\\\\001cmp 20110113 \\\\000\\\\000\\\\002\\\\001\\\\250\\\\000\\\\377\\\\000\\\\255'::bytea, NULL, NULL, NULL, NULL, NULL, 'f', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2025-05-26 11:24:26.725902+08', 0, 0, E'\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000'::bytea, E'\\\\001\\\\000\\\\001\\\\000\\\\001\\\\000\\\\001\\\\000\\\\001\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000'::bytea, '', '', 'f', 0, 0, NULL, NULL, 0, 0, 0, NULL, NULL, 0, NULL);"; + var savedataparam = new NpgsqlParameter("@savedata", NpgsqlDbType.Bytea); + savedataparam.Value = targetdata; + return SQLRUN_TARGET_DB.ExcuteSQL(str, new List { savedataparam }); + } + + + public static bool UpdateTargetDB_old(long cid, byte[] targetdata) + { + string str = $"UPDATE \"characters\" set savedata = @savedata where \"id\" = {cid};"; + var savedataparam = new NpgsqlParameter("@savedata", NpgsqlDbType.Bytea); + savedataparam.Value = targetdata; + return SQLRUN_SRC_DB.ExcuteSQL(str, new List { savedataparam }); + } public static bool loadCharacterOLD(long cid, out string name, out bool is_female, out byte[] data) { string sql = $"SELECT \"name\",savedata,is_female from \"characters\" WHERE id = {cid}"; @@ -60,5 +80,25 @@ namespace Axibug.MHFSaveAutoConverter.Data return false; } } + + + public static bool FixedSaveData(MHFVer from, MHFVer target, byte[] src, out byte[] targetdata, out string err) + { + try + { + byte[] decdata = MHFCompression.Decompress(src); + SaveDataEntity se = new SaveDataEntity(from, target, decdata); + targetdata = se.FixedEquipBox(decdata, out string log); + err = default; + Console.WriteLine(log); + return true; + } + catch (Exception ex) + { + err = ex.ToString(); + targetdata = default; + return false; + } + } } } diff --git a/Data/SaveDataEntity.cs b/Data/SaveDataEntity.cs index 01bb7d7..4014db1 100644 --- a/Data/SaveDataEntity.cs +++ b/Data/SaveDataEntity.cs @@ -2,6 +2,7 @@ using System.Data; using static Axibug.MHFSaveAutoConverter.DataStruct.DataStruct; using static Axibug.MHFSaveAutoConverter.DataStruct.MHFSaveDataCfg; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace Axibug.MHFSaveAutoConverter.DataStruct { public class SaveDataEntity @@ -70,6 +71,35 @@ namespace Axibug.MHFSaveAutoConverter.DataStruct Console.WriteLine("====写入完毕===="); return data; } + + + + public byte[] FixedEquipBox(byte[] srcdata, out string log) + { + log = null; + byte[] targetdata = srcdata.ToArray(); + + Console.WriteLine("====尝试开始写入===="); + foreach (var singledata in saveHandles) + { + if (!(singledata is s_Itembox itembox)) + continue; + + itembox.FixedData(out log); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine(singledata.GetType().Name); + Console.ForegroundColor = ConsoleColor.White; + string str = singledata.ToString(); + if (str.Length > 100) + str = str.Substring(0, 100) + "..."; + + bool ret = singledata.Write(TargetVer, targetdata); + Console.WriteLine($"写入:{singledata.GetType().Name} =>{(ret ? "成功" : "失败")}"); + Console.WriteLine(str); + } + Console.WriteLine("====写入完毕===="); + return targetdata; + } } } diff --git a/Program.cs b/Program.cs index 4d239d0..cf38448 100644 --- a/Program.cs +++ b/Program.cs @@ -1,8 +1,12 @@ using Axibug.MHFSaveAutoConverter.Data; +using Axibug.MHFSaveAutoConverter.DataStruct; using Axibug.MHFSaveAutoConverter.SQL; using HaoYue.MHFUserSrv.Server.Common; +using MonsterHunterSaveBruteForce; using Npgsql; using NpgsqlTypes; +using System; +using System.Runtime.ConstrainedExecution; using System.Text; using static Axibug.MHFSaveAutoConverter.DataStruct.MHFSaveDataCfg; @@ -13,6 +17,7 @@ namespace Axibug.MHFSaveAutoConverter static void Main(string[] args) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + //MH2DosSaveDataLoader.LoadSaveData(); Console.Title = "皓月云MHF存档迁移工具 ver 0.1.0"; Console.WriteLine("读取配置"); try @@ -29,8 +34,26 @@ namespace Axibug.MHFSaveAutoConverter while (true) { Console.WriteLine($"==欢迎使用 {Console.Title} Axibug.MHFSaveAutoConverter=="); + + int funcid = 0; + while (true) + { + Console.WriteLine("Step0.使用什么功能?[0]存档继承,[1]存档修复 What function to use? [0] userdata inheritance, [1] userdata repair"); + string var = Console.ReadLine(); + if (!int.TryParse(var, out funcid)) + continue; + + break; + } + + if (funcid == 1) + { + FixedItemBox(); + break; + } + string[] verlist = Enum.GetNames(typeof(MHFVer)); - + MHFVer src; MHFVer target; while (true) @@ -73,7 +96,7 @@ namespace Axibug.MHFSaveAutoConverter continue; } Console.WriteLine("===>操作的角色ID:" + cid); - if (!SaveDataCoverter.loadCharacterOLD(cid, out string name,out bool is_female, out byte[] srcdata)) + if (!SaveDataCoverter.loadCharacterOLD(cid, out string name, out bool is_female, out byte[] srcdata)) { Console.WriteLine("读取失败"); continue; @@ -112,7 +135,7 @@ namespace Axibug.MHFSaveAutoConverter } //if (!UpdateTargetDB(targetuserid, is_female, name, targetdata)) - if (!InsertTargetDB(targetuserid, is_female, name, targetdata)) + if (!SaveDataCoverter.InsertTargetDB_new(targetuserid, is_female, name, targetdata)) { Console.WriteLine($"写入目标{target}数据库失败"); continue; @@ -124,22 +147,54 @@ namespace Axibug.MHFSaveAutoConverter } - public static bool InsertTargetDB(long uid,bool is_female,string name, byte[] targetdata) - { - string str = "INSERT INTO \"public\".\"characters\" (\"user_id\", \"is_female\", \"is_new_character\", \"name\", \"unk_desc_string\", \"gr\", \"hr\", \"weapon_type\", \"last_login\", \"savedata\", \"decomyset\", \"hunternavi\", \"otomoairou\", \"partner\", \"platebox\", \"platedata\", \"platemyset\", \"rengokudata\", \"savemercenary\", \"restrict_guild_scout\", \"minidata\", \"gacha_items\", \"daily_time\", \"house_info\", \"login_boost\", \"skin_hist\", \"kouryou_point\", \"gcp\", \"guild_post_checked\", \"time_played\", \"weapon_id\", \"scenariodata\", \"savefavoritequest\", \"friends\", \"blocked\", \"deleted\", \"cafe_time\", \"netcafe_points\", \"boost_time\", \"cafe_reset\", \"bonus_quests\", \"daily_quests\", \"promo_points\", \"rasta_id\", \"pact_id\", \"stampcard\", \"mezfes\") " + - $"VALUES ({uid}, '{(is_female?"t":"f")}', 'f', '{name}', '', 0, 0, 0, 1750087006, @savedata, NULL, NULL, NULL, E'\\\\001cmp 20110113 \\\\000\\\\000\\\\002\\\\001\\\\250\\\\000\\\\377\\\\000\\\\255'::bytea, NULL, NULL, NULL, NULL, NULL, 'f', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2025-05-26 11:24:26.725902+08', 0, 0, E'\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000'::bytea, E'\\\\001\\\\000\\\\001\\\\000\\\\001\\\\000\\\\001\\\\000\\\\001\\\\000\\\\000\\\\000\\\\000\\\\000\\\\000'::bytea, '', '', 'f', 0, 0, NULL, NULL, 0, 0, 0, NULL, NULL, 0, NULL);"; - var savedataparam = new NpgsqlParameter("@savedata", NpgsqlDbType.Bytea); - savedataparam.Value = targetdata; - return SQLRUN_TARGET_DB.ExcuteSQL(str,new List { savedataparam }); - } - - public static bool UpdateTargetDB(long cid, bool is_female, string name, byte[] targetdata) + public static bool FixedItemBox() { - string str = $"UPDATE \"characters\" set savedata = @savedata where \"id\" = {cid};"; - var savedataparam = new NpgsqlParameter("@savedata", NpgsqlDbType.Bytea); - savedataparam.Value = targetdata; - return SQLRUN_TARGET_DB.ExcuteSQL(str, new List { savedataparam }); + string[] verlist = Enum.GetNames(typeof(MHFVer)); + MHFVer src; + while (true) + { + Console.WriteLine("Step1.选择要继承的角色的原始MHF版本: Select the original MHF version of the character you want to inherit:"); + for (int i = 0; i < verlist.Length; i++) + Console.WriteLine($"[{i}]{verlist[i]}"); + + int srcidx; + string ver = Console.ReadLine(); + if (!int.TryParse(ver, out srcidx)) + continue; + if (srcidx >= 0 && srcidx < verlist.Length) + { + src = (MHFVer)Enum.Parse(typeof(MHFVer), verlist[srcidx]); + break; + } + } + Console.WriteLine($"step3.请输入[{src}]版本中的源Characters表中的角色ID: Please enter the character ID from the source Characters table in [{src}] version:"); + if (!long.TryParse(Console.ReadLine(), out long cid)) + { + Console.WriteLine("输入有误"); + return false; + } + Console.WriteLine("===>操作的角色ID:" + cid); + if (!SaveDataCoverter.loadCharacterOLD(cid, out string name, out bool is_female, out byte[] srcdata)) + { + Console.WriteLine("读取失败"); + return false; + } + + if (!SaveDataCoverter.FixedSaveData(src, src, srcdata, out byte[] targetdata, out string err)) + { + Console.WriteLine($"处理失败:{err}"); + return false; + } + + if (!SaveDataCoverter.UpdateTargetDB_old(cid, targetdata)) + { + Console.WriteLine($"处理失败:{err}"); + return false; + } + + Console.WriteLine($"写入玩家{name}修正数据"); + return true; } //public static SaveDataEntity SetData(long cid, string name, byte[] srcdata) diff --git a/SQL/SQLRUN_SRC_DB.cs b/SQL/SQLRUN_SRC_DB.cs index fbea449..f84b33e 100644 --- a/SQL/SQLRUN_SRC_DB.cs +++ b/SQL/SQLRUN_SRC_DB.cs @@ -88,7 +88,8 @@ namespace Axibug.MHFSaveAutoConverter.SQL } } - public static bool ExcuteSQL(string strSql) + + public static bool ExcuteSQL(string strSql, List param = null) { NpgsqlConnection con = GetSqlConnect(); bool bneedPush = true; @@ -100,6 +101,13 @@ namespace Axibug.MHFSaveAutoConverter.SQL { using (NpgsqlCommand SqlCommand = new NpgsqlCommand(strSqlinsert, con)) { + if (param != null) + { + foreach (NpgsqlParameter p in param) + { + SqlCommand.Parameters.Add(p); + } + } setnumbert = SqlCommand.ExecuteNonQuery(); } PushConnect(con); @@ -115,6 +123,33 @@ namespace Axibug.MHFSaveAutoConverter.SQL return false; } } + //public static bool ExcuteSQL(string strSql) + //{ + // NpgsqlConnection con = GetSqlConnect(); + // bool bneedPush = true; + // if (string.IsNullOrEmpty(strSql)) + // return false; + // string strSqlinsert = strSql; + // int setnumbert = 0; + // try + // { + // using (NpgsqlCommand SqlCommand = new NpgsqlCommand(strSqlinsert, con)) + // { + // setnumbert = SqlCommand.ExecuteNonQuery(); + // } + // PushConnect(con); + // bneedPush = false; + // return true; + // } + // catch (Exception ex) + // { + // if (bneedPush) + // { + // PushConnect(con); + // } + // return false; + // } + //} public static DateTime ConvertTimestamptzToDatetime(object obj) {