private static void InitializeUnityVersion()
        {
            string unityVersion = MelonUtils.GetUnityVersion();

            if (string.IsNullOrEmpty(unityVersion))
            {
                return;
            }
            string[] unityVersionSplit = unityVersion.Split('.');
            int      major             = int.Parse(unityVersionSplit[0]);
            int      minor             = int.Parse(unityVersionSplit[1]);
            string   patchString       = unityVersionSplit[2];
            char     firstBadChar      = patchString.FirstOrDefault(it => it <'0' || it> '9');
            int      patch             = int.Parse(firstBadChar == 0 ? patchString : patchString.Substring(0, patchString.IndexOf(firstBadChar)));

            UnityVersionHandler.Initialize(major, minor, patch);
        }
Example #2
0
        public static void Erect(Record record)
        {
            var trampoline = Trampoline.Generate(record.FinalInitVa);

            unsafe
            {
                var p = (IntPtr *)Marshal.AllocHGlobal(IntPtr.Size);
                *   p = record.FinalInitVa;

                MelonUtils.NativeHookAttach((IntPtr)p, trampoline.Address);

                var handle = trampoline.Finish(*p, Bridge);

                BRIDGE_INDEX.Add(handle, record);

                Marshal.FreeHGlobal((IntPtr)p);
            }
        }
Example #3
0
                internal static InfoStruct Contact(string response_str)
                {
                    ResponseStruct responseobj = MelonUtils.ParseJSONStringtoStruct <ResponseStruct>(response_str);

                    if (responseobj == null)
                    {
                        return(null);
                    }

                    InfoStruct returninfo = new InfoStruct();

                    //returninfo.ForceDumperVersion = responseobj.forceDumperVersion;
                    returninfo.ForceUnhollowerVersion = responseobj.forceUnhollowerVersion;
                    returninfo.ObfuscationRegex       = responseobj.obfuscationRegex;
                    returninfo.MappingURL             = responseobj.mappingURL;
                    returninfo.MappingFileSHA512      = responseobj.mappingFileSHA512;
                    return(returninfo);
                }
Example #4
0
 unsafe static UIVertexWrapper()
 {
     if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2020.2.0", "2021.1.0" }))
     {
         mode          = 2;
         sizeOfElement = sizeof(UIVertex_2020);
     }
     else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2018.1.0" }))
     {
         mode          = 1;
         sizeOfElement = sizeof(UIVertex_2018);
     }
     else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2017.2.0" }))
     {
         mode          = 0;
         sizeOfElement = sizeof(UIVertex_2017);
     }
 }
Example #5
0
        public static void Patch()
        {
            unsafe
            {
                var setupMethod = typeof(PageWorldInfo).GetMethods()
                                  .Where(m =>
                                         m.Name.StartsWith("Method_Public_Void_ApiWorld_ApiWorldInstance_Boolean_Boolean_") &&
                                         !m.Name.Contains("PDM"))
                                  .OrderBy(m => m.GetCustomAttribute <CallerCountAttribute>().Count)
                                  .Last();

                // Thanks to Knah
                var originalMethod = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(setupMethod).GetValue(null);

                MelonUtils.NativeHookAttach((IntPtr)(&originalMethod), typeof(WorldInfoSetup).GetMethod(nameof(Postfix), BindingFlags.Static | BindingFlags.Public) !.MethodHandle.GetFunctionPointer());

                worldInfoSetupDelegate = Marshal.GetDelegateForFunctionPointer <WorldInfoSetupDelegate>(originalMethod);
            }
        }
        private bool CheckPlatformDomainAttribute()
        {
            MelonPlatformDomainAttribute platformDomainAttribute = MelonUtils.PullAttributeFromAssembly <MelonPlatformDomainAttribute>(Assembly);

            if ((platformDomainAttribute == null) ||
                (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.UNIVERSAL))
            {
                return(true);
            }
            bool is_il2cpp_expected_mono = (MelonUtils.IsGameIl2Cpp() && (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.MONO));
            bool is_mono_expected_il2cpp = (!MelonUtils.IsGameIl2Cpp() && (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.IL2CPP));

            if (is_il2cpp_expected_mono || is_mono_expected_il2cpp)
            {
                MelonLogger.Error($"Incompatible Platform Domain for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}");
                return(false);
            }
            return(true);
        }
Example #7
0
        internal static int LoadAndRun(LemonFunc <int> functionToWaitForAsync)
        {
            // We don't support Unity versions under 2017.2.0 (yet?)
            if (!MelonLaunchOptions.Core.StartScreen || !MelonUtils.GetUnityVersion().StartsWith("20") || MelonUtils.GetUnityVersion().StartsWith("2017.1"))
            {
                return(functionToWaitForAsync());
            }

            if (!Load())
            {
                return(functionToWaitForAsync());
            }

            if (LoadAndRunMethod != null)
            {
                return((int)LoadAndRunMethod.Invoke(null, new object[] { functionToWaitForAsync }));
            }

            return(-1);
        }
