Пример #1
0
        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);
        }
        private void CreateGameObjects()
        {
            MelonLogger.Msg("Finding original GameObjects");
            var UIRoot                     = GameObject.Find("UserInterface/MenuContent/Popups/LoadingPopup");
            var InfoPanel                  = GameObject.Find("UserInterface/MenuContent/Popups/LoadingPopup/3DElements/LoadingInfoPanel");
            var SkyCube                    = GameObject.Find("/UserInterface/MenuContent/Popups/LoadingPopup/3DElements/LoadingBackground_TealGradient/SkyCube_Baked");
            var bubbles                    = GameObject.Find("/UserInterface/MenuContent/Popups/LoadingPopup/3DElements/LoadingBackground_TealGradient/_FX_ParticleBubbles");
            var loginBubbles               = GameObject.Find("/UserInterface/LoadingBackground_TealGradient_Music/_FX_ParticleBubbles");
            var StartScreen                = GameObject.Find("/UserInterface/LoadingBackground_TealGradient_Music/");
            var originalStartScreenAudio   = GameObject.Find("/UserInterface/LoadingBackground_TealGradient_Music/LoadingSound");
            var originalStartScreenSkyCube = GameObject.Find("/UserInterface/LoadingBackground_TealGradient_Music/SkyCube_Baked");
            var originalLoadingAudio       = GameObject.Find("/UserInterface/MenuContent/Popups/LoadingPopup/LoadingSound");

            MelonLogger.Msg("Creating new GameObjects");
            loadScreenPrefab = CreateGameObject(loadScreenPrefab, new Vector3(400, 400, 400), "UserInterface/MenuContent/Popups/", "LoadingPopup");
            loginPrefab      = CreateGameObject(loginPrefab, new Vector3(0.5f, 0.5f, 0.5f), "UserInterface/", "LoadingBackground_TealGradient_Music");
            // newCube = CreateGameObject(newCube, new Vector3(0.5f, 0.5f, 0.5f), "UserInterface/", "LoadingBackground_TealGradient_Music");

            MelonLogger.Msg("Disabling original GameObjects");

            // Disable original objects from loading screen
            SkyCube.active = false;
            bubbles.active = false;
            originalLoadingAudio.active = false;

            // Disable original objects from login screen
            originalStartScreenAudio.active   = false;
            originalStartScreenSkyCube.active = false;
            loginBubbles.active = false;

            // Apply any preferences (yes ik this is lazy)
            OnPreferencesSaved();
        }
Пример #3
0
        public static void DumpTypesUsedBy(this MethodBase methodBase)
        {
            if (methodBase == null)
            {
                return;
            }

            MelonLogger.Msg("Types used by method: " + methodBase.Name);
            HashSet <string> usedTypes = new HashSet <string>();

            foreach (XrefInstance instance in XrefScanner.UsedBy(methodBase))
            {
                if (instance.Type == XrefType.Method)
                {
                    var resolved = instance.TryResolve();
                    if (resolved == null)
                    {
                        continue;
                    }
                    if (usedTypes.Contains(resolved.DeclaringType?.ToString()))
                    {
                        continue;
                    }
                    usedTypes.Add(resolved.DeclaringType?.ToString());
                    MelonLogger.Msg(resolved.DeclaringType?.ToString());
                }
            }
        }
Пример #4
0
        private static void DumpScan(IEnumerable <XrefInstance> scan)
        {
            foreach (XrefInstance instance in scan)
            {
                if (instance.Type == XrefType.Global)
                {
                    MelonLogger.Msg(instance.Type);
                    MelonLogger.Msg(instance.ReadAsObject().ToString());
                    MelonLogger.Msg("");
                    continue;
                }

                MethodBase resolvedMethod = instance.TryResolve();
                if (instance.Type == XrefType.Method)
                {
                    if (resolvedMethod == null)
                    {
                        MelonLogger.Msg("null");
                        MelonLogger.Msg("null");
                    }
                    else
                    {
                        MelonLogger.Msg(resolvedMethod.Name);
                        MelonLogger.Msg(resolvedMethod.DeclaringType.FullName);
                    }

                    MelonLogger.Msg("");
                }
            }
        }
