using System; using System.Collections.Generic; using System.IO; using System.Linq; using Newtonsoft.Json; namespace CacheReader { public class CachedItem { public string texName; public string m_strMenuName; public string m_strInfo; public string m_mpn; public string m_strCateName; public string m_eColorSetMPN; public string m_strMenuNameInColorSet; public string m_pcMultiColorID; public bool m_boDelOnly; public float m_fPriority; public bool m_bMan; } public class CacheData { public int version; public string menuHash; public string modMenuHash; public Dictionary cachedItems; } internal class Program { private static List mpnList = new List { "null_mpn", "MuneL", "MuneS", "MuneTare", "RegFat", "ArmL", "Hara", "RegMeet", "KubiScl", "UdeScl", "EyeScl", "EyeSclX", "EyeSclY", "EyePosX", "EyePosY", "EyeClose", "EyeBallPosX", "EyeBallPosY", "EyeBallSclX", "EyeBallSclY", "EarNone", "EarElf", "EarRot", "EarScl", "NosePos", "NoseScl", "FaceShape", "FaceShapeSlim", "MayuShapeIn", "MayuShapeOut", "MayuX", "MayuY", "MayuRot", "HeadX", "HeadY", "DouPer", "sintyou", "koshi", "kata", "west", "MuneUpDown", "MuneYori", "MuneYawaraka", "body", "moza", "head", "hairf", "hairr", "hairt", "hairs", "hairaho", "haircolor", "skin", "acctatoo", "accnail", "underhair", "hokuro", "mayu", "lip", "eye", "eye_hi", "eye_hi_r", "chikubi", "chikubicolor", "eyewhite", "nose", "facegloss", "wear", "skirt", "mizugi", "bra", "panz", "stkg", "shoes", "headset", "glove", "acchead", "accha", "acchana", "acckamisub", "acckami", "accmimi", "accnip", "acckubi", "acckubiwa", "accheso", "accude", "accashi", "accsenaka", "accshippo", "accanl", "accvag", "megane", "accxxx", "handitem", "acchat", "onepiece", "set_maidwear", "set_mywear", "set_underwear", "set_body", "folder_eye", "folder_mayu", "folder_underhair", "folder_skin", "folder_eyewhite", "kousoku_upper", "kousoku_lower", "seieki_naka", "seieki_hara", "seieki_face", "seieki_mune", "seieki_hip", "seieki_ude", "seieki_ashi" }; private static Dictionary mpns = mpnList.ToDictionary(v => mpnList.IndexOf(v), v => v); private static Dictionary parts = new Dictionary { [-1] = "NONE", [0]="EYE_L", [1] = "EYE_R", [2]="HAIR", [3]="EYE_BROW", [4]="UNDER_HAIR", [5]="SKIN", [6]="NIPPLE", [7]="HAIR_OUTLINE", [8]="SKIN_OUTLINE", [9]="EYE_WHITE", [10]="MAX" }; public static void Main(string[] args) { if (args.Length < 1) return; var path = args[0]; if (!File.Exists(path)) return; var data = new CacheData(); using var br = new BinaryReader(File.OpenRead(path)); try { data.version = br.ReadInt32(); var menuFilesHashSize = br.ReadInt32(); var menuFilesHash = br.ReadBytes(menuFilesHashSize); data.menuHash = Convert.ToBase64String(menuFilesHash); var modMenuFilesHashSize = br.ReadInt32(); var modMenuFilesHash = br.ReadBytes(modMenuFilesHashSize); data.modMenuHash = Convert.ToBase64String(modMenuFilesHash); data.cachedItems = new Dictionary(); while (true) { var key = br.ReadNullableString(); Console.WriteLine(key); var item = new CachedItem { texName = br.ReadNullableString(), m_strMenuName = br.ReadNullableString(), m_strInfo = br.ReadNullableString(), m_mpn = mpns.TryGetValue(br.ReadInt32(), out var val) ? val : "INVALID", m_strCateName = br.ReadNullableString(), m_eColorSetMPN = mpns.TryGetValue(br.ReadInt32(), out val) ? val : "INVALID", m_strMenuNameInColorSet = br.ReadNullableString(), m_pcMultiColorID = parts.TryGetValue(br.ReadInt32(), out val) ? val : "INVALID", m_boDelOnly = br.ReadBoolean(), m_fPriority = br.ReadSingle(), m_bMan = br.ReadBoolean() }; data.cachedItems[key] = item; } } catch (FormatException e) { Console.WriteLine($"Failed to deserialize cache because {e.Message}"); } catch (EndOfStreamException) { // End of file, no need to read more } File.WriteAllText("data.json", JsonConvert.SerializeObject(data, Formatting.Indented)); } } internal static class BinaryExtensions { public static string ReadNullableString(this BinaryReader br) { return br.ReadBoolean() ? br.ReadString() : null; } public static void WriteNullableString(this BinaryWriter bw, string value) { bw.Write(value != null); if (value != null) bw.Write(value); } } }