Example #8
0
        private unsafe static bool PatchIl2CppExport()
        {
            NativeLibrary il2cppLibrary = NativeLibrary.Load(Path.Combine(MelonUtils.GameDirectory, "GameAssembly.dll"));
            IntPtr        export        = il2cppLibrary.GetExport("il2cpp_unity_install_unitytls_interface");

            if (export == IntPtr.Zero)
            {
                Logger.Error("Failed to find il2cpp_unity_install_unitytls_interface!");
                return(false);
            }

            Logger.Msg("Patching il2cpp_unity_install_unitytls_interface...");
            MethodInfo patch    = typeof(Il2CppUnityTls_Module).GetMethod("SetUnityTlsInterface", BindingFlags.NonPublic | BindingFlags.Static);
            IntPtr     patchptr = patch.MethodHandle.GetFunctionPointer();

            MelonUtils.NativeHookAttach((IntPtr)(&export), patchptr);
            OriginalSetUnityTlsInterface = (dSetUnityTlsInterface)Marshal.GetDelegateForFunctionPointer(export, typeof(dSetUnityTlsInterface));

            return(true);
        }
Example #9
0
        public override void Setup()
        {
            HarmonyLib.Harmony harmony = new HarmonyLib.Harmony("DemeoIntegration");

            harmony.Patch(typeof(GameStateMachine).GetMethod("GetConnectionString", BindingFlags.Public | BindingFlags.Static),
                          typeof(Demeo_Module).GetMethod("GetConnectionString", BindingFlags.NonPublic | BindingFlags.Static).ToNewHarmonyMethod());

            if (MelonUtils.IsGameIl2Cpp())
            {
                Il2Cpp.Patch(harmony);
            }
            else
            {
                Mono.Patch(harmony);
            }

            MelonCompatibilityLayer.AddRefreshPluginsEvent(Refresh);
            MelonCompatibilityLayer.AddRefreshModsEvent(Refresh);
            Refresh();
        }
Example #10
0
        internal static void LoadAll(string folderpath, bool is_plugins = false)
        {
            MelonLaunchOptions.Core.LoadModeEnum loadMode = is_plugins
                ? MelonLaunchOptions.Core.LoadMode_Plugins
                : MelonLaunchOptions.Core.LoadMode_Mods;
            string[] filearr = Directory.GetFiles(folderpath).Where(x =>
                                                                    Path.GetExtension(x).ToLowerInvariant().Equals(".dll") &&
                                                                    ((loadMode == MelonLaunchOptions.Core.LoadModeEnum.DEV) ? x.ToLowerInvariant().EndsWith(".dev.dll")
                : ((loadMode == MelonLaunchOptions.Core.LoadModeEnum.NORMAL) ? !x.ToLowerInvariant().EndsWith(".dev.dll")
                : true))
                                                                    ).ToArray();
            if (filearr.Length <= 0)
            {
                return;
            }

            for (int i = 0; i < filearr.Length; i++)
            {
                string filepath = filearr[i];
                if (string.IsNullOrEmpty(filepath))
                {
                    continue;
                }

                string melonname = MelonUtils.GetFileProductName(filepath);
                if (string.IsNullOrEmpty(melonname))
                {
                    melonname = Path.GetFileNameWithoutExtension(filepath);
                }

                if (is_plugins
                    ? MelonHandler.IsPluginAlreadyLoaded(melonname)
                    : MelonHandler.IsModAlreadyLoaded(melonname))
                {
                    MelonLogger.Error($"Duplicate File: {filepath}");
                    continue;
                }

                LoadFromFile(filepath);
            }
        }
Example #11
0
        private bool CheckGameVersionAttribute()
        {
            if (!is_plugin) // Temporarily Skip this Check for Plugins
            {
                return(true);
            }

            List <MelonGameVersionAttribute> gameVersionAttributes = MelonUtils.PullAttributesFromAssembly <MelonGameVersionAttribute>(Assembly).ToList();

            if (gameVersionAttributes.Count <= 0)
            {
                return(true);
            }

            string game_version  = GameVersionHandler.Version;
            bool   is_compatible = false;

            for (int i = 0; i < gameVersionAttributes.Count; i++)
            {
                MelonGameVersionAttribute melonGameVersionAttribute = gameVersionAttributes[i];
                if (melonGameVersionAttribute == null)
                {
                    continue;
                }

                if (melonGameVersionAttribute.Universal ||
                    game_version.Equals(melonGameVersionAttribute.Version))
                {
                    is_compatible = true;
                    break;
                }
            }
            if (!is_compatible)
            {
                //MelonLogger.Error($"Incompatible Game Version for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}");
                MelonLogger.Error($"Incompatible Game Version for Mod: {FilePath}");
                return(false);
            }

            return(true);
        }