Пример #5
0
        private static void WhitelistUser(APIUser user)
        {
            if (user == null)
            {
                return;
            }

            if (UserPermissionHandler.IsWhitelisted(user.id))
            {
                UserPermissionHandler.RemoveFromWhitelist(user.id);
                MelonLogger.Msg($"{user.displayName} removed from whitelist");
                Utilities.QueueHudMessage($"{user.displayName} removed from whitelist");
            }
            else
            {
                if (UserPermissionHandler.IsBlacklisted(user.id))
                {
                    UserPermissionHandler.RemoveFromBlacklist(user.id);
                }
                UserPermissionHandler.AddToWhitelist(user);
                MelonLogger.Msg($"{user.displayName} added to whitelist");
                Utilities.QueueHudMessage($"{user.displayName} added to whitelist");
            }

            UserPermissionHandler.SaveSettings();
        }
Пример #6
0
        // 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);
        }
Пример #7
0
        public override void OnApplicationStart()
        {
            AskToPortalSettings.RegisterSettings();
            if (MelonHandler.Mods.Any(mod => mod.Info.Name == "Portal Confirmation"))
            {
                MelonLogger.Warning("Use of Portal Confirmation by 404 was detected! AskToPortal is NOT Portal Confirmation. AskToPortal is simply a replacement for Portal Confirmation as 404 was BANNED from the VRChat Modding Group. If you wish to use this mod please DELETE Portal Confirmation.");
            }
            else
            {
                portalInfo = typeof(VRCFlowManager).GetMethods()
                             .Where(mb => mb.Name.StartsWith("Method_Public_Void_String_WorldTransitionInfo_")).First().GetParameters()[1].ParameterType;
                portalInfoEnum = portalInfo.GetNestedTypes().First();
                enterWorld     = typeof(VRCFlowManager).GetMethods()
                                 .Where(mb => mb.Name.StartsWith($"Method_Public_Void_String_String_{portalInfo.Name}_Action_1_String_Boolean_") && !mb.Name.Contains("PDM") && CheckMethod(mb, "EnterWorld called with an invalid world id.")).First();
                popupV2 = typeof(VRCUiPopupManager).GetMethods()
                          .Where(mb => mb.Name.StartsWith("Method_Public_Void_String_String_String_Action_String_Action_Action_1_VRCUiPopup_") && !mb.Name.Contains("PDM") && CheckMethod(mb, "UserInterface/MenuContent/Popups/StandardPopupV2")).First();
                popupV2Small = typeof(VRCUiPopupManager).GetMethods()
                               .Where(mb => mb.Name.StartsWith("Method_Public_Void_String_String_String_Action_Action_1_VRCUiPopup_") && !mb.Name.Contains("PDM") && CheckMethod(mb, "UserInterface/MenuContent/Popups/StandardPopupV2")).First();
                closePopup = typeof(VRCUiPopupManager).GetMethods()
                             .Where(mb => mb.Name.StartsWith("Method_Public_Void_") && mb.Name.Length <= 21 && !mb.Name.Contains("PDM") && CheckMethod(mb, "POPUP")).First();
                enterPortal = typeof(PortalInternal).GetMethods()
                              .Where(mb => mb.Name.StartsWith("Method_Public_Void_") && mb.Name.Length <= 21 && CheckUsed(mb, "OnTriggerEnter")).First();
                closeMenu = typeof(VRCUiManager).GetMethods()
                            .Where(mb => mb.Name.StartsWith("Method_Public_Void_Boolean_") && CheckUsed(mb, "ShowAddMessagePopup")).First();


                Harmony.Patch(enterPortal, prefix: new HarmonyMethod(typeof(AskToPortalMod).GetMethod("OnPortalEnter", BindingFlags.Static | BindingFlags.Public)));
                Harmony.Patch(typeof(PortalInternal).GetMethod("ConfigurePortal"), prefix: new HarmonyMethod(typeof(AskToPortalMod).GetMethod("OnPortalDropped", BindingFlags.Static | BindingFlags.Public)));
                Harmony.Patch(typeof(PortalInternal).GetMethod("OnDestroy"), prefix: new HarmonyMethod(typeof(AskToPortalMod).GetMethod("OnPortalDestroyed", BindingFlags.Static | BindingFlags.Public)));

                MelonLogger.Msg("Initialized!");
            }
        }
