private static void AcceptNotificationPatch(IntPtr thisPtr, IntPtr notificationPtr) { try { if (thisPtr == IntPtr.Zero || notificationPtr == IntPtr.Zero) { return; } if (Utilities.GetStreamerMode()) { acceptNotificationDelegate(thisPtr, notificationPtr); return; } Notification notification = new Notification(notificationPtr); if (notification.notificationType.Equals("invite", StringComparison.OrdinalIgnoreCase)) { InviteHandler.HandleInvite(notification); return; } } catch (Exception e) { MelonLogger.Error($"Exception in accept notification patch: {e}"); } acceptNotificationDelegate(thisPtr, notificationPtr); }
private bool CheckVerifyLoaderVersionAttribute() { VerifyLoaderVersionAttribute verifyLoaderVersionAttribute = MelonUtils.PullAttributeFromAssembly <VerifyLoaderVersionAttribute>(Assembly); if (verifyLoaderVersionAttribute == null) { return(true); } if (CurrentMLVersion == null) { CurrentMLVersion = SemVersion.Parse(BuildInfo.Version); } bool is_acceptable = verifyLoaderVersionAttribute.IsMinimum ? (verifyLoaderVersionAttribute.SemVer <= CurrentMLVersion) : (verifyLoaderVersionAttribute.SemVer == CurrentMLVersion); if (!is_acceptable) { MelonLogger.Error($"Incompatible MelonLoader Version for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}"); return(false); } return(true); }
public static void SetupSprite(string fileName, string configName, ref Sprite sprite, bool specialBorder = false) { string texturePath = SetupConfigFile(fileName, ref VRCPlusPet.emptyList); if (texturePath != null) { Texture2D newTexture = new Texture2D(2, 2); byte[] imageByteArray = File.ReadAllBytes(texturePath); //poka-yoke if (imageByteArray.Length < 67 || !ImageConversion.LoadImage(newTexture, imageByteArray)) { MelonLogger.Error(string.Format("Option \"{0}\" | Image loading error", configName)); } else { sprite = Sprite.CreateSprite(newTexture, new Rect(.0f, .0f, newTexture.width, newTexture.height), new Vector2(.5f, .5f), 100f, 0, 0, specialBorder ? new Vector4(35f, 55f, 62f, 41f) : new Vector4(), false); sprite.hideFlags |= HideFlags.DontUnloadUnusedAsset; } } else { MelonLogger.Warning(string.Format("Option \"{0}\" | Image not found (UserData/{1}/{2})", configName, configPath, fileName)); } }
public override void OnSceneWasUnloaded(int buildIndex, string sceneName) { foreach (object subscriber in melonLoaderEventSubscribers) { try { if (subscriber is Type subscriberAsType) { try { subscriberAsType.GetMethod("OnSceneWasUnloaded", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)?.Invoke(null, new object[2] { buildIndex, sceneName }); } catch (ArgumentException) { throw new ArgumentException($"Type {subscriberAsType.Name} which is subscribed to MelonLoaderEvents via an attribute has an OnSceneWasUnloaded that is not static."); } } else { (subscriber as MelonLoaderEvents).OnSceneWasUnloaded(buildIndex, sceneName); } } catch (Exception ex) { MelonLogger.Error($"Exception during OnSceneWasUnloaded:\n{ex}"); } } }
// Completely stolen from Psychloor's PlayerRotator (https://github.com/Psychloor/PlayerRotater) public static IEnumerator CheckWorld(ApiWorld world) { string worldId = world.id; // Check if black/whitelisted from EmmVRC - thanks Emilia and the rest of EmmVRC Staff WWW www = new WWW($"https://thetrueyoshifan.com/RiskyFuncsCheck.php?worldid={worldId}", null, new Dictionary <string, string>()); while (!www.isDone) { yield return(new WaitForEndOfFrame()); } string result = www.text?.Trim().ToLower(); www.Dispose(); if (!string.IsNullOrWhiteSpace(result)) { switch (result) { case "allowed": MelonLogger.Msg("World allowed to show player distance"); PlayerEntry.worldAllowed = true; yield break; case "denied": MelonLogger.Msg("World NOT allowed to show player distance"); PlayerEntry.worldAllowed = false; yield break; } } // no result from server or they're currently down // Check tags then. should also be in cache as it just got downloaded API.Fetch <ApiWorld>( worldId, new Action <ApiContainer>( container => { ApiWorld apiWorld; if ((apiWorld = container.Model.TryCast <ApiWorld>()) != null) { foreach (string worldTag in apiWorld.tags) { if (worldTag.IndexOf("game", StringComparison.OrdinalIgnoreCase) >= 0) { MelonLogger.Msg("World NOT allowed to show player distance"); PlayerEntry.worldAllowed = false; return; } } MelonLogger.Msg("World allowed to show player distance"); PlayerEntry.worldAllowed = true; return; } else { MelonLogger.Error("Failed to cast ApiModel to ApiWorld"); } }), disableCache: false); }
private string GetLatestVersion() { string githubResponse; try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.github.com/repos/Slaynash/VRCModUpdater/releases/latest"); request.Method = "GET"; request.KeepAlive = true; request.ContentType = "application/x-www-form-urlencoded"; request.UserAgent = $"VRCModUpdater/{VERSION}"; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); using (StreamReader requestReader = new StreamReader(response.GetResponseStream())) { githubResponse = requestReader.ReadToEnd(); } } catch (Exception e) { MelonLogger.Error("Failed to fetch latest plugin version info from github:\n" + e); return(null); } JObject obj = JsonConvert.DeserializeObject(githubResponse) as JObject; return(obj.GetValue("tag_name")?.ToString()); }
public void callupdater() { loadFile(); MelonLogger.Msg("Latest SticksUItilityMod version: " + latestVersion); MelonLogger.Msg("Checking for updates..."); if (File.Exists(modfile)) { try { using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(modfile, new ReaderParameters { ReadWrite = true })) { CustomAttribute melonInfoAttribute = assembly.CustomAttributes.First(a => a.AttributeType.Name == "AssemblyFileVersionAttribute"); assemblyVersion = melonInfoAttribute.ConstructorArguments[0].Value as string; } MelonLogger.Msg("Installed SticksUItilityMod version: " + assemblyVersion); } catch (Exception e) { MelonLogger.Error("Failed to load SticksUItilityMod. Redownloading.\n" + e); } } if (assemblyVersion != latestVersion) { Update(latestVersion); } }
private static ISupportModule_To Initialize(ISupportModule_From interface_from) { Interface = interface_from; string game_version = ApplicationHandler.GetVersion(); if (string.IsNullOrEmpty(game_version) || game_version.Equals("0")) { game_version = ApplicationHandler.GetBuildGUID(); } MelonLogger.Msg($"Game Version: {game_version}"); SetDefaultConsoleTitleWithGameName(game_version); UnityMappers.RegisterMappers(); try { SceneManager.sceneLoaded += OnSceneLoad; } catch (Exception ex) { MelonLogger.Error($"SceneManager.sceneLoaded override failed: {ex}"); } try { SceneManager.sceneUnloaded += OnSceneUnload; } catch (Exception ex) { MelonLogger.Error($"SceneManager.sceneUnloaded override failed: {ex}"); } return(new SupportModule_To()); }
internal static bool Download(string url, string destination) { if (string.IsNullOrEmpty(url)) { MelonLogger.Error($"url cannot be Null or Empty!"); return(false); } if (string.IsNullOrEmpty(destination)) { MelonLogger.Error($"destination cannot be Null or Empty!"); return(false); } if (File.Exists(destination)) { File.Delete(destination); } MelonLogger.Msg($"Downloading {url} to {destination}"); try { Core.webClient.DownloadFile(url, destination); } catch (Exception ex) { MelonLogger.Error(ex.ToString()); if (File.Exists(destination)) { File.Delete(destination); } return(false); } return(true); }
public override DynamicMethodDefinition CopyOriginal() { DynamicMethodDefinition method = Original.ToNewDynamicMethodDefinition(); method.Definition.Name += "_wrapper"; ILContext ilcontext = new ILContext(method.Definition); ILCursor ilcursor = new ILCursor(ilcontext); FieldReference tempfieldreference = null; if (ilcursor.TryGotoNext(x => x.MatchLdsfld(out tempfieldreference), x => x.MatchCall(UnhollowerSupport.IL2CPPType, "il2cpp_object_get_virtual_method"))) { // Virtual method: Replace the sequence // - ldarg.0 // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::Il2CppObjectBaseToPtr(class [UnhollowerBaseLib] UnhollowerBaseLib.Il2CppObjectBase) // - ldsfld native int SomeClass::NativeMethodInfoPtr_Etc // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::il2cpp_object_get_virtual_method(native int, native int) ilcursor.Index -= 2; ilcursor.RemoveRange(4); } else if (ilcursor.TryGotoNext(x => x.MatchLdsfld(UnhollowerSupport.MethodBaseToIl2CppFieldInfo(Original)))) { ilcursor.Remove(); } else { MelonLogger.Error("Harmony Patcher could not rewrite Il2Cpp Unhollowed Method. Expect a stack overflow."); return(method); } ilcursor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I8, copiedMethodInfoPointer.ToInt64()); ilcursor.Emit(Mono.Cecil.Cil.OpCodes.Conv_I); return(method); }
private void SetHighlightsFXReferences() { try { highlightsObject = HighlightsFX.prop_HighlightsFX_0; highlightMaterial = highlightsObject.field_Protected_Material_0; highlightMaterialName = highlightMaterial.name; highlightShader = highlightsObject.field_Protected_Shader_0; highlightShaderName = highlightShader.name; } catch (Exception e) { MelonLogger.Error(e.ToString()); } finally { if (ValidateHighlightsFXReferences()) { LogDebugMsg("Found HighlightsFX Object: " + highlightsObject.name); LogDebugMsg("HighlightsFX Material Name: " + highlightMaterialName); LogDebugMsg("HighlightsFX Shader Name: " + highlightShaderName); } else { MelonLogger.Error("Error finding HighlightsFX references!"); } } }
private static void Handler(object sender, FileSystemEventArgs e) { var path = Utils.GetResourcePath(e.FullPath); MelonLogger.Msg($"{e.Name} {e.ChangeType} {e.FullPath} {path}"); try { switch (e.ChangeType) { case WatcherChangeTypes.Deleted: Remove(path); break; case WatcherChangeTypes.Created: case WatcherChangeTypes.Changed: case WatcherChangeTypes.Renamed: AddOrUpdate(path); break; case WatcherChangeTypes.All: throw new NotSupportedException(); default: throw new ArgumentOutOfRangeException(); } } catch (Exception ex) { MelonLogger.Error(ex); } }
public override void OnApplicationStart() { var category = MelonPreferences.CreateCategory(SettingsCategory, "Lag Free Screenshots"); ourEnabled = category.CreateEntry(SettingEnableMod, true, "Enabled"); ourResolution = category.CreateEntry(SettingScreenshotResolution, PresetScreenshotSizes.Default, "Screenshot resolution override"); ourFormat = category.CreateEntry(SettingScreenshotFormat, "png", "Screenshot format"); ourJpegPercent = category.CreateEntry(SettingJpegPercent, 95, "JPEG quality (0-100)"); ourAutorotation = category.CreateEntry(SettingAutorotation, true, "Rotate picture to match camera"); ourMetadata = category.CreateEntry(SettingMetadata, false, "Save metadata in picture"); ourRecommendedMaxFb = category.CreateEntry(SettingRecommendedMaximumFb, 1024, "Try to keep framebuffer below (MB) by reducing MSAA"); ourCustomResolutionX = category.CreateEntry(SettingCustomResolutionX, 1920, "Custom screenshot resolution (X)"); ourCustomResolutionY = category.CreateEntry(SettingCustomResolutionY, 1080, "Custom screenshot resolution (Y)"); if (!MelonHandler.Mods.Any(it => it.Info.Name == "UI Expansion Kit" && it.Assembly.GetName().Version >= new Version(0, 2, 6))) { MelonLogger.Error("UI Expansion Kit is not found. Lag Free Screenshots will not work."); return; } HarmonyInstance.Patch( typeof(CameraTakePhotoEnumerator).GetMethod("MoveNext"), new HarmonyMethod(AccessTools.Method(typeof(LagFreeScreenshotsMod), nameof(MoveNextPatchAsyncReadback)))); AddEnumSettings(); }
private static void loadAssets() { using (var assetStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("LocalHeadLightMod.headlight")) { using (var tempStream = new MemoryStream((int)assetStream.Length)) { assetStream.CopyTo(tempStream); assetBundleIcons = AssetBundle.LoadFromMemory_Internal(tempStream.ToArray(), 0); assetBundleIcons.hideFlags |= HideFlags.DontUnloadUnusedAsset; } } if (assetBundleIcons != null) { try { AngleMinus = LoadTextureSprite("AngleMinus.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { AnglePlus = LoadTextureSprite("AnglePlus.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { BrightnessHigher = LoadTextureSprite("BrightnessHigher.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { BrightnessLower = LoadTextureSprite("BrightnessLower.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { ColorPicker = LoadTextureSprite("ColorPicker.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { flashLight = LoadTextureSprite("flashLight.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { LightOff = LoadTextureSprite("LightOff.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { LightOn = LoadTextureSprite("LightOn.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { SizeMinus = LoadTextureSprite("SizeMinus.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { SizePlus = LoadTextureSprite("SizePlus.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { Trans = LoadTextureSprite("Trans.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } try { Reset = LoadTextureSprite("Reset.png"); } catch { MelonLogger.Error("Failed to load image from asset bundle"); } } else { MelonLogger.Error("Bundle was null"); } }
public override void OnApplicationStart() { MelonPreferences.CreateCategory("ReloadAvatars", "ReloadAvatars Settings"); reloadAvatarPref = (MelonPreferences_Entry <bool>)MelonPreferences.CreateEntry("ReloadAvatars", "ReloadAvatar", true, "Enable/Disable Reload Avatar Button"); reloadAllAvatarsPref = (MelonPreferences_Entry <bool>)MelonPreferences.CreateEntry("ReloadAvatars", "ReloadAllAvatars", true, "Enable/Disable Reload All Avatars Button"); MethodInfo reloadAvatarMethod = typeof(VRCPlayer).GetMethods().First(mi => mi.Name.StartsWith("Method_Private_Void_Boolean_") && mi.Name.Length < 31 && mi.GetParameters().Any(pi => pi.IsOptional)); MethodInfo reloadAllAvatarsMethod = typeof(VRCPlayer).GetMethods().Where(mi => mi.Name.StartsWith("Method_Public_Void_Boolean_") && mi.Name.Length < 30 && mi.GetParameters().Any(pi => pi.IsOptional)).First(); // Both methods seem to do the same thing ExpansionKitApi.GetExpandedMenu(ExpandedMenu.UserQuickMenu).AddSimpleButton("Reload Avatar", new Action(() => { try { reloadAvatarMethod.Invoke(QuickMenu.prop_QuickMenu_0.field_Private_Player_0.field_Internal_VRCPlayer_0, new object[] { true }); } catch (Exception ex) { MelonLogger.Error("Error while reloading single avatar:\n" + ex.ToString()); } // Ignore }), new Action <GameObject>((gameObject) => { reloadAvatarButton = gameObject; reloadAvatarButton.SetActive(reloadAllAvatarsPref.Value); })); ExpansionKitApi.GetExpandedMenu(ExpandedMenu.QuickMenu).AddSimpleButton("Reload All Avatars", new Action(() => { try { reloadAllAvatarsMethod.Invoke(VRCPlayer.field_Internal_Static_VRCPlayer_0, new object[] { true }); } catch (Exception ex) { MelonLogger.Error("Error while reloading all avatars:\n" + ex.ToString()); } // Ignore }), new Action <GameObject>((gameObject) => { reloadAllAvatarsButton = gameObject; reloadAllAvatarsButton.SetActive(reloadAvatarPref.Value); })); MelonLogger.Msg("Initialized!"); }
internal override void PostRegister() { foreach (var towerModel in towerModels) { ModTowerHelper.FinalizeTowerModel(this, towerModel); } Game.instance.GetLocalizationManager().textTable[Id] = DisplayName; Game.instance.GetLocalizationManager().textTable[Id + "s"] = DisplayNamePlural; Game.instance.GetLocalizationManager().textTable[Id + " Description"] = Description; if (!DontAddToShop) { try { var index = GetTowerIndex(Game.instance.model.towerSet.ToList()); if (index >= 0) { var shopTowerDetailsModel = new ShopTowerDetailsModel(Id, index, 5, 5, 5, -1, 0, null); Game.instance.model.AddTowerDetails(shopTowerDetailsModel, index); } } catch (Exception) { MelonLogger.Error($"Failed to add ModTower {Name} to the shop"); throw; } } ModTowerSet?.towers.Add(this); }
private static void SolvePelvisPatch(IntPtr thisPtr, IntPtr methodPtr) { if (!IkTweaksSettings.FullBodyVrIk.Value || ourCachedSolver.Spine?.Pointer != thisPtr || !ourCachedSolver.Spine.vrcFbtSpineMode) { ourOriginalSolvePelvis(thisPtr, methodPtr); return; } // single lock modes modify these for some reason if (ourCachedSolver.Spine.vrcAllowHipDrift) { ourCachedSolver.Spine.IKPositionPelvis = ourStoredPelvisPos; ourCachedSolver.Spine.IKRotationPelvis = ourStoredPelvisRot; } else if (ourCachedSolver.Spine.vrcAllowHeadDrift) { ourCachedSolver.Spine.IKPositionHead = ourStoredHeadPos; ourCachedSolver.Spine.IKRotationHead = ourStoredHeadRot; } try { ourCustomSpineSolver.SolvePelvis(); } catch (Exception ex) { MelonLogger.Error($"Exception in IK spine solver: {ex}"); } }
private static void SetupUDN(UnityDisplayNode udn, ModDisplay modDisplay, Action <UnityDisplayNode> onComplete) { udn.name = modDisplay.Id + "(Clone)"; udn.RecalculateGenericRenderers(); try { modDisplay.ModifyDisplayNode(udn); } catch (Exception e) { MelonLogger.Error($"Failed to modify DisplayNode for {modDisplay.Name}"); MelonLogger.Error(e); } try { if (modDisplay.Scale < 1f || modDisplay.Scale > 1f) { udn.transform.GetChild(0).transform.localScale = new Vector3(modDisplay.Scale, modDisplay.Scale, modDisplay.Scale); } } catch (Exception e) { MelonLogger.Error($"Failed to change scale for {modDisplay.Name}"); MelonLogger.Error(e); } udn.RecalculateGenericRenderers(); onComplete.Invoke(udn); ResourceHandler.Prefabs[modDisplay.Id] = udn; }
public string GetLatestVersion() { string gitRes; try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.github.com/repos/Thatcooldevguy/SticksUItilityMod/releases/latest"); request.Method = "GET"; request.KeepAlive = true; request.ContentType = "application/x-www-form-urlencoded"; request.UserAgent = $"SticksUItilityMod/{version}"; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); using (StreamReader requestReader = new StreamReader(response.GetResponseStream())) { gitRes = requestReader.ReadToEnd(); } } catch (Exception e) { MelonLogger.Error("Failed to fetch latest plugin version info from github... Unable to update. Stack: \n" + e); return(null); } JObject obj = JsonConvert.DeserializeObject(gitRes) as JObject; return(latestVersion = obj.GetValue("tag_name")?.ToString()); }
internal static void Load() { TomletMain.RegisterMapper(WriteColor, ReadColor); FilePath = Path.Combine(Core.FolderPath, "Config.cfg"); General = CreateCat <cGeneral>(FilePath, nameof(General)); bool UseDefault = true; if (!string.IsNullOrEmpty(General.Theme) && !General.Theme.Equals("Default") && !General.Theme.Equals("Random")) { try { // To-Do: Sanatize themeName General.Theme = General.Theme .Replace("\\", "") .Replace("/", ""); ThemePath = Path.Combine(Core.ThemesFolderPath, General.Theme); if (Directory.Exists(ThemePath)) { UseDefault = false; } else { throw new DirectoryNotFoundException(ThemePath); } } catch (Exception ex) { MelonLogger.Error($"Failed to find Start Screen Theme: {ex}"); } } if (General.Theme.Equals("Random")) { ThemePath = UIUtils.RandomFolder(Core.ThemesFolderPath); UseDefault = false; } if (UseDefault) { General.Theme = "Default"; ThemePath = Path.Combine(Core.ThemesFolderPath, General.Theme); if (!Directory.Exists(ThemePath)) { Directory.CreateDirectory(ThemePath); } } MelonLogger.Msg($"Using Start Screen Theme: \"{General.Theme}\""); Background = CreateCat <cBackground>(nameof(Background), true); LogoImage = CreateCat <LogoImageSettings>(nameof(LogoImage), true); LoadingImage = CreateCat <LoadingImageSettings>(nameof(LoadingImage), true); VersionText = CreateCat <VersionTextSettings>(nameof(VersionText), true); ProgressText = CreateCat <ProgressTextSettings>(nameof(ProgressText), true); ProgressBar = CreateCat <cProgressBar>(nameof(ProgressBar), true); MelonPreferences.SaveCategory <cGeneral>(nameof(General), false); }
internal static void Log(object log, LogType logType = LogType.Normal) { if (logType == LogType.None) { MelonLogger.Msg($"[{prefix}] {log}"); return; } ConsoleColor color = ConsoleColor.White; switch (logType) { case LogType.Normal: color = ConsoleColor.Cyan; break; case LogType.Warning: color = ConsoleColor.Yellow; MelonLogger.Warning($"{log}"); return; case LogType.Error: color = ConsoleColor.Red; MelonLogger.Error($"{log}"); return; case LogType.Success: color = ConsoleColor.Blue; break; } MelonLogger.Msg(color, $"{log}"); }
internal static void Init() { if (disabled) { return; } try { MelonDebug.Msg("Initializing UIStyleValues"); UIStyleValues.Init(); MelonDebug.Msg("UIStyleValues Initialized"); uint graphicsDeviceType = SystemInfo.GetGraphicsDeviceType(); MelonDebug.Msg("Graphics Device Type: " + graphicsDeviceType); shouldCallWFLPAGT = NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonLoader.InternalUtils.UnityInformationHandler.EngineVersion.ToStringWithoutType(), new[] { "2020.2.7", "2020.3.0", "2021.1.0" }) && (graphicsDeviceType == /*DX11*/ 2 || graphicsDeviceType == /*DX12*/ 18) ? graphicsDeviceType : 0; } catch (Exception e) { MelonLogger.Error("Exception while init rendering: " + e); disabled = true; } }
public override void OnApplicationQuit() { foreach (object subscriber in melonLoaderEventSubscribers) { try { if (subscriber is Type subscriberAsType) { try { subscriberAsType.GetMethod("OnApplicationQuit", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)?.Invoke(null, null); } catch (ArgumentException) { throw new ArgumentException($"Type {subscriberAsType.Name} which is subscribed to MelonLoaderEvents via an attribute has an OnApplicationQuit that is not static."); } } else { (subscriber as MelonLoaderEvents).OnApplicationQuit(); } } catch (Exception ex) { MelonLogger.Error($"Exception during OnApplicationQuit:\n{ex}"); } } }
public static void GoToWorld(ApiWorld apiWorld, string tags, bool isInvite) { if (isInvite) { if (ModSettings.tryUseAdvancedInvitePopup && ModSettings.AdvancedInvites) { try { Delegates.GetAdvancedInvitesInviteDelegate(WorldDownloadManager.DownloadInfo.Notification); } catch (Exception e) { MelonLogger.Error("Unable to execute Advanced Invite's Invite Handler Func" + e); } } else { Networking.GoToRoom($"{apiWorld.id}:{tags}"); } //new PortalInternal().Method_Private_Void_String_String_PDM_0(apiWorld.id, tags); } else { Networking.GoToRoom($"{apiWorld.id}:{tags}"); } }
private bool CheckPlatformAttribute() { MelonPlatformAttribute platformAttribute = MelonUtils.PullAttributeFromAssembly <MelonPlatformAttribute>(Assembly); if ((platformAttribute == null) || (platformAttribute.Platforms == null) || (platformAttribute.Platforms.Length <= 0)) { return(true); } bool is_compatible = false; for (int i = 0; i < platformAttribute.Platforms.Length; i++) { MelonPlatformAttribute.CompatiblePlatforms platform = platformAttribute.Platforms[i]; if ((platform == MelonPlatformAttribute.CompatiblePlatforms.UNIVERSAL) || (MelonUtils.IsGame32Bit() && (platform == MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X86)) || (!MelonUtils.IsGame32Bit() && (platform == MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64))) { is_compatible = true; break; } } if (!is_compatible) { MelonLogger.Error($"Incompatible Platform for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}"); return(false); } return(true); }
private static void Update(CancellationToken token) { while (!token.IsCancellationRequested) { try { if (EyeEnabled) { UpdateEye(); } if (FaceEnabled) { UpdateMouth(); } } catch (Exception e) { if (e.InnerException.GetType() != typeof(ThreadAbortException)) { MelonLogger.Error("Threading error occured in SRanipalTrack.Update: " + e + ": " + e.InnerException); } } Thread.Sleep(10); } }
internal static bool PatchMethods() { try { // Left room MethodInfo onLeftRoomMethod = typeof(NetworkManager).GetMethod( nameof(NetworkManager.OnLeftRoom), BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, Type.EmptyTypes, null); origOnLeftRoom = Patch <OnLeftRoom>(onLeftRoomMethod, GetDetour(nameof(OnLeftRoomPatch))); } catch (Exception e) { MelonLogger.Error("Failed to patch OnLeftRoom\n" + e.Message); return(false); } try { // Faded to and joined and initialized room MethodInfo fadeMethod = typeof(VRCUiManager).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).First( m => m.Name.StartsWith("Method_Public_Void_String_Single_Action_") && m.Name.IndexOf("PDM", StringComparison.OrdinalIgnoreCase) == -1 && m.GetParameters().Length == 3); origFadeTo = Patch <FadeTo>(fadeMethod, GetDetour(nameof(FadeToPatch))); } catch (Exception e) { MelonLogger.Error("Failed to patch FadeTo\n" + e.Message); return(false); } if (Utilities.IsInVR) { try { // Fixes spinning issue // TL;DR Prevents the tracking manager from applying rotational force MethodInfo applyPlayerMotionMethod = typeof(VRCTrackingManager).GetMethods(BindingFlags.Public | BindingFlags.Static) .Where( m => m.Name.StartsWith("Method_Public_Static_Void_Vector3_Quaternion") && !m.Name.Contains("_PDM_")).First( m => XrefScanner.UsedBy(m).Any( xrefInstance => xrefInstance.Type == XrefType.Method && xrefInstance.TryResolve()?.ReflectedType ?.Equals(typeof(VRC_StationInternal)) == true)); origApplyPlayerMotion = Patch <ApplyPlayerMotion>(applyPlayerMotionMethod, GetDetour(nameof(ApplyPlayerMotionPatch))); } catch (Exception e) { MelonLogger.Error("Failed to patch ApplyPlayerMotion\n" + e.Message); return(false); } } return(true); }
public static unsafe void ApplyPatches() { try { // PDM's are scary:( MethodInfo avatarChangedMethod = typeof(VRCAvatarManager).GetMethods().FirstOrDefault(method => method.Name.StartsWith("Method_Private_Void_ApiAvatar_GameObject_Action_1_Boolean_")); IntPtr original = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(avatarChangedMethod).GetValue(null); MelonUtils.NativeHookAttach((IntPtr)(&original), typeof(ImmersiveTouch).GetMethod(nameof(ImmersiveTouch.OnAvatarChanged), BindingFlags.Static | BindingFlags.Public) !.MethodHandle.GetFunctionPointer()); avatarChangedDelegate = Marshal.GetDelegateForFunctionPointer <AvatarChangedDelegate>(original); } catch (Exception e) { MelonLogger.Error($"Failed to patch: OnAvatarChanged\n{e}"); } try { IntPtr original = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(DynamicBone).GetMethod(nameof(DynamicBone.Method_Private_Void_Boolean_0))).GetValue(null); MelonUtils.NativeHookAttach((IntPtr)(&original), typeof(ImmersiveTouch).GetMethod(nameof(ImmersiveTouch.OnUpdateParticles), BindingFlags.Static | BindingFlags.Public) !.MethodHandle.GetFunctionPointer()); updateParticlesDelegate = Marshal.GetDelegateForFunctionPointer <UpdateParticlesDelegate>(original); } catch (Exception e) { MelonLogger.Error($"Failed to patch: OnUpdateParticles\n{e}"); } try { IntPtr original = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(DynamicBoneCollider).GetMethod(nameof(DynamicBoneCollider.Method_Public_Void_byref_Vector3_Single_0))).GetValue(null); MelonUtils.NativeHookAttach((IntPtr)(&original), typeof(ImmersiveTouch).GetMethod(nameof(ImmersiveTouch.OnCollide), BindingFlags.Static | BindingFlags.Public) !.MethodHandle.GetFunctionPointer()); collideDelegate = Marshal.GetDelegateForFunctionPointer <CollideDelegate>(original); } catch (Exception e) { MelonLogger.Error($"Failed to patch: OnCollide\n{e}"); } }
private static unsafe bool ApplyUser32SetTimerPatch() { IntPtr original = PEUtils.GetExportedFunctionPointerForModule("USER32.dll", "SetTimer"); MelonLogger.Msg($"User32::SetTimer original: 0x{(long)original:X}"); if (original == IntPtr.Zero) { MelonLogger.Error("Failed to find USER32.dll::SetTimer"); return(false); } // We get a native function pointer to User32SetTimerDetour from our current class //IntPtr detourPtr = typeof(Core).GetMethod("User32SetTimerDetour", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer(); IntPtr detourPtr = Marshal.GetFunctionPointerForDelegate((User32SetTimerDelegate)User32SetTimerDetour); if (detourPtr == IntPtr.Zero) { MelonLogger.Error("Failed to find User32SetTimerDetour"); return(false); } // And we patch SetTimer to replace it by our hook MelonLogger.Msg($"Applying USER32.dll::SetTimer Hook at 0x{original.ToInt64():X}"); MelonUtils.NativeHookAttach((IntPtr)(&original), detourPtr); MelonLogger.Msg($"Creating delegate for original USER32.dll::SetTimer (0x{original.ToInt64():X})"); user32SetTimerOriginal = (User32SetTimerDelegate)Marshal.GetDelegateForFunctionPointer(original, typeof(User32SetTimerDelegate)); MelonLogger.Msg("Applied USER32.dll::SetTimer patch"); return(true); }
private static IEnumerator FetchAPIUsers() { while (true) { yield return(new WaitForSeconds(1f)); while (UsersToFetch.Count > 0) { var id = UsersToFetch.Dequeue(); APIUser.FetchUser(id, new Action <APIUser>(user => { CachedApiUsers.Add(user); if (_reloadAvatar.Value) { var player = GetPlayerByUserId(id); _reloadAvatarMethod.Invoke(player._vrcplayer, new object[] { true }); } }), new Action <string>(error => { MelonLogger.Error($"Could not fetch APIUser object of {id}"); })); yield return(new WaitForSeconds(Random.Next(2, 5))); } } }