Example #12
0
        internal static void Init()
        {
            if (disabled)
            {
                return;
            }

            MelonDebug.Msg("Initializing UIStyleValues");
            UIStyleValues.Init();
            MelonDebug.Msg("UIStyleValues Initialized");

            TextGenerationSettings settings = new TextGenerationSettings();

            settings.textAnchor        = TextAnchor.MiddleCenter;
            settings.color             = new Color(1, 1, 1);
            settings.generationExtents = new Vector2(540, 47.5f);
            settings.richText          = true;
            settings.font             = UIStyleValues.standardFont;
            settings.pivot            = new Vector2(0.5f, 0.5f);
            settings.fontSize         = 24;
            settings.fontStyle        = FontStyle.Bold;
            settings.verticalOverflow = VerticalWrapMode.Overflow;
            settings.scaleFactor      = 1f;
            settings.lineSpacing      = 1f;
            MelonDebug.Msg("TextGenerationSettings settings set");

            string melonloaderText = (MelonLaunchOptions.Console.Mode == MelonLaunchOptions.Console.DisplayMode.LEMON)
                ? "<color=#FFCC4D>LemonLoader</color>"
                : "<color=#78f764>Melon</color><color=#ff3c6a>Loader</color>";

            melonloaderversionTextmesh = TextMeshGenerator.Generate($"{melonloaderText} v{BuildInfo.Version} Open-Beta", settings);

            progressBar = new ProgressBar(width: 540, height: 36);

            uint graphicsDeviceType = SystemInfo.GetGraphicsDeviceType();

            MelonDebug.Msg("Graphics Device Type: " + graphicsDeviceType);
            shouldCallWFLPAGT = NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new[] { "2020.2.7", "2020.3.0", "2021.1.0" }) &&
                                (graphicsDeviceType == /*DX11*/ 2 || graphicsDeviceType == /*DX12*/ 18)
                ? graphicsDeviceType : 0;
        }
Example #13
0
        private bool CheckVerifyLoaderVersionAttribute()
        {
            VerifyLoaderVersionAttribute verifyLoaderVersionAttribute = MelonUtils.PullAttributeFromAssembly <VerifyLoaderVersionAttribute>(Assembly);

            if (verifyLoaderVersionAttribute == null)
            {
                return(true);
            }

            bool is_acceptable = verifyLoaderVersionAttribute.IsMinimum
                ? (verifyLoaderVersionAttribute.SemVer <= BuildInfo.Version)
                : (verifyLoaderVersionAttribute.SemVer == BuildInfo.Version);

            if (!is_acceptable)
            {
                MelonLogger.Error($"Incompatible MelonLoader Version for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}");
                return(false);
            }

            return(true);
        }
Example #14
0
        private bool CheckPlatformDomainAttribute()
        {
            MelonPlatformDomainAttribute platformDomainAttribute = MelonUtils.PullAttributeFromAssembly <MelonPlatformDomainAttribute>(Assembly);

            if ((platformDomainAttribute == null) ||
                (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.UNIVERSAL))
            {
                return(true);
            }

            bool is_acceptable = MelonUtils.IsGameIl2Cpp()
                ? (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.IL2CPP)
                : (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.MONO);

            if (!is_acceptable)
            {
                MelonLogger.Error($"Incompatible Platform Domain for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}");
                return(false);
            }

            return(true);
        }
Example #15
0
        private bool CheckProcessAttributes()
        {
            List <MelonProcessAttribute> processAttributes = MelonUtils.PullAttributesFromAssembly <MelonProcessAttribute>(Assembly).ToList();

            if (processAttributes.Count <= 0)
            {
                return(true);
            }

            string current_exe_path        = Process.GetCurrentProcess().MainModule.FileName;
            string current_exe_name        = Path.GetFileName(current_exe_path);
            string current_exe_name_no_ext = Path.GetFileNameWithoutExtension(current_exe_path);

            bool is_compatible = false;

            for (int i = 0; i < processAttributes.Count; i++)
            {
                MelonProcessAttribute melonProcessAttribute = processAttributes[i];
                if (melonProcessAttribute == null)
                {
                    continue;
                }

                if (melonProcessAttribute.Universal ||
                    current_exe_name.Equals(melonProcessAttribute.EXE_Name) ||
                    current_exe_name_no_ext.Equals(melonProcessAttribute.EXE_Name))
                {
                    is_compatible = true;
                    break;
                }
            }
            if (!is_compatible)
            {
                MelonLogger.Error($"Incompatible Process Executable for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}");
                return(false);
            }

            return(true);
        }
Example #16
0
        static Texture2D()
        {
            InternalClassPointerStore <Texture2D> .NativeClassPtr = UnityInternals.GetClass("UnityEngine.CoreModule.dll", "UnityEngine", "Texture2D");
            UnityInternals.runtime_class_init(InternalClassPointerStore <Texture2D> .NativeClassPtr);

            m_ctor = UnityInternals.GetMethod(InternalClassPointerStore <Texture2D> .NativeClassPtr, ".ctor", "System.Void", "System.Int32", "System.Int32");

            m_get_whiteTexture = UnityInternals.GetMethod(InternalClassPointerStore <Texture2D> .NativeClassPtr, "get_whiteTexture", "UnityEngine.Texture2D");

            if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2018.1.0" }))
            {
                type_SetPixelsImpl   = 1;
                m_SetPixelsImpl_2018 = UnityInternals.ResolveICall <SetPixelsImplDelegate_2018>("UnityEngine.Texture2D::SetPixelsImpl");
            }
            else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2017.1.0" }))
            {
                type_SetPixelsImpl   = 0;
                m_SetPixelsImpl_2017 = UnityInternals.ResolveICall <SetPixelsImplDelegate_2017>("UnityEngine.Texture2D::SetPixels");
            }

            m_Apply = UnityInternals.GetMethod(InternalClassPointerStore <Texture2D> .NativeClassPtr, "Apply", "System.Void");
        }