Пример #8
0
        public static void ExportDefaultStyle(string baseDir, StyleEngine styleEngine)
        {
            var textAssetType = Il2CppType.Of <TextAsset>();
            var spriteType    = Il2CppType.Of <Sprite>();
            var audioClipType = Il2CppType.Of <AudioClip>();

            MelonLogger.Msg($"Exporting default VRC skin to {baseDir}");
            foreach (var keyValuePair in styleEngine.field_Private_Dictionary_2_Tuple_2_String_Type_Object_0)
            {
                var basePath = Path.Combine(baseDir, keyValuePair.Key.Item1);

                if (keyValuePair.Key.Item2 == textAssetType)
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(basePath) !);
                    var textAsset = keyValuePair.Value.Cast <TextAsset>();
                    File.WriteAllBytes(basePath + ".txt", textAsset.bytes);
                }
                else if (keyValuePair.Key.Item2 == spriteType)
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(basePath) !);
                    var sprite = keyValuePair.Value.Cast <Sprite>();
                    SpriteSnipperUtil.SaveSpriteAsPngWithMetadata(sprite, basePath + ".png");
                }
                else if (keyValuePair.Key.Item2 == audioClipType)
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(basePath) !);
                    var audioClip = keyValuePair.Value.Cast <AudioClip>();
                    WriteWaveFile(basePath + ".wav", audioClip);
                }
            }
            MelonLogger.Msg($"Export finished");
        }
Пример #9
0
        /// <summary> Logs a GameObject and all of its components to the console </summary>
        /// <param name="gameObject">The GameObject to log</param>
        /// <param name="max">Maximum amount of times to traverse down children</param>
        /// <param name="n_depth">This parameter should be ignored</param>
        public static void LogGameObject(GameObject gameObject, int max = -1, int?n_depth = null)
        {
            int depth = n_depth ?? 0;

            if (max != -1 && depth > max)
            {
                return;
            }

            MelonLogger.Msg(ConsoleColor.Green, "".PadLeft(depth * 4, ' ') + gameObject.name);

            Component[] components = gameObject.GetComponents <Component>();
            for (int i = 0; i < components.Length; i++)
            {
                MelonLogger.Msg(
                    ConsoleColor.Cyan,
                    "".PadLeft((depth + 1) * 4, ' ') +
                    ((gameObject.name.Length + 2 < components[i].ToString().Length) ?
                     components[i].ToString().Substring(
                         gameObject.name.Length + 2,
                         components[i].ToString().Length - gameObject.name.Length - 3
                         ) : components[i].ToString())
                    );
            }

            for (int i = 0; i < gameObject.transform.childCount; i++)
            {
                LogGameObject(gameObject.transform.GetChild(i).gameObject, max, depth + 1);
            }
        }
Пример #10
0
        internal static async Task <Variant> ValidateToken(string token)
        {
            Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("OAuth", token);
            Client.DefaultRequestHeaders.Add("Client-ID", ClientID);
            var response = await Client.GetAsync("https://id.twitch.tv/oauth2/validate");

            var responseContent = await response.Content.ReadAsStringAsync();

            //MelonLogger.Msg("Validation response: " + responseContent);
            var responseJson = JSON.Load(responseContent);

            if (response.IsSuccessStatusCode)
            {
                MelonLogger.Msg("That's a success! Setting variables.");
                _twitchID    = responseJson["user_id"];
                _twitchToken = token;
                TwitchAuthed = true;
                int expiresIn = responseJson["expires_in"];
                if (expiresIn < 24 * 60 * 60) // token expires within 24 hours
                {
                    PopupsToDisplay.Enqueue(new MyPopup(PopupType.Yesno,
                                                        "Your saved Twitch Authentication is due to expire within the next 24 hours. Do you want to reauthenticate now or later?",
                                                        "Twitch Integration", "Now", "Later", StreamingSetupMainMenuHook.ShowTwitchAuthPopup));
                }
            }
            else
            {
                MelonLogger.Warning("Preexisting token has expired!");
                TwitchAuthFailReason = "a previous authentication has expired.";
            }

            return(responseJson);
        }
