123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- using System.Reflection;
- using System.Reflection.Emit;
- namespace COM3D2.CacheEditMenu
- {
- 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);
- }
- }
- public static class Hooks
- {
- private static readonly Dictionary<string, MenuInfo> infoCache = new Dictionary<string, MenuInfo>();
- private static BinaryWriter cacheWriter;
- private static readonly Func<Dictionary<int, SceneEdit.SMenuItem>> getIdItemDic = () =>
- new Dictionary<int, SceneEdit.SMenuItem>();
- private static readonly Func<Dictionary<int, string>> getTexFileIDDic = () => new Dictionary<int, string>();
- private static readonly Action<bool> setNowMenuFlg = b => { };
- private static readonly Action<int> setNowStrMenuFileID = b => { };
- static Hooks()
- {
- var quickEditAss =
- TryLoadFrom(Path.Combine(Patcher.Patcher.SybarisPath, "COM3D2.QuickEditStart.Managed.dll"));
- if (quickEditAss == null)
- return;
- var mainType = quickEditAss.GetType("COM3D2.QuickEditStart.Managed.QuickEditStartManaged");
- MakeStaticGetter(mainType.GetField("texFileIDDic", BindingFlags.Public | BindingFlags.Static),
- ref getTexFileIDDic);
- MakeStaticGetter(mainType.GetField("idItemDic", BindingFlags.Public | BindingFlags.Static),
- ref getIdItemDic);
- MakeStaticSetter(mainType.GetField("nowMenuFlg", BindingFlags.NonPublic | BindingFlags.Static),
- ref setNowMenuFlg);
- MakeStaticSetter(mainType.GetField("nowStrMenuFileID", BindingFlags.NonPublic | BindingFlags.Static),
- ref setNowStrMenuFileID);
- }
- private static void MakeStaticGetter<T>(FieldInfo field, ref T result) where T : Delegate
- {
- if (field == null)
- return;
- var dm = new DynamicMethod($"CacheEditMenu_Getter_{field.GetHashCode()}", field.FieldType, null,
- typeof(Hooks), true);
- var il = dm.GetILGenerator();
- il.Emit(OpCodes.Ldsfld, field);
- il.Emit(OpCodes.Ret);
- result = dm.CreateDelegate(typeof(T)) as T;
- }
- private static void MakeStaticSetter<T>(FieldInfo field, ref T result) where T : Delegate
- {
- if (field == null)
- return;
- var dm = new DynamicMethod($"CacheEditMenu_Getter_{field.GetHashCode()}", typeof(void),
- new[] {field.FieldType}, typeof(Hooks), true);
- var il = dm.GetILGenerator();
- il.Emit(OpCodes.Ldarg_0);
- il.Emit(OpCodes.Stsfld, field);
- il.Emit(OpCodes.Ret);
- result = dm.CreateDelegate(typeof(T)) as T;
- }
- private static Assembly TryLoadFrom(string path)
- {
- try
- {
- return Assembly.LoadFrom(path);
- }
- catch (Exception)
- {
- return null;
- }
- }
- public static bool Prefix(ref bool result, SceneEdit.SMenuItem mi, string menuFileName)
- {
- Init();
- if (menuFileName.Contains("_zurashi"))
- {
- result = false;
- return false;
- }
- if (menuFileName.Contains("_mekure"))
- {
- result = false;
- return false;
- }
- menuFileName = Path.GetFileName(menuFileName);
- mi.m_strMenuFileName = menuFileName;
- mi.m_nMenuFileRID = menuFileName.ToLower().GetHashCode();
- if (infoCache.TryGetValue(menuFileName, out var menuInfo))
- {
- menuInfo.CopyTo(mi);
- result = true;
- return false;
- }
- return true;
- }
- private static Stopwatch sw = null;
- public static bool Postfix(bool result, SceneEdit.SMenuItem mi, string menuFileName)
- {
- if (!result)
- return false;
-
- var menuInfo = new MenuInfo
- {
- mi = mi,
- key = menuFileName
- };
- getTexFileIDDic().TryGetValue(mi.m_nMenuFileRID, out menuInfo.texName);
- infoCache[menuFileName] = menuInfo;
-
- menuInfo.Serialize(cacheWriter);
-
- return true;
- }
- private static void Init()
- {
- if (cacheWriter != null)
- return;
- var cacheDir = Path.Combine(Patcher.Patcher.SybarisPath, "EditMenuCache");
- var cachePath = Path.Combine(cacheDir, "EditMenuCache.dat");
- Directory.CreateDirectory(cacheDir);
- if (File.Exists(cachePath))
- using (var br = new BinaryReader(File.Open(cachePath, FileMode.Open, FileAccess.Read)))
- {
- try
- {
- while (true)
- {
- var menuInfo = new MenuInfo();
- menuInfo.Deserialize(br);
- infoCache[menuInfo.key] = menuInfo;
- }
- }
- catch (EndOfStreamException)
- {
- // End of file, no need to read more
- }
- }
- cacheWriter = new BinaryWriter(File.OpenWrite(cachePath));
- cacheWriter.BaseStream.Seek(0, SeekOrigin.End);
- }
- private class MenuInfo
- {
- public string key;
- public SceneEdit.SMenuItem mi;
- public string texName;
- public void Deserialize(BinaryReader br)
- {
- key = br.ReadString();
- texName = br.ReadNullableString();
- mi = new SceneEdit.SMenuItem
- {
- m_strMenuName = br.ReadString(),
- m_strInfo = br.ReadNullableString(),
- m_mpn = (MPN) br.ReadInt32(),
- m_strCateName = br.ReadString(),
- m_eColorSetMPN = (MPN) br.ReadInt32(),
- m_strMenuNameInColorSet = br.ReadNullableString(),
- m_pcMultiColorID = (MaidParts.PARTS_COLOR) br.ReadInt32(),
- m_boDelOnly = br.ReadBoolean(),
- m_fPriority = br.ReadSingle(),
- m_bMan = br.ReadBoolean()
- };
- }
- public void Serialize(BinaryWriter bw)
- {
- bw.Write(key);
- bw.WriteNullableString(texName);
- bw.Write(mi.m_strMenuName);
- bw.WriteNullableString(mi.m_strInfo);
- bw.Write((int) mi.m_mpn);
- bw.Write(mi.m_strCateName);
- bw.Write((int) mi.m_eColorSetMPN);
- bw.WriteNullableString(mi.m_strMenuNameInColorSet);
- bw.Write((int) mi.m_pcMultiColorID);
- bw.Write(mi.m_boDelOnly);
- bw.Write(mi.m_fPriority);
- bw.Write(mi.m_bMan);
- }
- public void CopyTo(SceneEdit.SMenuItem other)
- {
- other.m_strMenuName = mi.m_strMenuName;
- other.m_strInfo = mi.m_strInfo;
- other.m_mpn = mi.m_mpn;
- other.m_strCateName = mi.m_strCateName;
- other.m_eColorSetMPN = mi.m_eColorSetMPN;
- other.m_strMenuNameInColorSet = mi.m_strMenuNameInColorSet;
- other.m_pcMultiColorID = mi.m_pcMultiColorID;
- other.m_boDelOnly = mi.m_boDelOnly;
- other.m_fPriority = mi.m_fPriority;
- other.m_bMan = mi.m_bMan;
- if (string.IsNullOrEmpty(texName))
- return;
- setNowMenuFlg(true);
- setNowStrMenuFileID(other.m_nMenuFileRID);
- getIdItemDic()[other.m_nMenuFileRID] = other;
- other.m_texIcon = ImportCM.CreateTexture(texName);
- setNowMenuFlg(false);
- }
- }
- }
- }
|