Example #17
0
        private bool CheckVerifyLoaderBuildAttribute()
        {
            VerifyLoaderBuildAttribute verifyLoaderBuildAttribute = MelonUtils.PullAttributeFromAssembly <VerifyLoaderBuildAttribute>(Assembly);

            if ((verifyLoaderBuildAttribute == null) ||
                string.IsNullOrEmpty(verifyLoaderBuildAttribute.HashCode))
            {
                return(true);
            }
            string currentHashCode = MelonUtils.HashCode;

            if (string.IsNullOrEmpty(currentHashCode))
            {
                return(true);
            }
            if (!currentHashCode.Equals(verifyLoaderBuildAttribute.HashCode))
            {
                MelonLogger.Error($"Incompatible MelonLoader Build for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}");
                return(false);
            }
            return(true);
        }
Example #18
0
        private unsafe static void RunInstallFunction()
        {
            IntPtr unityplayer = GetUnityPlayerModule(out int unityplayer_size);

            if (unityplayer == IntPtr.Zero)
            {
                return;
            }

            IntPtr[] ptrs = null;
            if (MelonUtils.IsGame32Bit())
            {
                ptrs = GetPointers(unityplayer, unityplayer_size, Signatures_x86);
            }
            else
            {
                ptrs = GetPointers(unityplayer, unityplayer_size, Signatures_x64);
            }

            if ((ptrs == null) || (ptrs.Length <= 0))
            {
                Logger.Warning("Unable to find Il2CppInstallUnityTlsInterface!");
                return;
            }

            foreach (IntPtr ptr in ptrs)
            {
                byte *i = (byte *)ptr.ToPointer();
                if (*i == 0 || (*i & 0xF) == 0xF)
                {
                    continue;
                }
                Logger.Msg("Calling Il2CppInstallUnityTlsInterface...");
                VoidDelegate installUnityTlsInterface = (VoidDelegate)Marshal.GetDelegateForFunctionPointer(ptr, typeof(VoidDelegate));
                installUnityTlsInterface();
                break;
            }
        }
Example #19
0
        internal static IntPtr GetClass(string assemblyname, string name_space, string classname)
        {
            MelonDebug.Msg($"GetClass {assemblyname} {name_space} {classname}");
            if (MelonUtils.IsGameIl2Cpp())
            {
                InternalAssembly assembly = assemblies.FirstOrDefault(a => a.name == assemblyname);
                if (assembly == null)
                {
                    throw new Exception("Unable to find assembly " + assemblyname + " in il2cpp domain");
                }

                IntPtr clazz = il2cpp_class_from_name(assembly.ptr, name_space, classname);
                if (clazz == null)
                {
                    throw new Exception("Unable to find class " + name_space + "." + classname + " in assembly " + assemblyname);
                }

                MelonDebug.Msg($" > 0x{(long)clazz:X}");
                return(clazz);
            }
            else
            {
                string   fullname = string.IsNullOrEmpty(name_space) ? "" : (name_space + ".") + classname;
                Assembly ass      = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name + ".dll" == assemblyname);
                if (ass == null)
                {
                    throw new Exception("Unable to find assembly " + assemblyname + " in mono domain");
                }

                Type t = ass.GetType(fullname);
                if (t == null)
                {
                    throw new Exception("Unable to find class " + fullname + " in assembly " + assemblyname);
                }
                MelonDebug.Msg($" > 0x{(long)(*(IntPtr*)t.TypeHandle.Value):X}");
                return(*(IntPtr *)t.TypeHandle.Value);
            }
        }