Пример #11
0
        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);
        }
Пример #12
0
 public override async void OnApplicationStart()
 {
     base.OnApplicationStart();
     MelonLogger.Msg("Starting up Twitch Integration...");
     MelonLogger.Msg("Checking for existing authentication...");
     Directory.CreateDirectory(Path.GetDirectoryName(TwitchauthPath) ?? throw new InvalidOperationException());
     if (!File.Exists(TwitchauthPath))
     {
         TwitchAuthFailReason = " you started this mod for the first time.";
     }
     else
     {
         var content = File.Exists(TwitchauthPath) ? File.ReadAllText(TwitchauthPath) : "";
         content = content.Trim();
         //MelonLogger.Msg("Content was: \"" + content + "\"");
         if (!content.Equals(""))
         {
             await ValidateToken(content);
         }
         else
         {
             TwitchAuthFailReason = "the authentication file was empty. Did you do that?";
         }
     }
 }
Пример #13
0
        // ReSharper disable once InconsistentNaming
        public static bool PreResLoad(ref UnityEngine.Object __result, string path)
        {
            MelonLogger.Msg(path);

            const string templateObjectPath = "Game/Portrait/Woman/Body/101";

            if (!path.IsPortrait())
            {
                return(true);
            }

            var pp = path.ToPhysicalPath();

            if (!pp.Exist())
            {
                return(true);
            }

            // Can't use base method directly because of the missing of reverse path.
            // FIXME: There is no guarantee `Load<T>` won't use `Load` internally
            var orig = g.res.Load <GameObject>(templateObjectPath);

            var template = UnityEngine.Object.Instantiate(orig).Cast <GameObject>();
            var renderer = template.GetComponentInChildren <SpriteRenderer>();

            renderer.LoadCustomSprite(pp);

            __result = template;

            return(false);
        }
Пример #14
0
            public Object Get()
            {
                if (Interlocked.CompareExchange(ref expired, FALSE, TRUE) == TRUE)
                {
                    cacheLock.EnterWriteLock();
                    try
                    {
                        if (go != null)
                        {
                            MelonLogger.Msg("Update expired");
                        }
                        Update();
                        return(go);
                    }
                    finally
                    {
                        cacheLock.ExitWriteLock();
                    }
                }

                cacheLock.EnterReadLock();
                try
                {
                    return(go);
                }
                finally
                {
                    cacheLock.ExitReadLock();
                }
            }
Пример #15
0
        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}");
        }
Пример #16
0
 private static void Postfix(SongSelect __instance)
 {
     FilterPanel.Initialize();
     ScoreHistory.LoadHistory(PlatformChooser.I.GetLeaderboardID());
     MelonCoroutines.Start(SongBrowser.UpdateLastSongCount());
     MelonLogger.Msg("Updating song count");
 }
