导入导出修改的功能
This commit is contained in:
parent
6fdc6327e7
commit
cebb390167
@ -24,6 +24,20 @@ namespace MHFOldShopTools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool LoadFile(string FilePath, out string[] lines)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lines = File.ReadAllLines(FilePath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
lines = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string[] GetDirFile(string Path)
|
public static string[] GetDirFile(string Path)
|
||||||
{
|
{
|
||||||
return Directory.GetFiles(Path);
|
return Directory.GetFiles(Path);
|
||||||
@ -33,6 +47,7 @@ namespace MHFOldShopTools
|
|||||||
{
|
{
|
||||||
return Encoding.Default.GetBytes(value);
|
return Encoding.Default.GetBytes(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool SaveFile(string FilePath, byte[] buffer)
|
public static bool SaveFile(string FilePath, byte[] buffer)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -52,5 +67,11 @@ namespace MHFOldShopTools
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void SaveFile(string FilePath, string[] strArr)
|
||||||
|
{
|
||||||
|
System.IO.File.WriteAllLines(FilePath, strArr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
190
Program.cs
190
Program.cs
@ -1,4 +1,5 @@
|
|||||||
using System.Text;
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace MHFOldShopTools
|
namespace MHFOldShopTools
|
||||||
{
|
{
|
||||||
@ -6,8 +7,7 @@ namespace MHFOldShopTools
|
|||||||
{
|
{
|
||||||
static string loc = Path.GetDirectoryName(AppContext.BaseDirectory) + "\\";
|
static string loc = Path.GetDirectoryName(AppContext.BaseDirectory) + "\\";
|
||||||
|
|
||||||
const string InDir = "Input";
|
const string InDir = "Files";
|
||||||
const string OutDir = "Out";
|
|
||||||
const string Ver = "0.1";
|
const string Ver = "0.1";
|
||||||
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
@ -19,42 +19,45 @@ namespace MHFOldShopTools
|
|||||||
|
|
||||||
if (!Directory.Exists(loc + InDir))
|
if (!Directory.Exists(loc + InDir))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Input文件不存在");
|
Console.WriteLine("Files文件不存在");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (!Directory.Exists(loc + OutDir))
|
|
||||||
//{
|
|
||||||
// Console.WriteLine("Out文件不存在");
|
|
||||||
// Console.ReadLine();
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (!Directory.Exists(loc + PosFile2DosDir))
|
|
||||||
//{
|
|
||||||
// Console.WriteLine("Templete文件不存在");
|
|
||||||
// Console.ReadLine();
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
|
|
||||||
|
|
||||||
|
int bflag = 0;
|
||||||
|
|
||||||
string[] files = FileHelper.GetDirFile(loc + InDir);
|
string[] files = FileHelper.GetDirFile(loc + InDir);
|
||||||
Console.WriteLine($"共{files.Length}个文件,是否处理? (y/n)");
|
while (true)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"请确保Files目录中已放置解密的MHF-FW5 mhfdat.bin文件,请选择:");
|
||||||
|
Console.WriteLine($"[1],解析Files目录中bin文件,生成同名txt清单和csv表");
|
||||||
|
Console.WriteLine($"[2],解析Files目录中csv文件,修改回同名的bin文件中");
|
||||||
|
Console.WriteLine($"Please ensure that the decrypted MHF-FW5 mhfdat.bin file is placed in the Files directory. Please select:");
|
||||||
|
Console.WriteLine($"[1],Parse the .bin file in the Files directory and generate a .txt list and .csv table with the same name");
|
||||||
|
Console.WriteLine($"[2],Parse the .csv file in the Files directory and modify it back to the .bin file with the same name");
|
||||||
|
|
||||||
string yn = Console.ReadLine();
|
string yn = Console.ReadLine();
|
||||||
if (yn.ToLower() != "y")
|
if (yn.ToLower() == "1")
|
||||||
return;
|
bflag = 1;
|
||||||
|
else if(yn.ToLower() == "2")
|
||||||
|
bflag = 2;
|
||||||
|
|
||||||
|
if (bflag != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bflag == 1)
|
||||||
|
{
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int errcount = 0;
|
int errcount = 0;
|
||||||
for (int i = 0; i < files.Length; i++)
|
for (int i = 0; i < files.Length; i++)
|
||||||
{
|
{
|
||||||
string FileName = files[i].Substring(files[i].LastIndexOf("\\"));
|
string FileName = files[i].Substring(files[i].LastIndexOf("\\"));
|
||||||
|
|
||||||
if (!FileName.ToLower().Contains(".bin"))
|
if (System.IO.Path.GetExtension(FileName).ToLower() != ".bin")
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -63,8 +66,50 @@ namespace MHFOldShopTools
|
|||||||
Console.WriteLine($">>>>>>>>>>>>>>开始处理 第{index}个文件 {FileName}<<<<<<<<<<<<<<<<<<<");
|
Console.WriteLine($">>>>>>>>>>>>>>开始处理 第{index}个文件 {FileName}<<<<<<<<<<<<<<<<<<<");
|
||||||
FileHelper.LoadFile(files[i], out byte[] data);
|
FileHelper.LoadFile(files[i], out byte[] data);
|
||||||
|
|
||||||
ReaderItems(data);
|
ReaderItems(data, out List<string> OutInputString, out List<string> outPutCsv);
|
||||||
Console.WriteLine($">>>>>>>>>>>>>>处理完毕");
|
|
||||||
|
|
||||||
|
string listfileName = System.IO.Path.GetFileNameWithoutExtension(FileName) + ".txt";
|
||||||
|
string listoutpath = loc + InDir + "\\" + listfileName;
|
||||||
|
FileHelper.SaveFile(listoutpath, OutInputString.ToArray());
|
||||||
|
|
||||||
|
string csvfileName = System.IO.Path.GetFileNameWithoutExtension(FileName) + ".csv";
|
||||||
|
string csvoutpath = loc + InDir + "\\" + csvfileName;
|
||||||
|
FileHelper.SaveFile(csvoutpath, outPutCsv.ToArray());
|
||||||
|
|
||||||
|
Console.WriteLine($">>>>>>>>>>>>>>处理完毕>>>>>>>>>>>>>>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
int errcount = 0;
|
||||||
|
for (int i = 0; i < files.Length; i++)
|
||||||
|
{
|
||||||
|
string FileName = files[i].Substring(files[i].LastIndexOf("\\"));
|
||||||
|
|
||||||
|
if (System.IO.Path.GetExtension(FileName).ToLower() != ".csv")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
|
||||||
|
Console.WriteLine($">>>>>>>>>>>>>>开始处理 第{index}个文件 {FileName}<<<<<<<<<<<<<<<<<<<");
|
||||||
|
FileHelper.LoadFile(files[i], out string[] lines);
|
||||||
|
List<ShopItem> itemlist = LoadStructForCsv(lines);
|
||||||
|
|
||||||
|
|
||||||
|
string binfileName = System.IO.Path.GetFileNameWithoutExtension(FileName) + ".bin";
|
||||||
|
string binoutpath = loc + InDir + "\\" + binfileName;
|
||||||
|
|
||||||
|
FileHelper.LoadFile(binoutpath, out byte[] bindata);
|
||||||
|
|
||||||
|
ModifyItem(bindata, itemlist, out byte[] ResultData);
|
||||||
|
|
||||||
|
FileHelper.SaveFile(binoutpath, ResultData);
|
||||||
|
|
||||||
|
Console.WriteLine($">>>>>>>>>>>>>>处理完毕>>>>>>>>>>>>>>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
@ -74,16 +119,40 @@ namespace MHFOldShopTools
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int StartPtr = 0x539A78;
|
static int NPStore_Ptr = 0x537924;
|
||||||
const int _singelItemDatalenght = 12;
|
const int _singelItemDatalenght = 12;
|
||||||
static void ReaderItems(byte[] data)
|
static int NPStore_ItemCount = 712;
|
||||||
{
|
|
||||||
List<ShopItem> items = new List<ShopItem>();
|
|
||||||
|
|
||||||
|
static void ReaderItems(byte[] data,out List<string> OutInput,out List<string> outPutCsv)
|
||||||
|
{
|
||||||
|
OutInput = new List<string>();
|
||||||
|
outPutCsv = new List<string>();
|
||||||
|
List<ShopItem> items = new List<ShopItem>();
|
||||||
|
for (int i = 0; i < NPStore_ItemCount; i++)
|
||||||
|
{
|
||||||
|
items.Add(GetShopItemInfo(data, NPStore_Ptr + (i * _singelItemDatalenght)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < items.Count; i++)
|
||||||
|
{
|
||||||
|
ShopItem item = items[i];
|
||||||
|
string ItemInfo;
|
||||||
|
if (item.UnKnow)
|
||||||
|
ItemInfo = $"{"0x" + item.Ptr.ToString("X") + ":"} | 解析失败";
|
||||||
|
else
|
||||||
|
ItemInfo = $"{"0x" + item.Ptr.ToString("X") + ":"} | {item.ItemID} ({MHHelper.Get2MHFItemName(item.ItemID)}) | {item.Point}点 | {item.Group}({GetShopName(item.Group)}) {item.LevelType}({GetLevelTypeName(item.LevelType)})| [{item.OtherData[0].ToString("X")} {item.OtherData[1].ToString("X")} {item.OtherData[2].ToString("X")} {item.OtherData[3].ToString("X")}]";
|
||||||
|
|
||||||
|
OutInput.Add(ItemInfo);
|
||||||
|
outPutCsv.Add($"{item.ItemID},{item.Point},{item.Group},{item.LevelType}");
|
||||||
|
Console.WriteLine(ItemInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
int TempPtr = 0x539A78;
|
||||||
int ToUpCount = 712;
|
int ToUpCount = 712;
|
||||||
for (int i = 0; i < ToUpCount; i++)
|
for (int i = 0; i < ToUpCount; i++)
|
||||||
{
|
{
|
||||||
items.Add(GetShopItemInfo(data, StartPtr + (-1 * i * _singelItemDatalenght)));
|
items.Add(GetShopItemInfo(data, TempPtr + (-1 * i * _singelItemDatalenght)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = items.Count - 1; i >= 0; i--)
|
for (int i = items.Count - 1; i >= 0; i--)
|
||||||
@ -93,10 +162,53 @@ namespace MHFOldShopTools
|
|||||||
if (item.UnKnow)
|
if (item.UnKnow)
|
||||||
ItemInfo = $"{"0x" + item.Ptr.ToString("X") + ":"} | 解析失败";
|
ItemInfo = $"{"0x" + item.Ptr.ToString("X") + ":"} | 解析失败";
|
||||||
else
|
else
|
||||||
ItemInfo = $"{ "0x" + item.Ptr.ToString("X") + ":"} | {item.ItemID} ({MHHelper.Get2MHFItemName(item.ItemID)}) | {item.Point}点 | {item.Group}({GetShopName(item.Group)})| [{item.OtherData[0].ToString("X")} {item.OtherData[1].ToString("X")} {item.OtherData[2].ToString("X")} {item.OtherData[3].ToString("X")}]";
|
ItemInfo = $"{ "0x" + item.Ptr.ToString("X") + ":"} | {item.ItemID} ({MHHelper.Get2MHFItemName(item.ItemID)}) | {item.Point}点 | {item.Group}({GetShopName(item.Group)}) {item.LevelType}({GetLevelTypeName(item.LevelType)})| [{item.OtherData[0].ToString("X")} {item.OtherData[1].ToString("X")} {item.OtherData[2].ToString("X")} {item.OtherData[3].ToString("X")}]";
|
||||||
|
|
||||||
Console.WriteLine(ItemInfo);
|
Console.WriteLine(ItemInfo);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<ShopItem> LoadStructForCsv(string[] lines)
|
||||||
|
{
|
||||||
|
List<ShopItem> itemList = new List<ShopItem>();
|
||||||
|
for (int i = 0;i < lines.Length; i++)
|
||||||
|
{
|
||||||
|
string[] temp = lines[i].Split(',');
|
||||||
|
ShopItem item = new ShopItem()
|
||||||
|
{
|
||||||
|
ItemID = Convert.ToInt32(temp[0]),
|
||||||
|
Point = Convert.ToInt32(temp[1]),
|
||||||
|
Group = Convert.ToInt32(temp[2]),
|
||||||
|
LevelType = Convert.ToInt32(temp[3]),
|
||||||
|
};
|
||||||
|
itemList.Add(item);
|
||||||
|
}
|
||||||
|
return itemList;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ModifyItem(byte[] srcdata, List<ShopItem> items,out byte[] ResultData)
|
||||||
|
{
|
||||||
|
byte[] target = HexHelper.CopyByteArr(srcdata);
|
||||||
|
|
||||||
|
//ClearData
|
||||||
|
for (int i = NPStore_Ptr; i < NPStore_Ptr + (NPStore_ItemCount * _singelItemDatalenght); i++)
|
||||||
|
target[i] = 0x00;
|
||||||
|
|
||||||
|
for (int i = 0; i < items.Count; i++)
|
||||||
|
{
|
||||||
|
ShopItem itemdata = items[i];
|
||||||
|
int tempItemIDPtr = NPStore_Ptr + (i * _singelItemDatalenght);
|
||||||
|
int tempPricePtr = tempItemIDPtr + 4;
|
||||||
|
int tempMenuPtr = tempItemIDPtr + 4 + 4;
|
||||||
|
int tempLevelPtr = tempItemIDPtr + 4 + 4 + 1;
|
||||||
|
HexHelper.ModifyDataToBytes(target, HexHelper.intToBytes(itemdata.ItemID), tempItemIDPtr);
|
||||||
|
HexHelper.ModifyDataToBytes(target, HexHelper.intToBytes(itemdata.Point), tempPricePtr);
|
||||||
|
target[tempMenuPtr] = (byte)itemdata.Group;
|
||||||
|
target[tempLevelPtr] = (byte)itemdata.LevelType;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultData = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
static string GetShopName(int gourp)
|
static string GetShopName(int gourp)
|
||||||
@ -114,17 +226,33 @@ namespace MHFOldShopTools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static string GetLevelTypeName(int Level)
|
||||||
|
{
|
||||||
|
switch (Level)
|
||||||
|
{
|
||||||
|
case 0:return "无限制";
|
||||||
|
case 1:return "HR31以上";
|
||||||
|
case 2:return "HR100以上";
|
||||||
|
case 3:return "SR1以上";
|
||||||
|
case 4:return "SR31以上";
|
||||||
|
default:
|
||||||
|
return "未定义";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ShopItem GetShopItemInfo(byte[] data, int StartPos)
|
static ShopItem GetShopItemInfo(byte[] data, int StartPos)
|
||||||
{
|
{
|
||||||
int ItemID = -1;
|
int ItemID = -1;
|
||||||
int Point = -1;
|
int Point = -1;
|
||||||
int Group = -1;
|
int Group = -1;
|
||||||
|
int LevelType = -1;
|
||||||
bool UnKnow = false;
|
bool UnKnow = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ItemID = HexHelper.bytesToInt(data, 4, StartPos);
|
ItemID = HexHelper.bytesToInt(data, 4, StartPos);
|
||||||
Point = HexHelper.bytesToInt(data, 4, StartPos + 4);
|
Point = HexHelper.bytesToInt(data, 4, StartPos + 4);
|
||||||
Group = HexHelper.bytesToInt(data, 1, StartPos + 4 + 4);
|
Group = HexHelper.bytesToInt(data, 1, StartPos + 4 + 4);
|
||||||
|
LevelType = HexHelper.bytesToInt(data, 1, StartPos + 4 + 4 + 1);
|
||||||
UnKnow = false;
|
UnKnow = false;
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch(Exception ex)
|
||||||
@ -138,6 +266,7 @@ namespace MHFOldShopTools
|
|||||||
ItemID = ItemID,
|
ItemID = ItemID,
|
||||||
Point = Point,
|
Point = Point,
|
||||||
Group = Group,
|
Group = Group,
|
||||||
|
LevelType = LevelType,
|
||||||
OtherData = new int[]{ data[StartPos + 4 + 4 + 0],data[StartPos + 4 + 4 + 1], data[StartPos + 4 + 4 + 2], data[StartPos + 4 + 4 + 3] },
|
OtherData = new int[]{ data[StartPos + 4 + 4 + 0],data[StartPos + 4 + 4 + 1], data[StartPos + 4 + 4 + 2], data[StartPos + 4 + 4 + 3] },
|
||||||
UnKnow = UnKnow
|
UnKnow = UnKnow
|
||||||
};
|
};
|
||||||
@ -150,6 +279,7 @@ namespace MHFOldShopTools
|
|||||||
public int ItemID;
|
public int ItemID;
|
||||||
public int Point;
|
public int Point;
|
||||||
public int Group;
|
public int Group;
|
||||||
|
public int LevelType;
|
||||||
public int[] OtherData;
|
public int[] OtherData;
|
||||||
public bool UnKnow;
|
public bool UnKnow;
|
||||||
}
|
}
|
||||||
|
38
README.md
Normal file
38
README.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
##[Cn]
|
||||||
|
|
||||||
|
本工具是用于Monster Hunter Frontier 老版本(Forward 5)的玩家道具商店读写工具。
|
||||||
|
|
||||||
|
因为老版本怪物猎人边境的NPC商店列表商店,并不受服务器控制。(如Erupe的shop相关的表)
|
||||||
|
|
||||||
|
纯客户端文件固定死的。
|
||||||
|
|
||||||
|
为了便于修改,以及为了实现服务器控制客户端商店列表,实现一个工具或类库。于是有了本工具。
|
||||||
|
|
||||||
|
本工具,可以将mhfdat文件,解析后,将商店数据输出txt清单和csv文件。
|
||||||
|
|
||||||
|
同时,也可以自己编辑csv文件。用本工具,重新导入mhfdat。得以修复。
|
||||||
|
|
||||||
|
对非中国服务器的老版本服务器运营者(因为老版本MHF中国只有我一个运营的服务器),也分享本工具。
|
||||||
|
|
||||||
|
如果您的服务器有Launcher,那么可以通过集成本工具,最终由服务器控制客户端商店列表。(我服务器就是这么做的)
|
||||||
|
|
||||||
|
** 目前只处理了,NetCafe Point Store这一个商店
|
||||||
|
|
||||||
|
##[En]
|
||||||
|
This tool is a player item store read-write tool for Monster Hunter Frontier older versions (Forward 5).
|
||||||
|
|
||||||
|
Because the NPC store list store in the old version of Monster Hunter Frontier is not controlled by the server. (such as Erupe's shop related table)
|
||||||
|
|
||||||
|
The pure client file is fixed.
|
||||||
|
|
||||||
|
To facilitate modification and to achieve server control of the client store list, implement a tool or library. So there was this tool.
|
||||||
|
|
||||||
|
This tool can parse the mhfdat file and output the store data as a txt list and CSV file.
|
||||||
|
|
||||||
|
At the same time, you can also edit CSV files yourself. Use this tool to re import mhfdat. Can be repaired.
|
||||||
|
|
||||||
|
I also share this tool with operators of older versions of non Chinese servers (as I am the only one operating the server in MHF China).
|
||||||
|
|
||||||
|
If your server has a Launcher, then the client store list can be ultimately controlled by the server through the set cost tool. (That's how my server does it)
|
||||||
|
|
||||||
|
** Currently, only the NetCafe Point Store has been processed
|
Loading…
Reference in New Issue
Block a user