From 3e33a706b5a7161be118e74ba443add29e1b10c7 Mon Sep 17 00:00:00 2001 From: sin365 <353374337@qq.com> Date: Thu, 22 Jan 2026 18:26:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=85=A8=E6=9C=8D=E9=81=93?= =?UTF-8?q?=E5=85=B7=E7=BB=9F=E8=AE=A1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Data/DataStruct.cs | 50 ++++++++++++- Data/SaveDataCoverter.cs | 31 ++++++++ Program.cs | 158 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 235 insertions(+), 4 deletions(-) diff --git a/Data/DataStruct.cs b/Data/DataStruct.cs index 142f9a1..9ce8110 100644 --- a/Data/DataStruct.cs +++ b/Data/DataStruct.cs @@ -1,4 +1,5 @@ using Axibug.MHFSaveAutoConverter.Helper; +using System.Linq; using System.Text; using static Axibug.MHFSaveAutoConverter.DataStruct.DataStruct; using static Axibug.MHFSaveAutoConverter.DataStruct.MHFSaveDataCfg; @@ -261,6 +262,32 @@ namespace Axibug.MHFSaveAutoConverter.DataStruct } public class s_Itembox : s_base_BytesarrayGroup { + public List<(int, int)> GetItemData(bool bSkillNullItem) + { + string str = string.Empty; + + 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]; + } + int id = HexHelper.bytesToInt(itemiddata, 2, 0); + if (bSkillNullItem && id <= 0) + continue; + itemdata.Add((id, HexHelper.bytesToInt(countdata, 2, 0))); + } + return itemdata; + } + public override string ToString() { string str = string.Empty; @@ -286,7 +313,22 @@ namespace Axibug.MHFSaveAutoConverter.DataStruct return str; } - public override bool FixedData(out string log, out bool bneedFixed) + static HashSet aya = new HashSet{ +8139, +8855, +7502, +8335, +8330, +8331, +8332, +9064, +6683, +6687, +7313, +8123, +8136}; + + public override bool FixedData(out string log, out bool bneedFixed) { if (!SrcVerHad) { @@ -325,7 +367,13 @@ namespace Axibug.MHFSaveAutoConverter.DataStruct //9583 月光砂 //bool needfix = (itemid >= 9749); //bool needfix = (itemid >= 9579); + + bool needfix = (itemid >= 9498); + + if (aya.Contains(itemid)) + needfix = true; + if (needfix) { //抹除数据 diff --git a/Data/SaveDataCoverter.cs b/Data/SaveDataCoverter.cs index e1aae49..75cb923 100644 --- a/Data/SaveDataCoverter.cs +++ b/Data/SaveDataCoverter.cs @@ -5,6 +5,7 @@ using NpgsqlTypes; using System.Data; using System.Text; using System.Xml.Linq; +using static Axibug.MHFSaveAutoConverter.DataStruct.DataStruct; using static Axibug.MHFSaveAutoConverter.DataStruct.MHFSaveDataCfg; using static System.Runtime.InteropServices.JavaScript.JSType; @@ -126,5 +127,35 @@ namespace Axibug.MHFSaveAutoConverter.Data return false; } } + + public static bool ReadItemCount(MHFVer from, MHFVer target, byte[] src, int[] itemidList,out Dictionary counterData,bool skiplog = false) + { + try + { + byte[] decdata = MHFCompression.Decompress(src, skiplog); + SaveDataEntity se = new SaveDataEntity(from, target, decdata, false); + s_Itembox itemboxdata = (s_Itembox)se.saveHandles.Where(w => w is s_Itembox).FirstOrDefault(); + List<(int, int)> itemlist = itemboxdata.GetItemData(true); + counterData = new Dictionary(); + + bool skipItemIdCondition = itemidList.Count() > 0 && itemidList[0] == -1; + foreach (var item in itemlist) + { + if (!skipItemIdCondition && !itemidList.Contains(item.Item1)) + continue; + + if (!counterData.ContainsKey(item.Item1)) + counterData[item.Item1] = item.Item2; + else + counterData[item.Item1] += item.Item2; + } + return true; + } + catch (Exception ex) + { + counterData = null; + return false; + } + } } } diff --git a/Program.cs b/Program.cs index 2f2f00a..54ab0be 100644 --- a/Program.cs +++ b/Program.cs @@ -1,7 +1,10 @@ using Axibug.MHFSaveAutoConverter.Data; +using Axibug.MHFSaveAutoConverter.Helper; using HaoYue.MHFUserSrv.Server.Common; using System; using System.Text; +using System.Xml.Linq; +using static Axibug.MHFSaveAutoConverter.DataStruct.DataStruct; using static Axibug.MHFSaveAutoConverter.DataStruct.MHFSaveDataCfg; namespace Axibug.MHFSaveAutoConverter @@ -14,6 +17,12 @@ namespace Axibug.MHFSaveAutoConverter //MH2DosSaveDataLoader.LoadSaveData(); Console.Title = "皓月云MHF存档迁移工具 ver 0.1.0"; Console.WriteLine("读取配置"); + while (true) + MainMenu();~ + } + + static void MainMenu() + { try { Config.LoadCfg("cfg.ini"); @@ -32,7 +41,7 @@ namespace Axibug.MHFSaveAutoConverter int funcid = 0; while (true) { - Console.WriteLine("Step0.使用什么功能?[0]存档继承,[1]存档修复 What function to use? [0] userdata inheritance, [1] userdata repair"); + Console.WriteLine("Step0.使用什么功能?[0]存档继承,[1]存档修复,[2]道具統計 What function to use? [0] userdata inheritance, [1] userdata repair"); string var = Console.ReadLine(); if (!int.TryParse(var, out funcid)) continue; @@ -45,6 +54,11 @@ namespace Axibug.MHFSaveAutoConverter FixedItemBox(); break; } + else if (funcid == 2) + { + ItemCounterItemBox(); + break; + } string[] verlist = Enum.GetNames(typeof(MHFVer)); @@ -141,8 +155,6 @@ namespace Axibug.MHFSaveAutoConverter } } - - public static bool FixedItemBox() { string[] verlist = Enum.GetNames(typeof(MHFVer)); @@ -246,5 +258,145 @@ namespace Axibug.MHFSaveAutoConverter Console.WriteLine($"写入玩家{name}修正数据"); return true; } + + public static bool ItemCounterItemBox() + { + string[] verlist = Enum.GetNames(typeof(MHFVer)); + MHFVer src; + List idsArr = new List(); + while (true) + { + Console.WriteLine("Step1.选择MHF版本: Select the original MHF version :"); + 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($"step2.请输入要统计的道具ID用,隔开,-1代表所有道具一起统计"); + string inputItemIDs = Console.ReadLine().Trim(); + if (string.IsNullOrEmpty(inputItemIDs)) + { + Console.WriteLine("输入有误"); + return false; + } + string[] idsStrArr = inputItemIDs.Split(','); + idsArr.Clear(); + if (idsStrArr.Length < 1) + { + Console.WriteLine("输入有误"); + return false; + } + foreach (string id in idsStrArr) + { + if (!int.TryParse(id, out int val)) + { + Console.WriteLine("输入有误"); + return false; + } + idsArr.Add(val); + if (val == -1) + { + idsArr.Clear(); + idsArr.Add(val); + Console.WriteLine($"统计任何道具"); + break; + } + string itemname = MHHelper.Get2MHFItemName(val); + Console.WriteLine($"需要统计{val}:{itemname}"); + } + Console.WriteLine("==開始統計=="); + Dictionary allServerCounter = new Dictionary(); + Dictionary allServerTop = new Dictionary(); + if (!SaveDataCoverter.GetAllCharcterOLD(out var cidList)) + return false; + + for (int i = 0; i < cidList.Count; i++) + { + long targetCid = cidList[i]; + if (595 == targetCid) + continue; + ItemCounterBoxByCid(src, targetCid, idsArr.ToArray(), out string charname, out Dictionary counterData); + + foreach (var data in counterData) + { + if (!allServerCounter.ContainsKey(data.Key)) + { + allServerCounter[data.Key] = data.Value; + } + else + allServerCounter[data.Key] += data.Value; + + + if (!allServerTop.ContainsKey(data.Key)) + allServerTop[data.Key] = new(targetCid, data.Key, charname, data.Value); + else + { + if (data.Value > allServerTop[data.Key].count) + { + allServerTop[data.Key] = new(targetCid, data.Key, charname, data.Value); + } + } + } + } + + string logall = string.Empty; + + Console.WriteLine($"--------全服道具统计-------"); + logall += ($"--------全服道具统计-------\r\n"); + foreach (var item in allServerCounter.OrderByDescending(w => w.Value)) + { + string log = $" =>{item.Key} {MHHelper.Get2MHFItemName(item.Key)}: 共{item.Value}个"; + logall += ($" {MHHelper.Get2MHFItemName(item.Key)}: 共{item.Value}个\r\n"); + Console.WriteLine(log); + } + Console.WriteLine($"--------全服拥有道具排行-------"); + logall += ($"--------全服拥有道具排行-------\r\n"); + foreach (var item in allServerTop.Values.OrderByDescending(w => w.count)) + { + string log = $" =>玩家{item.rname} 拥有最多数量的 {MHHelper.Get2MHFItemName(item.itemid)}: 共{item.count}个"; + logall += ($"{log}\r\n"); + Console.WriteLine(log); + } + + File.WriteAllText($"全服道具统计{DateTime.Now.ToString("yyyyMMddHHmmss")}.txt", logall); + return true; + } + + + public static bool ItemCounterBoxByCid(MHFVer src,long cid, int[] itemidList, out string charname, out Dictionary counterData) + { + counterData = null; + if (!SaveDataCoverter.loadCharacterOLD(cid, out charname, out bool is_female, out byte[] srcdata)) + { + Console.WriteLine("读取失败"); + return false; + } + + if (!SaveDataCoverter.ReadItemCount(src, src, srcdata, itemidList,out counterData, true)) + { + Console.WriteLine($"处理失败"); + return false; + } + + if (counterData.Count > 0) + { + Console.WriteLine($"--------玩家cid=>{cid} : {charname} 拥有道具-------"); + foreach (var item in counterData) + { + string log = $" =>{item.Key} {MHHelper.Get2MHFItemName(item.Key)}: 数量:{item.Value}"; + Console.WriteLine(log); + } + } + return true; + } } }