Пример #17
0
 public override void OnApplicationStart()
 {
     MelonLogger.Msg("Paragon Sentry In Shop mod loaded");
     Directory.CreateDirectory($"{dir}");
     if (File.Exists(config))
     {
         MelonLogger.Msg("Reading config file");
         using (StreamReader sr = File.OpenText(config))
         {
             string s = "";
             while ((s = sr.ReadLine()) != null)
             {
                 SentryParagonCost = int.Parse(s.Substring(s.IndexOf(char.Parse("=")) + 1));
             }
         }
         MelonLogger.Msg("Done reading");
     }
     else
     {
         MelonLogger.Msg("Creating config file");
         using (StreamWriter sw = File.CreateText(config))
         {
             sw.WriteLine("ParagonSentryCost=5000");
         }
         MelonLogger.Msg("Done Creating");
     }
 }
        private static void HandleErrors(Error eyeError, Error faceError)
        {
            if (eyeError.IsRealError())
            {
                // Msg instead of Warning under the assumption most people will be using only lip tracking
                MelonLogger.Msg($"Eye Tracking will be unavailable for this session. ({eyeError})");
            }
            else if (eyeError == Error.WORK)
            {
                MainMod.AppendEyeParams();
                EyeEnabled = true;
                MelonLogger.Msg("SRanipal Eye Initialized!");
            }

            if (faceError.IsRealError())
            {
                MelonLogger.Warning($"Lip Tracking will be unavailable for this session. ({faceError})");
            }
            else if (faceError == (Error)1051)
            {
                while (faceError == (Error)1051)
                {
                    faceError = SRanipal_API.Initial(SRanipal_Lip_v2.ANIPAL_TYPE_LIP_V2, IntPtr.Zero);
                }
            }
            if (faceError == Error.WORK)
            {
                MainMod.AppendLipParams();
                FaceEnabled = true;
                MelonLogger.Msg("SRanipal Lip Initialized!");
            }
        }
Пример #19
0
        private static void GetNewInstancePrefix(ref string tags)
        {
            MelonLogger.Msg("Mono Stacktrace:\n" + new StackTrace().ToString());
            MelonLogger.Msg("Il2Cpp Stacktrace:\n" + new Il2CppSystem.Diagnostics.StackTrace().ToString());
            ServerDef targetServer;

            if (new StackTrace().GetFrame(2).GetMethod().DeclaringType == typeof(PopupRoomInstance))
            {
                targetServer = serverList[serverDropdown.value];
            }
            else
            {
                targetServer = ss.AppSettings.UseNameServer ? ServerDef.CloudServer("", ss.AppSettings.FixedRegion, ss.AppSettings.AppIdRealtime, ss.AppSettings.AppVersion) : ServerDef.DedicatedServer("", ss.AppSettings.Server, ss.AppSettings.Port);
            }

            if (targetServer != defaultServer)
            {
                if (targetServer.cloud)
                {
                    tags += "~cloud(" + targetServer.region + "," + targetServer.appId + "," + targetServer.appVersion + ")";
                }
                else
                {
                    tags += "~server(" + targetServer.address + "," + targetServer.port + ")";
                }
            }

            MelonLogger.Msg("generated instance id: " + tags);
        }
Пример #20
0
        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!");
        }
