using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("KFontPatcher")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("KFontPatcher")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("93d10828-2361-4866-8bc0-d1839e945127")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] [BepInPlugin("Whiteline.kfontpatcher", "KFontPatcher", "1.0.2")] public class KFontPatcher : BaseUnityPlugin { private ConfigEntry cfg_SourceFileName; private ConfigEntry cfg_OverwriteIfDifferent; private ConfigEntry cfg_AttemptEmbedExtraction; private void Awake() { cfg_SourceFileName = ((BaseUnityPlugin)this).Config.Bind("Dev", "SourceFileName", "Kfont", "패처 DLL과 같은 폴더에 있는 에셋/폰트 파일명(확장자 없이 사용 가능). 예: Kfont"); cfg_OverwriteIfDifferent = ((BaseUnityPlugin)this).Config.Bind("General", "OverwriteIfDifferent", true, "이미 대상 파일이 있을 때 덮어쓸지 여부"); cfg_AttemptEmbedExtraction = ((BaseUnityPlugin)this).Config.Bind("General", "AttemptEmbedExtraction", true, "DLL 내부 임베디드 리소스를 추출 시도할지 여부"); try { ((BaseUnityPlugin)this).Logger.LogInfo((object)"KFontPatcher: 폰트 자동 설정을 시작합니다"); CopyBundleToTarget(); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"KFontPatcher 예외: {arg}"); } } private void CopyBundleToTarget() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = cfg_SourceFileName.Value ?? "Kfont"; string text2 = FindSourceFile(directoryName, text); if (text2 == null && cfg_AttemptEmbedExtraction.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("폰트 파일을 찾을 수 없음: '" + text + "'. 임베디드 리소스 추출 시도...")); if (TryExtractEmbeddedResourceAny(directoryName, text)) { text2 = FindSourceFile(directoryName, text); ((BaseUnityPlugin)this).Logger.LogInfo((object)"임베디드 리소스에서 파일을 추출했습니다."); } } if (text2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("최종적으로도 소스 파일을 찾지 못함: " + text + " (DLL과 같은 폴더에 있어야 함)")); return; } string directoryName2 = Path.GetDirectoryName(Application.dataPath); if (string.IsNullOrEmpty(directoryName2)) { ((BaseUnityPlugin)this).Logger.LogError((object)"게임 루트를 찾을 수 없음. Application.dataPath 확인 필요."); return; } string text3 = Path.Combine(directoryName2, "RPKP폰트", "FontBundles"); string text4 = Path.Combine(text3, Path.GetFileName(text2)); try { if (!Directory.Exists(text3)) { Directory.CreateDirectory(text3); ((BaseUnityPlugin)this).Logger.LogInfo((object)("대상 폴더가 스팀 로컬파일에 존재하지 않습니다, 폴더를 새로 생성합니다: " + text3)); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"대상 디렉토리 생성 실패: {text3}. 예외: {arg}"); return; } bool flag = true; if (File.Exists(text4)) { if (!cfg_OverwriteIfDifferent.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("대상 파일이 이미 있으며 OverwriteIfDifferent 설정이 False 이므로 복사를 생략합니다: " + text4)); return; } FileInfo fileInfo = new FileInfo(text2); FileInfo fileInfo2 = new FileInfo(text4); if (fileInfo.Length == fileInfo2.Length) { flag = false; ((BaseUnityPlugin)this).Logger.LogInfo((object)("출처와 대상 파일의 크기가 동일합니다. 덮어쓰지 않습니다: " + text4)); } } if (!flag) { return; } try { File.Copy(text2, text4, overwrite: true); ((BaseUnityPlugin)this).Logger.LogInfo((object)("에셋/폰트 파일을 성공적으로 복사했습니다! " + text2 + " -> " + text4)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"폰트가 이제 막 적용되었습니다!!! 안정적인 적용을 위해 게임을 재시작하세요!!!\r\n재시작하지 않으면 글자의 크기나 위치가 잘못 배치됩니다!!!"); } catch (Exception arg2) { ((BaseUnityPlugin)this).Logger.LogError((object)$"파일 복사 실패: {arg2}"); } } private string FindSourceFile(string asmDir, string sourceName) { string text = Path.Combine(asmDir, sourceName); if (File.Exists(text)) { return text; } string[] array = (from f in Directory.GetFiles(asmDir) where string.Equals(Path.GetFileNameWithoutExtension(f), sourceName, StringComparison.OrdinalIgnoreCase) select f).ToArray(); if (array.Length != 0) { return array[0]; } return null; } private bool TryExtractEmbeddedResourceAny(string outputDir, string fileNameWithoutExt) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); if (manifestResourceNames == null || manifestResourceNames.Length == 0) { return false; } string[] array = manifestResourceNames.Where((string r) => Path.GetFileNameWithoutExtension(r).Equals(fileNameWithoutExt, StringComparison.OrdinalIgnoreCase)).ToArray(); if (array.Length == 0) { return false; } try { string text = array[0]; using (Stream stream = executingAssembly.GetManifestResourceStream(text)) { if (stream == null) { return false; } using FileStream destination = new FileStream(Path.Combine(outputDir, Path.GetFileName(text)), FileMode.Create, FileAccess.Write); stream.CopyTo(destination); } return true; } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"임베디드 리소스 추출 실패: {arg}"); return false; } } }