Example #20
0
        private unsafe static bool PatchExports()
        {
            IntPtr monolib = MonoLibrary.GetLibPtr();

            if (monolib == IntPtr.Zero)
            {
                Logger.Warning("Unable to find Mono Library Pointer!");
                return(false);
            }

            NativeLibrary monoLibrary = new NativeLibrary(monolib);
            IntPtr        mono_export = monoLibrary.GetExport("mono_unity_get_unitytls_interface");

            if (mono_export == IntPtr.Zero)
            {
                Logger.Warning("Unable to find Mono's mono_unity_get_unitytls_interface Export!");
                return(false);
            }

            NativeLibrary il2cppLibrary = NativeLibrary.Load(Path.Combine(MelonUtils.GameDirectory, "GameAssembly.dll"));
            IntPtr        il2cpp_export = il2cppLibrary.GetExport("il2cpp_unity_install_unitytls_interface");

            if (il2cpp_export == IntPtr.Zero)
            {
                Logger.Warning("Unable to find Il2Cpp's il2cpp_unity_install_unitytls_interface Export!");
                return(false);
            }

            Logger.Msg("Patching mono_unity_get_unitytls_interface...");
            MelonUtils.NativeHookAttach((IntPtr)(&mono_export), typeof(Il2CppUnityTls_Module).GetMethod("GetUnityTlsInterface", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer());

            Logger.Msg("Patching il2cpp_unity_install_unitytls_interface...");
            MelonUtils.NativeHookAttach((IntPtr)(&il2cpp_export), typeof(Il2CppUnityTls_Module).GetMethod("SetUnityTlsInterface", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer());
            OriginalSetUnityTlsInterface = (dSetUnityTlsInterface)Marshal.GetDelegateForFunctionPointer(il2cpp_export, typeof(dSetUnityTlsInterface));

            return(true);
        }
Example #21
0
        public override void OnApplicationStart()
        {
            var library = LoadLibrary(MelonUtils.GetGameDataDirectory() + "\\Plugins\\steam_api64.dll");

            if (library == IntPtr.Zero)
            {
                MelonLogger.LogError("Library load failed");
                return;
            }
            var names = new[]
            {
                "SteamAPI_Init",
                "SteamAPI_RestartAppIfNecessary",
                "SteamAPI_GetHSteamUser",
                "SteamAPI_RegisterCallback",
                "SteamAPI_UnregisterCallback",
                "SteamAPI_RunCallbacks",
                "SteamAPI_Shutdown"
            };

            foreach (var name in names)
            {
                unsafe
                {
                    var address = GetProcAddress(library, name);
                    if (address == IntPtr.Zero)
                    {
                        MelonLogger.LogError($"Procedure {name} not found");
                        continue;
                    }
                    Imports.Hook((IntPtr)(&address),
                                 AccessTools.Method(typeof(NoSteamAtAllMod), nameof(InitFail)).MethodHandle
                                 .GetFunctionPointer());
                }
            }
        }
Example #22
0
 public static int class_value_size(IntPtr klass, ref uint align) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_class_value_size(klass, ref align) : mono_class_value_size(klass, ref align);
        private static void ReadGameInfo(AssetsManager assetsManager)
        {
            string             gameDataPath = MelonUtils.GetGameDataDirectory();
            AssetsFileInstance instance     = null;

            try
            {
                string bundlePath = Path.Combine(gameDataPath, "globalgamemanagers");
                if (!File.Exists(bundlePath))
                {
                    bundlePath = Path.Combine(gameDataPath, "mainData");
                }

                if (!File.Exists(bundlePath))
                {
                    bundlePath = Path.Combine(gameDataPath, "data.unity3d");
                    if (!File.Exists(bundlePath))
                    {
                        return;
                    }

                    BundleFileInstance bundleFile = assetsManager.LoadBundleFile(bundlePath);
                    instance = assetsManager.LoadAssetsFileFromBundle(bundleFile, "globalgamemanagers");
                }
                else
                {
                    instance = assetsManager.LoadAssetsFile(bundlePath, true);
                }
                if (instance == null)
                {
                    return;
                }

                assetsManager.LoadIncludedClassPackage();
                if (!instance.file.typeTree.hasTypeTree)
                {
                    assetsManager.LoadClassDatabaseFromPackage(instance.file.typeTree.unityVersion);
                }
                EngineVersion = UnityVersion.Parse(instance.file.typeTree.unityVersion);

                List <AssetFileInfoEx> assetFiles = instance.table.GetAssetsOfType(129);
                if (assetFiles.Count > 0)
                {
                    AssetFileInfoEx playerSettings = assetFiles.First();

                    AssetTypeInstance assetTypeInstance = null;
                    try
                    {
                        assetTypeInstance = assetsManager.GetTypeInstance(instance, playerSettings);
                    }
                    catch (Exception ex)
                    {
                        if (MelonDebug.IsEnabled())
                        {
                            MelonLogger.Error(ex);
                            MelonLogger.Warning("Attempting to use Large Class Package...");
                        }
                        assetsManager.LoadIncludedLargeClassPackage();
                        assetsManager.LoadClassDatabaseFromPackage(instance.file.typeTree.unityVersion);
                        assetTypeInstance = assetsManager.GetTypeInstance(instance, playerSettings);
                    }

                    if (assetTypeInstance != null)
                    {
                        AssetTypeValueField playerSettings_baseField = assetTypeInstance.GetBaseField();

                        AssetTypeValueField bundleVersion = playerSettings_baseField.Get("bundleVersion");
                        if (bundleVersion != null)
                        {
                            GameVersion = bundleVersion.GetValue().AsString();
                        }

                        AssetTypeValueField companyName = playerSettings_baseField.Get("companyName");
                        if (companyName != null)
                        {
                            GameDeveloper = companyName.GetValue().AsString();
                        }

                        AssetTypeValueField productName = playerSettings_baseField.Get("productName");
                        if (productName != null)
                        {
                            GameName = productName.GetValue().AsString();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (MelonDebug.IsEnabled())
                {
                    MelonLogger.Error(ex);
                }
                MelonLogger.Error("Failed to Initialize Assets Manager!");
            }
            if (instance != null)
            {
                instance.file.Close();
            }
        }
Example #24
0
        public override void OnApplicationStart()
        {
            var pluginsPath = MelonUtils.GetGameDataDirectory() + "/Plugins";
            var dllName     = ShaderFilterApi.DLLName + ".dll";

            try
            {
                using var resourceStream = Assembly.GetExecutingAssembly()
                                           .GetManifestResourceStream(typeof(TrueShaderAntiCrashMod), dllName);
                using var fileStream = File.Open(pluginsPath + "/" + dllName, FileMode.Create, FileAccess.Write);

                resourceStream.CopyTo(fileStream);
            }
            catch (IOException ex)
            {
                MelonLogger.Warning("Failed to write native unity plugin; will attempt loading it anyway. This is normal if you're running multiple instances of VRChat");
                MelonDebug.Msg(ex.ToString());
            }

            var process = Process.GetCurrentProcess();

            foreach (ProcessModule module in process.Modules)
            {
                if (!module.FileName.Contains("UnityPlayer"))
                {
                    continue;
                }

                var loadLibraryAddress = module.BaseAddress + 0x819130;
                var dg = Marshal.GetDelegateForFunctionPointer <FindAndLoadUnityPlugin>(loadLibraryAddress);

                var strPtr = Marshal.StringToHGlobalAnsi(ShaderFilterApi.DLLName);

                dg(strPtr, out var loaded);

                if (loaded == IntPtr.Zero)
                {
                    MelonLogger.Error("Module load failed");
                    return;
                }

                ShaderFilterApi.Init(loaded);

                Marshal.FreeHGlobal(strPtr);

                break;
            }

            var category = MelonPreferences.CreateCategory("True Shader Anticrash");

            var loopsEnabled    = (MelonPreferences_Entry <bool>)category.CreateEntry("LimitLoops", true, "Limit loops");
            var geometryEnabled = (MelonPreferences_Entry <bool>)category.CreateEntry("LimitGeometry", true, "Limit geometry shaders");
            var tessEnabled     = (MelonPreferences_Entry <bool>)category.CreateEntry("LimitTesselation", true, "Limit tesselation");

            MelonPreferences_Entry <bool> enabledInPublicsOnly = null;

            IEnumerator WaitForRoomManagerAndUpdate()
            {
                while (RoomManager.field_Internal_Static_ApiWorldInstance_0 == null)
                {
                    yield return(null);
                }

                UpdateLimiters();
            }

            void UpdateLimiters()
            {
                if (enabledInPublicsOnly.Value)
                {
                    var room = RoomManager.field_Internal_Static_ApiWorldInstance_0;
                    if (room == null)
                    {
                        MelonCoroutines.Start(WaitForRoomManagerAndUpdate());
                        return;
                    }

                    if (room.GetAccessType() != ApiWorldInstance.AccessType.Public)
                    {
                        ShaderFilterApi.SetFilteringState(false, false, false);
                        return;
                    }
                }

                ShaderFilterApi.SetFilteringState(loopsEnabled.Value, geometryEnabled.Value, tessEnabled.Value);
            }

            loopsEnabled.OnValueChanged    += (_, value) => UpdateLimiters();
            geometryEnabled.OnValueChanged += (_, value) => UpdateLimiters();
            tessEnabled.OnValueChanged     += (_, value) => UpdateLimiters();

            var maxLoopIterations = (MelonPreferences_Entry <int>)category.CreateEntry("MaxLoopIterations", 128, "Max loop iterations");

            maxLoopIterations.OnValueChanged += (_, value) => ShaderFilterApi.SetLoopLimit(value);

            var maxGeometry = (MelonPreferences_Entry <int>)category.CreateEntry("MaxGeometryOutputs", 60, "Max geometry shader outputs");

            maxGeometry.OnValueChanged += (_, value) => ShaderFilterApi.SetLoopLimit(value);

            var maxTess = (MelonPreferences_Entry <float>)category.CreateEntry("MaxTesselation", 5f, "Max tesselation power");

            maxTess.OnValueChanged += (_, value) => ShaderFilterApi.SetMaxTesselationPower(value);

            var enabledForWorlds = (MelonPreferences_Entry <bool>)category.CreateEntry("DisableDuringWorldLoad", true, "Try to avoid affecting world shaders");

            enabledInPublicsOnly = (MelonPreferences_Entry <bool>)category.CreateEntry("EnabledInPublicsOnly", false, "Only enabled in public instances");

            SceneManager.add_sceneLoaded(new Action <Scene, LoadSceneMode>((sc, _) =>
            {
                if (sc.buildIndex == -1)
                {
                    UpdateLimiters();
                }
            }));

            SceneManager.add_sceneUnloaded(new Action <Scene>(_ =>
            {
                if (enabledForWorlds.Value)
                {
                    ShaderFilterApi.SetFilteringState(false, false, false);
                }
            }));

            UpdateLimiters();
            ShaderFilterApi.SetMaxTesselationPower(maxTess.Value);
            ShaderFilterApi.SetLoopLimit(maxLoopIterations.Value);
            ShaderFilterApi.SetGeometryLimit(maxGeometry.Value);

            if (MelonHandler.Mods.Any(it =>
                                      it.Assembly.GetName().Name == "UIExpansionKit" &&
                                      it.Assembly.GetName().Version >= new Version(0, 2, 4)))
            {
                AddNewUixProperties(category.Identifier);
            }
        }
Example #25
0
 public static uint gchandle_new(IntPtr obj, bool pinned) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_gchandle_new(obj, pinned) : mono_gchandle_new(obj, pinned ? 1 : 0);
Example #26
0
        public override void OnApplicationStart()
        {
            /* Register settings */
            Settings.RegisterConfig();

            /* Load audio settings */
            WorldAudio.LoadConfig();

            /* Load avatar parameters */
            Parameters.LoadConfig();

            /* Load our custom UI elements */
            UiExpansion.LoadUiObjects();

            /* TODO: Consider switching to operator+ when everyone had to update the assembly unhollower */
            /*       The current solution might be prefereable so we are always first */
            VRCAvatarManager.field_Private_Static_Action_3_Player_GameObject_VRC_AvatarDescriptor_0 += (Il2CppSystem.Action <Player, GameObject, VRC.SDKBase.VRC_AvatarDescriptor>)OnAvatarInstantiate;

            /* Register async, awaiting network manager */
            MelonCoroutines.Start(RegisterJoinLeaveNotifier());

            ExpansionKitApi.GetExpandedMenu(ExpandedMenu.QuickMenu).AddSimpleButton("Player List", PlayerList);
            ExpansionKitApi.GetExpandedMenu(ExpandedMenu.QuickMenu).AddSimpleButton("WorldCleanup", MainMenu);
            ExpansionKitApi.GetExpandedMenu(ExpandedMenu.UserQuickMenu).AddSimpleButton("Avatar Toggles", OnUserQuickMenu);

            /* Hook into setter for parameter properties */
            unsafe
            {
                var param_prop_bool_set = (IntPtr)typeof(AvatarParameter).GetField("NativeMethodInfoPtr_Method_Public_Virtual_Final_New_set_Void_Boolean_0", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
                MelonUtils.NativeHookAttach(param_prop_bool_set, new Action <IntPtr, bool>(Parameters.BoolPropertySetter).Method.MethodHandle.GetFunctionPointer());
                Parameters._boolPropertySetterDelegate = Marshal.GetDelegateForFunctionPointer <Parameters.BoolPropertySetterDelegate>(*(IntPtr *)(void *)param_prop_bool_set);

                var param_prop_int_set = (IntPtr)typeof(AvatarParameter).GetField("NativeMethodInfoPtr_Method_Public_Virtual_Final_New_set_Void_Int32_0", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
                MelonUtils.NativeHookAttach(param_prop_int_set, new Action <IntPtr, int>(Parameters.IntPropertySetter).Method.MethodHandle.GetFunctionPointer());
                Parameters._intPropertySetterDelegate = Marshal.GetDelegateForFunctionPointer <Parameters.IntPropertySetterDelegate>(*(IntPtr *)(void *)param_prop_int_set);

                var param_prop_float_set = (IntPtr)typeof(AvatarParameter).GetField("NativeMethodInfoPtr_Method_Public_Virtual_Final_New_set_Void_Single_0", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
                MelonUtils.NativeHookAttach(param_prop_float_set, new Action <IntPtr, float>(Parameters.FloatPropertySetter).Method.MethodHandle.GetFunctionPointer());
                Parameters._floatPropertySetterDelegate = Marshal.GetDelegateForFunctionPointer <Parameters.FloatPropertySetterDelegate>(*(IntPtr *)(void *)param_prop_float_set);
            }

            AMUtils.AddToModsFolder("Player Toggles", () =>
            {
                /* Filter inactive avatar objects */
                s_PlayerList = s_PlayerList.Where(o => o.Value).ToDictionary(o => o.Key, o => o.Value);

                /* Order by physical distance to camera */
                var query = from player in s_PlayerList
                            orderby Vector3.Distance(player.Value.transform.position, Camera.main.transform.position)
                            select player;

                /* Only allow a max of 10 players there at once */
                /* TODO: Consider adding multiple pages */
                var remaining_count = 10;

                foreach (var entry in query)
                {
                    var manager = entry.Value.GetComponentInParent <VRCAvatarManager>();

                    /* Ignore SDK2 & avatars w/o custom expressions */
                    if (!manager.HasCustomExpressions())
                    {
                        continue;
                    }

                    var avatar_id = entry.Value.GetComponent <VRC.Core.PipelineManager>().blueprintId;
                    var user_icon = s_Portraits[avatar_id].Get();

                    /* Source default expression icon */
                    var menu_icons         = ActionMenuDriver.prop_ActionMenuDriver_0.field_Public_MenuIcons_0;
                    var default_expression = menu_icons.defaultExpression;

                    CustomSubMenu.AddSubMenu(entry.Key, () =>
                    {
                        if (entry.Value == null || !entry.Value.active)
                        {
                            return;
                        }

                        var parameters        = manager.GetAllAvatarParameters();
                        var filtered          = Parameters.FilterDefaultParameters(parameters);
                        var avatar_descriptor = manager.prop_VRCAvatarDescriptor_0;

                        CustomSubMenu.AddToggle("Lock", filtered.Any(Parameters.IsLocked), (state) => { filtered.ForEach(state ? Parameters.Lock : Parameters.Unlock); }, icon: UiExpansion.LockClosedIcon);
                        CustomSubMenu.AddButton("Save", () => Parameters.StoreParameters(manager), icon: UiExpansion.SaveIcon);

                        AvatarParameter FindParameter(string name)
                        {
                            foreach (var parameter in parameters)
                            {
                                if (parameter.field_Private_String_0 == name)
                                {
                                    return(parameter);
                                }
                            }
                            return(null);
                        }

                        void ExpressionSubmenu(VRCExpressionsMenu expressions_menu)
                        {
                            if (entry.Value == null || !entry.Value.active)
                            {
                                return;
                            }

                            void FourAxisControl(VRCExpressionsMenu.Control control, Action <Vector2> callback)
                            {
                                CustomSubMenu.AddFourAxisPuppet(
                                    control.TruncatedName(),
                                    callback,
                                    icon: control.icon ?? default_expression,
                                    topButtonText: control.labels[0]?.TruncatedName() ?? "Up",
                                    rightButtonText: control.labels[1]?.TruncatedName() ?? "Right",
                                    downButtonText: control.labels[2]?.TruncatedName() ?? "Down",
                                    leftButtonText: control.labels[3]?.TruncatedName() ?? "Left");
                            }

                            foreach (var control in expressions_menu.controls)
                            {
                                try
                                {
                                    switch (control.type)
                                    {
                                    case VRCExpressionsMenu.Control.ControlType.Button:
                                    /* Note: Action Menu "Buttons" are actually Toggles */
                                    /*       that set on press and revert on release.   */
                                    /* TODO: Add proper implementation.                 */
                                    case VRCExpressionsMenu.Control.ControlType.Toggle:
                                        {
                                            var param         = FindParameter(control.parameter.name);
                                            var current_value = param.GetValue();
                                            var default_value = avatar_descriptor.expressionParameters.FindParameter(control.parameter.name)?.defaultValue ?? 0f;
                                            var target_value  = control.value;
                                            void SetIntFloat(bool state) => param.SetValue(state ? target_value : default_value);
                                            void SetBool(bool state) => param.SetValue(state ? 1f : 0f);

                                            CustomSubMenu.AddToggle(
                                                control.TruncatedName(),
                                                current_value == target_value,
                                                param.prop_ParameterType_0 == AvatarParameter.ParameterType.Bool ? SetBool : SetIntFloat,
                                                icon: control.icon ?? default_expression);
                                            break;
                                        }

                                    case VRCExpressionsMenu.Control.ControlType.SubMenu:
                                        {
                                            CustomSubMenu.AddSubMenu(control.TruncatedName(), () => ExpressionSubmenu(control.subMenu), icon: control.icon ?? default_expression);
                                            break;
                                        }

                                    case VRCExpressionsMenu.Control.ControlType.TwoAxisPuppet:
                                        {
                                            var horizontal = FindParameter(control.subParameters[0]?.name);
                                            var vertical   = FindParameter(control.subParameters[1]?.name);
                                            FourAxisControl(control, (value) =>
                                            {
                                                horizontal.SetFloatProperty(value.x);
                                                vertical.SetFloatProperty(value.y);
                                            });
                                            break;
                                        }

                                    case VRCExpressionsMenu.Control.ControlType.FourAxisPuppet:
                                        {
                                            var up    = FindParameter(control.subParameters[0]?.name);
                                            var down  = FindParameter(control.subParameters[1]?.name);
                                            var left  = FindParameter(control.subParameters[2]?.name);
                                            var right = FindParameter(control.subParameters[3]?.name);
                                            FourAxisControl(control, (value) =>
                                            {
                                                up.SetFloatProperty(Math.Max(0, value.y));
                                                down.SetFloatProperty(-Math.Min(0, value.y));
                                                left.SetFloatProperty(Math.Max(0, value.x));
                                                right.SetFloatProperty(-Math.Min(0, value.x));
                                            });
                                            break;
                                        }

                                    case VRCExpressionsMenu.Control.ControlType.RadialPuppet:
                                        {
                                            var param = FindParameter(control.subParameters[0]?.name);
                                            CustomSubMenu.AddRestrictedRadialPuppet(control.TruncatedName(), param.SetValue, startingValue: param.GetValue(), icon: control.icon ?? default_expression);
                                            break;
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    MelonLogger.Error(e.StackTrace);
                                }
                            }
                        }

                        ExpressionSubmenu(avatar_descriptor.expressionsMenu);
                    }, icon: user_icon);

                    if (--remaining_count == 0)
                    {
                        break;
                    }
                }
            });

            MelonLogger.Msg(ConsoleColor.Green, "WorldCleanup ready!");
        }
Example #27
0
 static GfxDevice()
 {
     if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new[] { "2020.2.7", "2020.3.0", "2021.1.0" }))
     {
         // `FrameTimingManager_CUSTOM_CaptureFrameTimings()` calls `GetRealGfxDevice()` after 4 bytes.
         m_GetRealGfxDevice = (GetRealGfxDeviceDelegate)Marshal.GetDelegateForFunctionPointer(
             CppUtils.ResolveRelativeInstruction(
                 (IntPtr)((long)UnityInternals.ResolveICall("UnityEngine.FrameTimingManager::CaptureFrameTimings") + (MelonUtils.IsGame32Bit() ? 0 : 4))),
             typeof(GetRealGfxDeviceDelegate));
     }
 }
Example #28
0
 public static IntPtr gchandle_get_target(uint gchandle) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_gchandle_get_target(gchandle) : mono_gchandle_get_target(gchandle);
Example #29
0
 public static void format_stack_trace(IntPtr ex, void *output, int output_size)
 {
     if (MelonUtils.IsGameIl2Cpp())
         il2cpp_format_stack_trace(ex, output, output_size); }
Example #30
0
 public static IntPtr value_box(IntPtr klass, IntPtr val) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_value_box(klass, val) : mono_value_box(domain, klass, val);