Пример #21
0
        public static unsafe void SetupHooking()
        {
            try
            {
                var intPtr = (IntPtr)typeof(VRCAvatarManager.MulticastDelegateNPublicSealedVoGaVRBoUnique)
                             .GetField(
                    "NativeMethodInfoPtr_Invoke_Public_Virtual_New_Void_GameObject_VRC_AvatarDescriptor_Boolean_0",
                    BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
                Imports.Hook(intPtr,
                             new Action <IntPtr, IntPtr, IntPtr, bool>(OnAvatarInstantiated).Method.MethodHandle
                             .GetFunctionPointer());
                _onAvatarInstantiatedDelegate =
                    Marshal.GetDelegateForFunctionPointer <AvatarInstantiatedDelegate>(*(IntPtr *)(void *)intPtr);

                intPtr = (IntPtr)typeof(VRCAvatarManager)
                         .GetField(
                    "NativeMethodInfoPtr_Method_Public_Boolean_ApiAvatar_String_Single_MulticastDelegateNPublicSealedVoGaVRBoUnique_0",
                    BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
                Imports.Hook(intPtr,
                             new Action <IntPtr, IntPtr, string, float, IntPtr>(OnAvatarSwitch).Method.MethodHandle
                             .GetFunctionPointer());
                _avatarSwitch = Marshal.GetDelegateForFunctionPointer <OnAvatarSwitchDelegate>(*(IntPtr *)(void *)intPtr);
            }
            catch (Exception ex)
            {
                MelonLogger.Msg("Patch Failed " + ex);
            }
        }
Пример #22
0
        public static void UiInit()
        {
            MelonLogger.Msg("Loading UI...");

            menu = new SubMenu(QuickMenu.prop_QuickMenu_0.gameObject, "InstanceHistoryModMenu");

            openButton = new SingleButton(QuickMenu.prop_QuickMenu_0.transform.FindChild("ShortcutMenu").gameObject, new Vector3(Config.openButtonX.Value, Config.openButtonY.Value), "Instance History", new Action(OpenInstanceHistoryMenu), "Open instance history", "InstancenHistoryButton");
            openButton.gameObject.SetActive(!(InstanceHistoryMod.HasUIX && Config.useUIX.Value));
            Config.openButtonX.OnValueChanged += OnPositionChange;
            Config.openButtonY.OnValueChanged += OnPositionChange;

            if (InstanceHistoryMod.HasUIX)
            {
                typeof(UIXManager).GetMethod("AddOpenButtonToUIX").Invoke(null, null);
            }

            pageUp     = new SingleButton(menu.gameObject, GameObject.Find("UserInterface/QuickMenu/EmojiMenu/PageUp"), new Vector3(4, 0), "", new Action(() => InstanceIndex -= 9), $"Go up a page", "UpPageButton");
            pageDown   = new SingleButton(menu.gameObject, GameObject.Find("UserInterface/QuickMenu/EmojiMenu/PageDown"), new Vector3(4, 2), "", new Action(() => InstanceIndex += 9), $"Go down a page", "DownPageButton");
            backButton = new SingleButton(menu.gameObject, new Vector3(4, 0), "Back", new Action(() => UiManager.OpenSubMenu("UserInterface/QuickMenu/ShortcutMenu")), "Press to go back to the Shortcut Menu", "BackButton", textColor: Color.yellow);
            backButton.gameObject.SetActive(false);
            pageNumLabel = new Label(menu.gameObject, new Vector3(4, 1), $"Page: 1 of {LastPageNum}", "PageNumberLabel");

            for (int i = 0; i < 9; i++)
            {
                buttons[i] = new SingleButton(menu.gameObject, new Vector3((i % 3) + 1, Mathf.Floor(i / 3)), "Placeholder text", null, "Placeholder text", $"World Button {i + 1}", resize: true);
            }

            MelonLogger.Msg("UI Loaded!");
        }
Пример #23
0
        /// <summary>
        /// Prints relevant info about this node to the console including:
        /// <br/>
        ///
        /// </summary>
        /// <param name="node"></param>
        public static void PrintInfo(this UnityDisplayNode node)
        {
            var start = $"-------------Information about UnityDisplayNode {node.name}-------------";

            MelonLogger.Msg(start);

            MelonLogger.Msg("Generic Renderers:");
            for (var i = 0; i < node.genericRenderers.Count; i++)
            {
                var renderer = node.genericRenderers[i];
                MelonLogger.Msg($"   {i}. {renderer.name} ({renderer.GetIl2CppType().Name})");
            }

            MelonLogger.Msg("");

            MelonLogger.Msg("Generic Render Layers:");
            for (var i = 0; i < node.genericRendererLayers.Count; i++)
            {
                var layer = node.genericRendererLayers[i];
                MelonLogger.Msg($"   {i}. {layer}");
            }

            MelonLogger.Msg("");

            MelonLogger.Msg("Component Hierarchy:");
            node.gameObject.RecursivelyLog();

            MelonLogger.Msg(new string('-', start.Length));
        }
Пример #24
0
        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);
            }
        }
Пример #25
0
        public override void VRChat_OnUiManagerInit()
        {
            ClassInjector.RegisterTypeInIl2Cpp <EnableDisableListener>();
            Config.RegisterSettings();

            // Initialize Constants util
            Constants.UIInit();

            LoadAssetBundle();

            // Initialize UIManager
            UIManager.Init();

            // Initialize submenu for the list
            MenuManager.CreateMainSubMenu();

            // TODO: Add opacity options, maybe color too, (maybe even for each stage of ping and fps??)

            MenuManager.AddMenuListeners();
            MenuManager.CreateSubMenus();
            PlayerEntry.Patch(Harmony);
            EntryManager.AddGeneralInfoEntries();
            MenuManager.CreateGeneralInfoSubMenus();
            MenuManager.AdjustSubMenus();

            // Initialize on leave and join events
            NetworkHooks.NetworkInit();
            NetworkHooks.OnPlayerJoin  += new Action <Player>((player) => OnPlayerJoin(player));
            NetworkHooks.OnPlayerLeave += new Action <Player>((player) => OnPlayerLeave(player));

            MelonLogger.Msg("Initialized!");
        }
