update MeatKit (9a1a68ab68cd0650227af944ffa30d1166b9e056)

This commit is contained in:
msk
2023-07-26 16:45:05 -07:00
parent 920875f56b
commit d2316bac96
266 changed files with 2855 additions and 9187 deletions
@@ -0,0 +1,95 @@
/*
* This code is from BepInEx's NStrip library, licensed under MIT
* https://github.com/BepInEx/NStrip/blob/f1e9887b3eb77c0e02acb5919b5e26a6e7c2c342/NStrip/AssemblyStripper.cs
*/
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;
using UnityEngine;
namespace NStrip
{
public static class AssemblyStripper
{
static IEnumerable<TypeDefinition> GetAllTypeDefinitions(AssemblyDefinition assembly)
{
var typeQueue = new Queue<TypeDefinition>(assembly.MainModule.Types);
while (typeQueue.Count > 0)
{
var type = typeQueue.Dequeue();
yield return type;
foreach (var nestedType in type.NestedTypes)
typeQueue.Enqueue(nestedType);
}
}
private static bool CheckCompilerGeneratedAttribute(IMemberDefinition member)
{
return member.CustomAttributes.Any(x =>
x.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute");
}
public static void MakePublic(AssemblyDefinition assembly, IList<string> typeNameBlacklist, bool includeCompilerGenerated, bool excludeCgEvents)
{
foreach (var type in GetAllTypeDefinitions(assembly))
{
if (typeNameBlacklist.Contains(type.Name))
continue;
if (!includeCompilerGenerated && CheckCompilerGeneratedAttribute(type))
continue;
if (type.IsNested)
type.IsNestedPublic = true;
else
type.IsPublic = true;
foreach (var method in type.Methods)
{
if (!includeCompilerGenerated &&
(CheckCompilerGeneratedAttribute(method) || method.IsCompilerControlled))
continue;
method.IsPublic = true;
}
foreach (var field in type.Fields)
{
if (!includeCompilerGenerated &&
(CheckCompilerGeneratedAttribute(field) || field.IsCompilerControlled))
continue;
if (includeCompilerGenerated && excludeCgEvents)
{
if (type.Events.Any(x => x.Name == field.Name))
continue;
}
if (field.IsPublic) continue;
field.IsPublic = true;
var attributes = field.CustomAttributes;
CustomAttribute isExplicitlySerialized = attributes.FirstOrDefault(x => x.AttributeType.Name == "SerializeField");
if (isExplicitlySerialized == null)
{
var nonSerializedAttributeCtor = typeof(NonSerializedAttribute).GetConstructor(Type.EmptyTypes);
var nonSerializedAttributeRef = assembly.MainModule.ImportReference(nonSerializedAttributeCtor);
attributes.Add(new CustomAttribute(nonSerializedAttributeRef));
var hideInInspectorCtor = typeof(MeatKit.HideInNormalInspectorAttribute).GetConstructor(Type.EmptyTypes);
var hideInInspectorRef = assembly.MainModule.ImportReference(hideInInspectorCtor);
attributes.Add(new CustomAttribute(hideInInspectorRef));
}
}
}
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4c62b8c488f64d298e5bc464fdee9f17
timeCreated: 1646326380
@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace MeatKit
{
public class NativeHookFunctionOffsets
{
public long MonoScriptTransferWrite { get; set; }
public long MonoScriptTransferRead { get; set; }
public long ShutdownManaged { get; set; }
public long StringAssign { get; set; }
}
public class EditorVersion
{
public NativeHookFunctionOffsets FunctionOffsets { get; set; }
private static bool _hasShownPopup = false;
public static bool IsSupportedVersion
{
get
{
bool supported = SupportedVersions.ContainsKey(Application.unityVersion);
if (!supported && !_hasShownPopup)
{
// Show the warning popup about the wrong version if is hasn't come up already.
string validVersion = string.Join(", ", SupportedVersions.Keys.ToArray());
EditorUtility.DisplayDialog("Wrong editor version",
"You are using Unity version " + Application.unityVersion + ", MeatKit requires one of the following: " + validVersion,
"I'll go install that.");
_hasShownPopup = true;
}
return supported;
}
}
public static EditorVersion Current
{
get
{
EditorVersion currentVersion;
if (SupportedVersions.TryGetValue(Application.unityVersion, out currentVersion))
return currentVersion;
throw new NotSupportedException("The current editor version is not in the list of supported versions.");
}
}
private static readonly Dictionary<string, EditorVersion> SupportedVersions = new Dictionary<string, EditorVersion>()
{
{
"5.6.3p4", new EditorVersion
{
FunctionOffsets = new NativeHookFunctionOffsets
{
MonoScriptTransferWrite = 0xE321E0,
MonoScriptTransferRead = 0xE34000,
ShutdownManaged = 0x17542D0,
StringAssign = 0x1480
}
}
},
{
"5.6.7f1", new EditorVersion
{
FunctionOffsets = new NativeHookFunctionOffsets
{
MonoScriptTransferWrite = 0xE39BF0,
MonoScriptTransferRead = 0xE3BA10,
ShutdownManaged = 0x175D2C0,
StringAssign = 0x1480
}
}
},
};
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f6222c8b0cb74878820d6fe4c55aae88
timeCreated: 1684366513
+192
View File
@@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace MeatKit
{
public static class Extensions
{
public static Type[] GetTypesSafe(this Assembly assembly)
{
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
return e.Types.Where(t => t != null).ToArray();
}
}
public static string ByteArrayToString(byte[] ba)
{
var hex = new StringBuilder(ba.Length * 2);
foreach (var b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
// Modified version of http://answers.unity.com/answers/1425776/view.html
public static T[] GetAllInstances<T>() where T : ScriptableObject
{
return AssetDatabase.FindAssets("t:" + typeof(T).FullName)
.Select(AssetDatabase.GUIDToAssetPath)
.Select(AssetDatabase.LoadAssetAtPath<T>)
.ToArray();
}
public static Object[] GetAllInstances(Type t)
{
return AssetDatabase.FindAssets("t:" + t.FullName)
.Select(AssetDatabase.GUIDToAssetPath)
.Select(p => AssetDatabase.LoadAssetAtPath(p, t))
.ToArray();
}
// https://stackoverflow.com/a/25223884
public static string MakeValidFileName(string text, char? replacement = '_')
{
if (string.IsNullOrEmpty(text)) return "";
var invalids = Path.GetInvalidFileNameChars();
var sb = new StringBuilder(text.Length);
var changed = false;
for (var i = 0; i < text.Length; i++)
{
var c = text[i];
if (invalids.Contains(c))
{
changed = true;
var repl = replacement ?? '\0';
if (repl != '\0')
sb.Append(repl);
}
else
sb.Append(c);
}
if (sb.Length == 0)
return "_";
return changed ? sb.ToString() : text;
}
// https://answers.unity.com/questions/150942/texture-scale.html
public static Texture2D ScaleTexture(this Texture2D source, int targetWidth, int targetHeight)
{
Texture2D result = new Texture2D(targetWidth, targetHeight, TextureFormat.ARGB32, false);
for (int i = 0; i < result.height; ++i)
{
for (int j = 0; j < result.width; ++j)
{
Color newColor = source.GetPixelBilinear(j / (float) result.width, i / (float) result.height);
result.SetPixel(j, i, newColor);
}
}
result.Apply();
return result;
}
public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target) {
foreach (DirectoryInfo dir in source.GetDirectories())
CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
foreach (FileInfo file in source.GetFiles())
file.CopyTo(Path.Combine(target.FullName, file.Name));
}
public static void CopyFilesRecursively(string source, string target)
{
CopyFilesRecursively(new DirectoryInfo(source), new DirectoryInfo(target));
}
#region TimeSpan formatting https://stackoverflow.com/a/21649465/8809017
public static string GetReadableTimespan(this TimeSpan ts)
{
// formats and its cutoffs based on totalseconds
var cutoff = new SortedList<long, string>
{
{59, "{3:S}"},
{60, "{2:M}"},
{60 * 60 - 1, "{2:M}, {3:S}"},
{60 * 60, "{1:H}"},
{24 * 60 * 60 - 1, "{1:H}, {2:M}"},
{24 * 60 * 60, "{0:D}"},
{long.MaxValue, "{0:D}, {1:H}"}
};
// find nearest best match
var find = cutoff.Keys.ToList()
.BinarySearch((long) ts.TotalSeconds);
// negative values indicate a nearest match
var near = find < 0 ? Math.Abs(find) - 1 : find;
// use custom formatter to get the string
return String.Format(
new HMSFormatter(),
cutoff[cutoff.Keys[near]],
ts.Days,
ts.Hours,
ts.Minutes,
ts.Seconds);
}
// formatter for forms of
// seconds/hours/day
private class HMSFormatter : ICustomFormatter, IFormatProvider
{
// list of Formats, with a P customformat for pluralization
static Dictionary<string, string> timeformats = new Dictionary<string, string>
{
{"S", "{0:P:s:s}"},
{"M", "{0:P:m:m}"},
{"H", "{0:P:h:h}"},
{"D", "{0:P:d:d}"}
};
public string Format(string format, object arg, IFormatProvider formatProvider)
{
return String.Format(new PluralFormatter(), timeformats[format], arg);
}
public object GetFormat(Type formatType)
{
return formatType == typeof(ICustomFormatter) ? this : null;
}
}
// formats a numeric value based on a format P:Plural:Singular
private class PluralFormatter : ICustomFormatter, IFormatProvider
{
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (arg != null)
{
var parts = format.Split(':'); // ["P", "Plural", "Singular"]
if (parts[0] == "P") // correct format?
{
// which index postion to use
int partIndex = (arg.ToString() == "1") ? 2 : 1;
// pick string (safe guard for array bounds) and format
return String.Format("{0}{1}", arg, (parts.Length > partIndex ? parts[partIndex] : ""));
}
}
return String.Format(format, arg);
}
public object GetFormat(Type formatType)
{
return formatType == typeof(ICustomFormatter) ? this : null;
}
}
#endregion
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d928d818e3c24bce8c1c938e971da916
timeCreated: 1628577239
@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEditor;
namespace MeatKit
{
[CustomPropertyDrawer(typeof(HideInNormalInspectorAttribute))]
class HideInNormalInspectorDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return 0f;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { }
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0c4b5d56cc4522845a6ca6bb3d6d76f0
timeCreated: 1667603705
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using MonoMod.RuntimeDetour;
using MonoMod.Utils;
using UnityEditor;
using UnityEngine;
namespace MeatKit
{
/// <summary>
/// This class helps manage detours into the native code of the Editor.
/// Any detours into native code should be registered using this as it will automatically dispose of them
/// right before the Editor reloads the mono domain, preventing editor crashes.
/// </summary>
[InitializeOnLoad]
public static class NativeHookManager
{
// Actual name: ShutdownPlatformSupportModulesInManaged(void)
private delegate void ShutdownManaged();
private static readonly ShutdownManaged OrigShutdownManaged;
// Keep track of all the applied detours so we can quickly undo them before the mono domain is reloaded
private static readonly List<NativeDetour> Detours = new List<NativeDetour>();
static NativeHookManager()
{
if (!EditorVersion.IsSupportedVersion) return;
// Apply our detours here and save the trampoline to call the original function
OrigShutdownManaged = ApplyEditorDetour<ShutdownManaged>(EditorVersion.Current.FunctionOffsets.ShutdownManaged, new ShutdownManaged(OnShutdownManaged));
}
public static T ApplyEditorDetour<T>(long from, Delegate to) where T : class
{
// Avoid crashing the editor if we're loaded in the wrong Unity version
if (!EditorVersion.IsSupportedVersion) return null;
// Get the base address of the Unity module and the address in memory of the function
IntPtr editorBase = DynDll.OpenLibrary("Unity.exe");
IntPtr fromPtr = (IntPtr)(editorBase.ToInt64() + from);
// Get a function pointer for the managed callback
var toPtr = Marshal.GetFunctionPointerForDelegate(to);
// Make a detour and add it to the list
var detour = new NativeDetour(fromPtr, toPtr, new NativeDetourConfig { ManualApply = true });
Detours.Add(detour);
// Apply the detour and generate a trampoline for it, which we return
var original = detour.GenerateTrampoline(to.GetType().GetMethod("Invoke")).CreateDelegate(typeof(T)) as T;
detour.Apply();
return original;
}
public static Delegate GetDelegateForFunctionPointer<T>(long from)
{
// Avoid crashing the editor if we're loaded in the wrong Unity version
if (!EditorVersion.IsSupportedVersion) return null;
// Get the base address for the Unity module and apply the offset
IntPtr editorBase = DynDll.OpenLibrary("Unity.exe");
return Marshal.GetDelegateForFunctionPointer((IntPtr)(editorBase.ToInt64() + from), typeof(T));
}
private static void OnShutdownManaged()
{
// Unity is about to shutdown the mono runtime! Quickly dispose of our detours!
OrigShutdownManaged();
foreach (var detour in Detours) detour.Dispose();
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9a51d43ba1fe4baf8e3b0a90d7f8ec88
timeCreated: 1654485214
@@ -0,0 +1,45 @@
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.Win32;
namespace MeatKit
{
public static class SteamAppLocator
{
private const int AppId = 450540;
private const string AppFolderName = "H3VR";
public static string LocateGame()
{
// Get the main steam installation location via registry.
var steamDir = (
Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam", "InstallPath", null) ??
Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Valve\Steam", "InstallPath", null))
as string;
// If we can't find it, return. This should really only happen if Steam isn't installed.
if (string.IsNullOrEmpty(steamDir)) return null;
// Check main steamapps library folder for h3 manifest.
var manifestFile = @"steamapps\appmanifest_" + AppId + ".acf";
var gameFolder = @"steamapps\common\" + AppFolderName + @"\";
if (File.Exists(Path.Combine(steamDir, manifestFile)))
{
return Path.Combine(steamDir, gameFolder);
}
// We didn't find it, look at other library folders by lazily parsing libraryfolders.
var libraryFolders = Path.Combine(steamDir, @"steamapps\libraryfolders.vdf");
foreach (Match match in Regex.Matches(File.ReadAllText(libraryFolders), @"^\s+\""path\""\s+\""(.+)\""$",
RegexOptions.Multiline))
{
var folder = match.Groups[1].Value;
if (!File.Exists(Path.Combine(folder, manifestFile))) continue;
return Path.Combine(folder, gameFolder);
}
// Nope. Still can't find it.
return null;
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4c50a485a68d43caa9c30a864c2d8b25
timeCreated: 1655693881
@@ -0,0 +1,60 @@
using System;
using System.Runtime.InteropServices;
namespace MeatKit
{
public static class UnityNativeHelper
{
private delegate IntPtr StringAssignType(IntPtr ptr, string str, ulong len, IntPtr nul);
private static readonly StringAssignType AssignNativeString;
static UnityNativeHelper()
{
if (!EditorVersion.IsSupportedVersion) return;
AssignNativeString = (StringAssignType) NativeHookManager.GetDelegateForFunctionPointer<StringAssignType>(EditorVersion.Current.FunctionOffsets.StringAssign);
}
/// <summary>
/// Reads a native string structure from unmanaged memory
/// </summary>
/// <param name="ptr">The pointer to the structure</param>
/// <param name="ofs">Offset to the pointer</param>
/// <returns>A copy of the structure in managed memory</returns>
public static string ReadNativeString(IntPtr ptr, int ofs)
{
// Apply the offset
var real = (IntPtr) (ptr.ToInt64() + ofs);
// Get the pointer to the string in memory
var stringPointer = Marshal.ReadIntPtr(real);
if (stringPointer == IntPtr.Zero)
{
// If the pointer is null, that means it's stored in the struct directly.
// In this format, the string is 16 chars or less.
var length = Marshal.ReadInt64(real, 24);
return Marshal.PtrToStringAnsi((IntPtr) (real.ToInt64() + 8), (int) length);
}
else
{
// If it isn't null, we can just go out into that memory location and read it.
var length = Marshal.ReadInt64(real, 24);
return Marshal.PtrToStringAnsi(stringPointer, (int) length);
}
}
/// <summary>
/// Writes a managed string to the unmanaged memory location of a string structure
/// </summary>
/// <param name="ptr">The pointer to the structure in memory</param>
/// <param name="ofs">Offset to the pointer</param>
/// <param name="str">The string to write</param>
public static void WriteNativeString(IntPtr ptr, int ofs, string str)
{
// Apply the offset and call the assign function of native Unity code
var real = (IntPtr) (ptr.ToInt64() + ofs);
AssignNativeString(real, str, (ulong) str.Length, IntPtr.Zero);
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ba90027061ca46f88e2e0cf4fefc0224
timeCreated: 1655406646