From 74b821ac13a2a0cb4b86d3aafb2b08b127053c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Tue, 10 Jun 2025 13:53:30 -0500 Subject: [PATCH] feat: ini accessor (needs work) --- .vscode/settings.json | 1 + src/BlitzKit.FFI/FFI.cs | 4 + src/BlitzKit.FFI/Models/BlitzProvider.cs | 19 ++++ src/BlitzKit.FFI/Models/INIAccessor.cs | 58 ++++++++++ src/BlitzKit.FFI/Utils/AgnosticHelpers.cs | 124 ++++++++++++++++++++++ 5 files changed, 206 insertions(+) create mode 100644 src/BlitzKit.FFI/Models/INIAccessor.cs create mode 100644 src/BlitzKit.FFI/Utils/AgnosticHelpers.cs diff --git a/.vscode/settings.json b/.vscode/settings.json index 80f5f5d66..f5a086df5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -128,6 +128,7 @@ "noout", "normalmap", "oneof", + "oodle", "oopsies", "Oopsy", "opentest", diff --git a/src/BlitzKit.FFI/FFI.cs b/src/BlitzKit.FFI/FFI.cs index ff07e1c73..5a07f912b 100644 --- a/src/BlitzKit.FFI/FFI.cs +++ b/src/BlitzKit.FFI/FFI.cs @@ -1,6 +1,8 @@ using System; using System.Runtime.InteropServices; using BlitzKit.FFI.Models; +using BlitzKit.FFI.Utils; +using CUE4Parse.Compression; namespace BlitzKit.FFI; @@ -20,6 +22,8 @@ public static class FFI public static void DebugGetGameMountPoint(IntPtr pointPtr) { var point = Marshal.PtrToStringAnsi(pointPtr); + + AgnosticHelpers.Initialize().Wait(); provider = new(point); } diff --git a/src/BlitzKit.FFI/Models/BlitzProvider.cs b/src/BlitzKit.FFI/Models/BlitzProvider.cs index 5d2543c81..268720e24 100644 --- a/src/BlitzKit.FFI/Models/BlitzProvider.cs +++ b/src/BlitzKit.FFI/Models/BlitzProvider.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Text; using CUE4Parse.FileProvider; using CUE4Parse.UE4.Versions; @@ -17,6 +18,24 @@ namespace BlitzKit.FFI.Models { Initialize(); Mount(); + + Console.WriteLine(DiscoveryURL()); + } + + public string DiscoveryURL() + { + if (TryGetGameFile("Blitz/Config/DefaultEngine.ini", out var defaultEngine)) + { + INIAccessor accessor = new(Encoding.UTF8.GetString(defaultEngine.Read())); + + var url = (string)accessor.Get("DiscoveryURLDedicProduction"); + + return url; + } + else + { + throw new FileNotFoundException("Could not find DefaultEngine.ini"); + } } } } diff --git a/src/BlitzKit.FFI/Models/INIAccessor.cs b/src/BlitzKit.FFI/Models/INIAccessor.cs new file mode 100644 index 000000000..56b536320 --- /dev/null +++ b/src/BlitzKit.FFI/Models/INIAccessor.cs @@ -0,0 +1,58 @@ +using System.Collections.Generic; +using System.Linq; + +namespace BlitzKit.FFI.Models +{ + public class INIAccessor + { + private Dictionary data = []; + + public INIAccessor(string content) + { + var lines = content.Split(['\n', '\r'], System.StringSplitOptions.RemoveEmptyEntries); + + foreach (var line in lines) + { + var trimmed = line.Trim(); + + if (string.IsNullOrWhiteSpace(trimmed) || trimmed.StartsWith(';')) + continue; + + var prefix = trimmed[0]; + string key, + value; + + if (prefix == '+' || prefix == '-') + { + var x = trimmed.IndexOf('='); + key = trimmed[1..x]; + value = trimmed[(x + 1)..]; + + if (!data.TryGetValue(key, out var existing)) + { + data[key] = existing = new List(); + } + + var list = (List)existing; + + if (prefix == '+') + list.Add(value); + else + list.Remove(value); + } + else + { + var x = trimmed.IndexOf('='); + key = trimmed[..x]; + value = trimmed[(x + 1)..]; + + data[key] = value; + } + } + } + + public bool TryGet(string key, out object value) => data.TryGetValue(key, out value); + + public object Get(string key) => data[key]; + } +} diff --git a/src/BlitzKit.FFI/Utils/AgnosticHelpers.cs b/src/BlitzKit.FFI/Utils/AgnosticHelpers.cs new file mode 100644 index 000000000..e1b8ee515 --- /dev/null +++ b/src/BlitzKit.FFI/Utils/AgnosticHelpers.cs @@ -0,0 +1,124 @@ +using System; +using System.IO; +using System.IO.Compression; +using System.Net.Http; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using CUE4Parse.Compression; + +namespace BlitzKit.FFI.Utils +{ + public static class AgnosticHelpers + { + public const string BINARY_DIR = "../../temp/"; + public const string ZLIB_BINARY_URL_PREFIX = + "https://github.com/NotOfficer/Zlib-ng.NET/releases/download/1.0.0"; + public const string OODLE_BINARY_URL_PREFIX = + "https://github.com/WorkingRobot/OodleUE/releases/download/2024-11-01-726"; + + public static async Task Initialize() + { + if (!Directory.Exists(BINARY_DIR)) + { + Directory.CreateDirectory(BINARY_DIR); + } + + InitializeZlib(); + await InitializeOodle(); + } + + public static async Task InitializeOodle() + { + string url; + string extension; + string entry; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + url = $"{OODLE_BINARY_URL_PREFIX}/msvc.zip"; + entry = "bin/Release/oodle-data-shared.dll"; + extension = "dll"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + url = $"{OODLE_BINARY_URL_PREFIX}/gcc.zip"; + entry = "lib/Release/liboodle-data-shared.so"; + extension = "so"; + } + else + { + throw new PlatformNotSupportedException(); + } + + string fileName = $"oodle.{extension}"; + string filePath = Path.Combine(BINARY_DIR, fileName); + + if (File.Exists(filePath)) + { + Console.WriteLine($"Oodle found at {filePath}; using that"); + OodleHelper.Initialize(filePath); + + return; + } + + Console.WriteLine( + $"Oodle not found; downloading to {filePath} from {url} and extracting {entry}" + ); + + HttpClient client = new(); + using var response = await client.GetAsync(url).ConfigureAwait(false); + + response.EnsureSuccessStatusCode(); + + await using var responseStream = await response + .Content.ReadAsStreamAsync() + .ConfigureAwait(false); + using var zip = new ZipArchive(responseStream, ZipArchiveMode.Read); + var zipEntry = zip.GetEntry(entry); + + ArgumentNullException.ThrowIfNull(zipEntry, "oodle entry in zip not found"); + + await using var entryStream = zipEntry.Open(); + await using var fs = File.Create(filePath); + await entryStream.CopyToAsync(fs).ConfigureAwait(false); + + OodleHelper.Initialize(filePath); + } + + public static void InitializeZlib() + { + string url; + string extension; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + url = $"{ZLIB_BINARY_URL_PREFIX}/zlib-ng2.dll"; + extension = "dll"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + url = $"{ZLIB_BINARY_URL_PREFIX}/libz-ng.so"; + extension = "so"; + } + else + { + throw new PlatformNotSupportedException(); + } + + string fileName = $"zlib.{extension}"; + string filePath = Path.Combine(BINARY_DIR, fileName); + + if (File.Exists(filePath)) + { + Console.WriteLine($"Zlib found at {filePath}; using that"); + } + else + { + Console.WriteLine($"Zlib not found; downloading to {filePath} from {url}"); + ZlibHelper.DownloadDll(filePath, url); + } + + ZlibHelper.Initialize(filePath); + } + } +}