Пример #26
0
 public virtual void Deactivate()
 {
     if (!defaultParams.active)
     {
         MelonLogger.Msg(type.ToString() + " cancelled");
         return;
     }
     MelonLogger.Msg(type.ToString() + " deactivated");
     defaultParams.active = false;
     ModStatusHandler.RemoveStatusDisplays(type, ModStatusHandler.UpdateType.Ingame);
     ModStatusHandler.UpdateStatusDisplays(type, defaultParams.name, defaultParams.cooldown.ToString(), defaultParams.user, defaultParams.color, ModStatusHandler.UpdateType.ScoreOverlay);
     ModifierManager.ProcessQueue();
     MelonCoroutines.Start(CooldownTimer(defaultParams.cooldown));
     if (ModifierManager.nukeActive)
     {
         foreach (Modifier mod in ModifierManager.activeModifiers)
         {
             if (mod.defaultParams.active)
             {
                 return;
             }
         }
         ModifierManager.nukeActive = false;
     }
 }
Пример #27
0
        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);
        }
Пример #28
0
        public AvatarModule() : base(ExpandedMenu.AvatarMenu, FavCatMod.Database.AvatarFavorites, GetListsParent(), false, false)
        {
            myCurrentAnnoyingMessage = CanPerformAdditiveActions ? "WillBeObsolete" : (CanShowExistingLists ? "CantAddWithCanny" : "NoFavorites");

            MelonLogger.Msg("Adding button to UI - Looking up for Change Button");
            var foundAvatarPage = Resources.FindObjectsOfTypeAll <PageAvatar>()?.FirstOrDefault(p => p.transform.Find("Change Button") != null);

            if (foundAvatarPage == null)
            {
                throw new ApplicationException("No avatar page, can't initialize extended favorites");
            }

            myPageAvatar = foundAvatarPage;

            ExpansionKitApi.GetExpandedMenu(ExpandedMenu.UserDetailsMenu).AddSimpleButton("Search known public avatars", DoSearchKnownAvatars);

            var expandEnforcer = new GameObject(ExpandEnforcerGameObjectName, new[] { Il2CppType.Of <RectTransform>(), Il2CppType.Of <LayoutElement>() });

            expandEnforcer.transform.SetParent(GetListsParent(), false);
            var layoutElement = expandEnforcer.GetComponent <LayoutElement>();

            layoutElement.minWidth  = 1534;
            layoutElement.minHeight = 0;

            myPageAvatar.gameObject.AddComponent <EnableDisableListener>().OnEnabled += () =>
            {
                if (FavCatSettings.DontShowAnnoyingMessage == myCurrentAnnoyingMessage || myHasShownAnnoyingMessageThisRun)
                {
                    return;
                }
                ShowAnnoyingMessage();
            };

            myInitialised = true;
        }
Пример #29
0
        internal static void XrefDump(this MethodBase methodBase)
        {
            MelonLogger.Msg("Scanning Method: " + methodBase.Name);
            foreach (XrefInstance instance in XrefScanner.XrefScan(methodBase))
            {
                switch (instance.Type)
                {
                case XrefType.Global:
                    MelonLogger.Msg($"\tGlobal Instance: {instance.ReadAsObject()?.ToString()}");
                    break;

                case XrefType.Method:
                    var resolved = instance.TryResolve();
                    if (resolved == null)
                    {
                        MelonLogger.Msg("\tNull Method Instance");
                    }
                    else
                    {
                        MelonLogger.Msg($"\tMethod Instance: {resolved.DeclaringType?.Name} {resolved.Name}");
                    }
                    break;

                default:
                    break;
                }
            }
            MelonLogger.Msg("");
        }
Пример #30
0
        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());
        }