public static void ImageSnifferPatch(IntPtr instancePtr, IntPtr asyncOperationPtr)
        {
            ourOriginalOnDone(instancePtr, asyncOperationPtr);

            try
            {
                if (!FavCatSettings.UseLocalImageCache || FavCatMod.Database == null)
                {
                    return;
                }

                var closure = Activator.CreateInstance(ImageDownloaderClosureType, instancePtr);
                var url     = (string)ImageUrlField.Invoke(NestedClosureField?.Invoke(closure, EmptyObjectArray) ?? closure, EmptyObjectArray);

                var webRequest = (UnityWebRequest)WebRequestField.Invoke(closure, EmptyObjectArray);
                if (webRequest.isNetworkError || webRequest.isHttpError)
                {
                    return;
                }

                if (webRequest.downloadedBytes > 1024 * 1024)
                {
                    if (Imports.IsDebugMode())
                    {
                        MelonLogger.Log($"Ignored downloaded image from {url} because it's bigger than 1 MB");
                    }
                    return; // ignore images over 1 megabyte, 256-pixel previews should not be that big
                }

                FavCatMod.Database.ImageHandler.StoreImageAsync(url, webRequest.downloadHandler.data).NoAwait();
            }
            catch (Exception ex)
            {
                MelonLogger.LogError($"Exception in image downloader patch: {ex}");
            }
        }
Example #2
0
        public AvatarModule() : base(ExpandedMenu.AvatarMenu, FavCatMod.Database.AvatarFavorites, GetListsParent())
        {
            MelonLogger.Log("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;

            myInitialised = true;
        }
Example #3
0
 public override void OnApplicationStart()
 {
     MelonCoroutines.Start(GetAssembly());
     MelonLogger.Msg("Initialized!");
 }
Example #4
0
        internal static void FinalizeTowerModel(ModTower modTower, TowerModel towerModel)
        {
            // do their base tower modifications
            try
            {
                modTower.ModifyBaseTowerModel(towerModel);
            }
            catch (Exception)
            {
                MelonLogger.Error($"Failed to modify TowerModel {towerModel.name}");
                throw;
            }

            // actually apply the upgrades
            try
            {
                foreach (var modUpgrade in modTower.upgrades.Cast <ModUpgrade>()
                         .Where(modUpgrade =>
                                modUpgrade != null && towerModel.tiers[modUpgrade.Path] >= modUpgrade.Tier)
                         .OrderByDescending(modUpgrade => modUpgrade.Priority)
                         .ThenBy(modUpgrade => modUpgrade.Tier)
                         .ThenBy(modUpgrade => modUpgrade.Path))
                {
                    try
                    {
                        modUpgrade.ApplyUpgrade(towerModel);
                    }
                    catch (Exception)
                    {
                        MelonLogger.Error(
                            $"Failed to apply ModUpgrade {modUpgrade.Name} to TowerModel {towerModel.name}");
                        throw;
                    }
                }
            }
            catch (Exception)
            {
                MelonLogger.Error($"Failed to apply upgrades for TowerModel {towerModel.name}");
                throw;
            }

            if (modTower.ShouldCreateParagon && towerModel.isParagon)
            {
                towerModel.tiers = new[] { 6, 0, 0 };
            }

            // set the tower's display model
            if (modTower.Use2DModel)
            {
                try
                {
                    var name = modTower.Get2DTexture(towerModel.tiers);
                    var guid = ModContent.GetTextureGUID(modTower.mod, name);
                    towerModel.display = guid;
                    towerModel.GetBehavior <DisplayModel>().display        = guid;
                    towerModel.GetBehavior <DisplayModel>().positionOffset = new Vector3(0, 0, 2f);
                    Tower2DScales[guid] = modTower.PixelsPerUnit;
                }
                catch (Exception)
                {
                    MelonLogger.Error($"Failed to load 2d display for TowerModel {towerModel.name}");
                    throw;
                }
            }
            else
            {
                try
                {
                    if (modTower.displays.Where(display =>
                                                display.UseForTower(towerModel.tiers) && display.ParagonDisplayIndex <= 0)
                        .OrderByDescending(display => display.Id)
                        .FirstOrDefault() is ModTowerDisplay modTowerDisplay)
                    {
                        modTowerDisplay.ApplyToTower(towerModel);
                    }
                }
                catch (Exception)
                {
                    MelonLogger.Error($"Failed to load ModTowerDisplay for TowerModel {towerModel.name}");
                    throw;
                }
            }

            // last paragon stuff
            if (modTower.ShouldCreateParagon && towerModel.isParagon)
            {
                try
                {
                    if (modTower.paragonUpgrade.RemoveAbilities)
                    {
                        towerModel.behaviors = towerModel.behaviors.RemoveItemsOfType <Model, AbilityModel>();
                    }

                    var paragonModel = modTower.paragonUpgrade.ParagonTowerModel.Duplicate();

                    for (var i = 0; i < paragonModel.displayDegreePaths.Count; i++)
                    {
                        var displayDegreePath = paragonModel.displayDegreePaths[i];
                        displayDegreePath.name = $"AssetPathModel_{modTower.paragonUpgrade.GetType().Name}Lvl1";

                        var index           = i;
                        var modTowerDisplay = modTower.displays.Where(display =>
                                                                      display.UseForTower(towerModel.tiers) && index >= display.ParagonDisplayIndex)
                                              .OrderByDescending(display => display.ParagonDisplayIndex)
                                              .FirstOrDefault();
                        if (modTowerDisplay != default)
                        {
                            displayDegreePath.assetPath = modTowerDisplay.Id;
                        }
                    }

                    towerModel.behaviors = towerModel.behaviors.AddTo(paragonModel);

                    modTower.paragonUpgrade.ApplyUpgrade(towerModel);
                }
                catch (Exception)
                {
                    MelonLogger.Error(
                        $"Failed to apply ModParagonUpgrade {modTower.paragonUpgrade.Name} to TowerModel {towerModel.name}");
                    throw;
                }
            }
        }
Example #5
0
 static SM_Component()
 {
     try { SetAsLastSiblingMethod = typeof(Transform).GetMethod("SetAsLastSibling", BindingFlags.Public | BindingFlags.Instance); } catch (System.Exception ex) { MelonLogger.Warning($"Exception while Getting Transform.SetAsLastSibling: {ex}"); }
 }
        private void ShitIStoleFromYude2000()
        {
            string[] allitems = new string[]
            {
                "BasementKey",
                "CarKey",
                "GarageKey",
                "MainKey",
                "Blacklight Flashlight",
                "Glowstick",
                "Flashlight",
                "StrongFlashlight",
                "EMF Reader",
                "EVP Recorder",
                "Thermometer",
                "IR Light Sensor",
                "Motion Sensor",
                "SoundSensor",
                "Ghost Writing Book",
                "Parabolic Microphone",
                "DSLRCamera",
                "Tripod",
                "Head Mounted Camera",
                "Candle",
                "Crucifix",
                "Lighter",
                "SaltShaker",
                "Bone",
                "Ouija board",
                "PainKillers",
                "WhiteSage",
                "Hellephant",
                "Hanging Body",
                "monsterprefab",
                "WiccanAltar",
                "ZomBear",
                "ZomBunny",
                "ButcherKnife",
                "HumanSkull",
                "VHS Tape",
                "TarotCardBox",
                "VoodooDoll",
                "Bug",
                "GhostOrb",
                "EMF Spot",
                "Footstep",
                "PhotoPaper",
                "Noise Spot",
                "SaltSpot",
                "SanitySoundSpot",
                "TornCloth",
                "Camera",
                "Walkie Talkie",
                "BoxFlashPrefab",
            };

            if (!PhotonNetwork.InRoom)
            {
                GUI.Label(new Rect(720f, 0f, 200f, 20f), "Custom Room Creator:");
                this.serverName  = GUI.TextArea(new Rect(720f, 25f, 200f, 20f), this.serverName);
                this.serverSlots = GUI.HorizontalSlider(new Rect(720f, 50f, 200f, 20f), (float)((int)this.serverSlots), 4f, 90f);
                GUI.Label(new Rect(720f, 65f, 200f, 20f), "Slots: " + ((int)this.serverSlots).ToString());
                if (GUI.Toggle(new Rect(720f, 80f, 200f, 20f), this.isPrivateServer, "Private Room") != this.isPrivateServer)
                {
                    this.isPrivateServer = !isPrivateServer;
                }
                if (GUI.Button(new Rect(720f, 105f, 200f, 20f), "Create Custom Room"))
                {
                    if (this.isPrivateServer)
                    {
                        PlayerPrefs.SetInt("isPublicServer", 0);
                        RoomOptions roomOptions = new RoomOptions
                        {
                            IsOpen     = true,
                            IsVisible  = false,
                            MaxPlayers = Convert.ToByte((int)this.serverSlots),
                            PlayerTtl  = 2000
                        };
                        PhotonNetwork.CreateRoom(UnityEngine.Random.Range(0, 999999).ToString("000000"), roomOptions, TypedLobby.Default);
                    }
                    if (!this.isPrivateServer)
                    {
                        PlayerPrefs.SetInt("isPublicServer", 1);
                        RoomOptions roomOptions2 = new RoomOptions
                        {
                            IsOpen     = true,
                            IsVisible  = true,
                            MaxPlayers = Convert.ToByte((int)this.serverSlots),
                            PlayerTtl  = 2000
                        };
                        PhotonNetwork.CreateRoom(this.serverName + "#" + UnityEngine.Random.Range(0, 999999).ToString("000000"), roomOptions2, TypedLobby.Default);
                    }
                }
            }
            if (Main.levelController != null)
            {
                if (GUI.Button(new Rect(520f, 120f, 200f, 20f), "Random Event") && Main.ghostAI != null)
                {
                    Main.ghostAI.field_Public_GhostActivity_0.InteractWithARandomDoor();
                    Main.ghostAI.field_Public_GhostActivity_0.InteractWithARandomProp();
                    Main.ghostAI.field_Public_GhostActivity_0.Interact();
                    Main.ghostAI.RandomEvent();
                }

                //if (GUI.Button(new Rect(520f, 120f, 200f, 20f), "Sound"))
                //{
                //    Main.ghostAudio.PlaySound(1, false, false);
                //    Main.ghostAudio.PlaySound(0, false, false);

                //    Main.ghostInteraction.GetComponent<PhotonView>().RPC("SpawnFootstepNetworked", 0, new Il2CppSystem.Object[]
                //    {
                //        ghostAI.transform.position,
                //        ghostAI.transform.rotation,
                //        new Il2CppSystem.Int32(){ m_value = UnityEngine.Random.Range(0, 3) }.BoxIl2CppObject()
                //    });
                //}

                if (GUI.Button(new Rect(520f, 145f, 200f, 20f), "Wander"))
                {
                    Main.ghostAI.field_Public_Boolean_6 = true;
                    Main.ghostAI.field_Public_Animator_0.SetBool("isIdle", false);
                    Vector3    destination = Vector3.zero;
                    NavMeshHit navMeshHit;
                    if (NavMesh.SamplePosition(UnityEngine.Random.insideUnitSphere * 3f + Main.ghostAI.transform.position, out navMeshHit, 3f, 1))
                    {
                        destination = navMeshHit.position;
                    }
                    Main.ghostAI.field_Public_NavMeshAgent_0.destination = destination;
                    Main.ghostAI.ChangeState((GhostAI.EnumNPublicSealedvaidwahufalidothfuapUnique) 1, null, null);
                    Main.ghostAI.field_Public_PhotonView_0.RPC("Hunting", 0, new Il2CppSystem.Object[]
                    {
                        new Il2CppSystem.Boolean().BoxIl2CppObject()
                    });
                    Main.ghostAI.field_Public_PhotonView_0.RPC("SyncChasingPlayer", 0, new Il2CppSystem.Object[]
                    {
                        new Il2CppSystem.Boolean().BoxIl2CppObject()
                    });
                }
                if (GUI.Button(new Rect(520f, 170f, 200f, 20f), "Hunt"))
                {
                    SetupPhaseController.field_Public_Static_SetupPhaseController_0.field_Public_Boolean_0 = false;
                    Main.ghostAI.field_Public_Boolean_4 = true;
                    Main.ghostAI.field_Public_Boolean_2 = true;
                    Main.ghostAI.field_Public_Animator_0.SetBool("isIdle", false);
                    Main.ghostAI.field_Public_Animator_0.SetInteger("WalkType", 1);
                    Main.ghostAI.field_Public_NavMeshAgent_0.speed = Main.ghostAI.field_Public_Single_0;
                    Main.ghostAI.field_Public_GhostInteraction_0.CreateAppearedEMF(Main.ghostAI.transform.position);
                    Vector3 destination2 = Vector3.zero;
                    float   num          = UnityEngine.Random.Range(2f, 15f);

                    NavMeshHit navMeshHit2;

                    if (NavMesh.SamplePosition(UnityEngine.Random.insideUnitSphere * num + Main.ghostAI.transform.position, out navMeshHit2, num, 1))
                    {
                        destination2 = navMeshHit2.position;
                    }
                    else
                    {
                        destination2 = Vector3.zero;
                    }
                    Main.ghostAI.field_Public_NavMeshAgent_0.SetDestination(destination2);
                    SetupPhaseController.field_Public_Static_SetupPhaseController_0.ForceEnterHuntingPhase();
                    Main.ghostAI.ChangeState((GhostAI.EnumNPublicSealedvaidwahufalidothfuapUnique) 2, null, null);
                    Main.ghostAI.field_Public_PhotonView_0.RPC("Hunting", 0, new Il2CppSystem.Object[]
                    {
                        new Il2CppSystem.Boolean()
                        {
                            m_value = true
                        }.BoxIl2CppObject()
                    });
                    Main.ghostAI.field_Public_PhotonView_0.RPC("SyncChasingPlayer", 0, new Il2CppSystem.Object[]
                    {
                        new Il2CppSystem.Boolean()
                        {
                            m_value = true
                        }.BoxIl2CppObject()
                    });
                }
                if (GUI.Button(new Rect(520f, 195f, 200f, 20f), "Idle"))
                {
                    Main.ghostAI.field_Public_Animator_0.SetInteger("IdleNumber", UnityEngine.Random.Range(0, 2));
                    Main.ghostAI.field_Public_Animator_0.SetBool("isIdle", true);
                    Main.ghostAI.UnAppear(false);
                    Main.ghostAI.field_Public_GhostAudio_0.TurnOnOrOffAppearSource(false);
                    Main.ghostAI.field_Public_GhostAudio_0.PlayOrStopAppearSource(false);
                    Main.ghostAI.ChangeState(0, null, null);
                    Main.ghostAI.field_Public_PhotonView_0.RPC("Hunting", 0, new Il2CppSystem.Object[]
                    {
                        new Il2CppSystem.Boolean().BoxIl2CppObject()
                    });
                    Main.ghostAI.field_Public_PhotonView_0.RPC("SyncChasingPlayer", 0, new Il2CppSystem.Object[]
                    {
                        new Il2CppSystem.Boolean().BoxIl2CppObject()
                    });
                }
                Il2CppSystem.Int32 appearRand = new Il2CppSystem.Int32();

                appearRand.m_value = UnityEngine.Random.Range(0, 3);

                if (GUI.Button(new Rect(520f, 220f, 200f, 20f), "Appear"))
                {
                    Main.ghostAI.field_Public_PhotonView_0.RPC("MakeGhostAppear", 0, new Il2CppSystem.Object[]
                    {
                        new Il2CppSystem.Boolean()
                        {
                            m_value = true
                        }.BoxIl2CppObject(),
                        new Il2CppSystem.Int32()
                        {
                            m_value = UnityEngine.Random.Range(0, 3)
                        }.BoxIl2CppObject()
                    });
                }
                if (GUI.Button(new Rect(520f, 245f, 200f, 20f), "Unappear"))
                {
                    Main.ghostAI.field_Public_PhotonView_0.RPC("MakeGhostAppear", 0, new Il2CppSystem.Object[]
                    {
                        new Il2CppSystem.Boolean().BoxIl2CppObject(),
                        new Il2CppSystem.Int32()
                        {
                            m_value = UnityEngine.Random.Range(0, 3)
                        }.BoxIl2CppObject()
                    });
                }
                if (GUI.Toggle(new Rect(1120f, 325f, 200f, 20f), this.showItemList, "Show Item Spawner") != this.showItemList)
                {
                    this.showItemList = !this.showItemList;
                }

                if (this.showItemList)
                {
                    GUI.Label(new Rect(520f, 225f, 200f, 20f), "Item Spawner:");
                    this.scrollViewVector = GUI.BeginScrollView(new Rect(this.dropDownRect2.x - 100f, this.dropDownRect2.y + 25f, this.dropDownRect2.width, this.dropDownRect2.height), this.scrollViewVector, new Rect(0f, 0f, this.dropDownRect2.width, Mathf.Max(this.dropDownRect2.height, (float)(allitems.Length * 25))));
                    GUI.Box(new Rect(0f, 0f, this.dropDownRect2.width, Mathf.Max(this.dropDownRect2.height, (float)(allitems.Length * 25))), "");
                    for (int l = 0; l < allitems.Length; l++)
                    {
                        if (GUI.Button(new Rect(0f, (float)(l * 25), this.dropDownRect2.height, 25f), ""))
                        {
                            this.selecteditem = l;
                            if (PhotonNetwork.InRoom)
                            {
                                MyPlayer = GetLocalPlayer();
                                MelonLogger.Log(allitems[this.selecteditem].ToString());
                                PhotonNetwork.Instantiate(allitems[this.selecteditem], MyPlayer.transform.position, Quaternion.identity, 0, null);
                            }
                        }
                        GUI.Label(new Rect(5f, (float)(l * 25), this.dropDownRect2.height, 25f), allitems[l]);
                    }
                    GUI.EndScrollView();
                }

                GUI.Label(new Rect(920f, 295f, 200f, 20f), "ESP:");
                if (GUI.Toggle(new Rect(920f, 320f, 200f, 20f), this.GhostESP, "Ghost") != this.GhostESP)
                {
                    this.GhostESP = !this.GhostESP;
                }
                if (GUI.Toggle(new Rect(920f, 370f, 200f, 20f), this.PlayerESP, "Player") != this.PlayerESP)
                {
                    this.PlayerESP = !this.PlayerESP;
                }
                if (GUI.Toggle(new Rect(920f, 395f, 200f, 20f), this.OuijaESP, "Ouija Board") != this.OuijaESP)
                {
                    this.OuijaESP = !this.OuijaESP;
                }
                if (GUI.Toggle(new Rect(920f, 420f, 200f, 20f), this.KeyESP, "Key") != this.KeyESP)
                {
                    this.KeyESP = !this.KeyESP;
                }
                if (GUI.Toggle(new Rect(920f, 445f, 200f, 20f), this.EvidenceESP, "Evidence") != this.EvidenceESP)
                {
                    this.EvidenceESP = !this.EvidenceESP;
                }

                if (GUI.Toggle(new Rect(1120f, 300f, 200f, 20f), this.ShowInfoGhost, "Show Ghost Info") != this.ShowInfoGhost)
                {
                    this.ShowInfoGhost = !this.ShowInfoGhost;
                }
                if (GUI.Toggle(new Rect(1120f, 250f, 200f, 20f), this.ShowInfoPlayer, "Show Player Info") != this.ShowInfoPlayer)
                {
                    this.ShowInfoPlayer = !this.ShowInfoPlayer;
                }
            }
            if (Main.levelController == null)
            {
                GUI.SetNextControlName("changename");
                this.Name = GUI.TextArea(new Rect(320f, 25f, 200f, 20f), this.Name);
                if (GUI.Button(new Rect(320f, 45f, 200f, 20f), "Change Name"))
                {
                    GUI.FocusControl("changename");
                    PhotonNetwork.NickName = this.Name;
                }

                if (GUI.Button(new Rect(320f, 145f, 200f, 20f), "Force Start"))
                {
                    Main.serverManager.StartGame();
                }

                if (GUI.Button(new Rect(520f, 50f, 200f, 20f), "Add 100$"))
                {
                    FileBasedPrefs.SetInt("PlayersMoney", FileBasedPrefs.GetInt("PlayersMoney", 0) + 100);
                }
                if (GUI.Button(new Rect(520f, 75f, 200f, 20f), "Add 1 Level"))
                {
                    FileBasedPrefs.SetInt("myTotalExp", FileBasedPrefs.GetInt("myTotalExp", 0) + 100);
                }

                //GUI.Label(new Rect(920f, 0f, 200f, 20f), "Join Room:");
                //this.roomName = GUI.TextArea(new Rect(920f, 25f, 200f, 20f), this.roomName);
                //this.steamID = GUI.TextArea(new Rect(920f, 50f, 200f, 20f), this.steamID);
                //if (GUI.Button(new Rect(920f, 75f, 200f, 20f), "Join Room by Name"))
                //{
                //    PhotonNetwork.JoinRoom(this.roomName);
                //}
                //if (GUI.Button(new Rect(920f, 100f, 200f, 20f), "Join Room by ID"))
                //{
                //    object[] FriendIDList;

                //    bool test = PhotonNetwork.FindFriends(new string[]
                //    {
                //            this.steamID
                //    });
                //    MelonLogger.Log("steamID = " + steamID);
                //    //foreach (FriendInfo friendInfo in PhotonNetwork.Friends)
                //    //{
                //    //PhotonNetwork.JoinRoom(friendInfo.Room);
                //    //}
                //}
            }
        }
Example #7
0
 public static void LogAsHeader(string title)
 {
     MelonLogger.Msg(spacesForHeader);
     MelonLogger.Msg(title);
     MelonLogger.Msg(spacesForHeader);
 }
Example #8
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 #9
0
        internal static void LoadFromFile(string filepath, string symbolspath = null)
        {
            if (string.IsNullOrEmpty(filepath))
            {
                return;
            }

            if (MelonDebug.IsEnabled())
            {
                Assembly melonassembly = null;
                try
                {
                    melonassembly = Assembly.LoadFrom(filepath);
                }
                catch (Exception ex)
                {
                    MelonLogger.Error($"Failed to Load Assembly for {filepath}: {ex}");
                    return;
                }

                if (melonassembly == null)
                {
                    MelonLogger.Error($"Failed to Load Assembly for {filepath}: Assembly.LoadFrom returned null");;
                    return;
                }

                MelonHandler.LoadFromAssembly(melonassembly, filepath);
            }
            else
            {
                byte[] symbolsdata = new byte[0];
                if (string.IsNullOrEmpty(symbolspath))
                {
                    symbolspath = Path.Combine(Path.GetDirectoryName(filepath), $"{Path.GetFileNameWithoutExtension(filepath)}.mdb");
                }
                if (!File.Exists(symbolspath))
                {
                    symbolspath = $"{filepath}.mdb";
                }
                if (File.Exists(symbolspath))
                {
                    try
                    {
                        symbolsdata = File.ReadAllBytes(symbolspath);
                    }
                    catch (Exception ex)
                    {
                        if (MelonDebug.IsEnabled())
                        {
                            MelonLogger.Warning($"Failed to Load Symbols for {filepath}: {ex}");
                        }
                    }
                }

                byte[] filedata = null;
                try
                {
                    filedata = File.ReadAllBytes(filepath);
                }
                catch (Exception ex)
                {
                    MelonLogger.Error($"Failed to Read File Data for {filepath}: {ex}");
                    return;
                }

                LoadFromByteArray(filedata, symbolsdata, filepath);
            }
        }
Example #10
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!");
        }
 internal static void LogError(string message, params object[] parameters) => MelonLogger.LogError(message, parameters);
Example #12
0
    private static void Update()
    {
        for (;;)
        {
            try
            {
                if (SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.WORKING &&
                    SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.NOT_SUPPORT)
                {
                    Thread.Sleep(50);
                    continue;
                }

                SRanipal_Eye_API.GetEyeData_v2(ref _latestEyeData);
                var CombinedEyeReverse = Vector3.Scale(
                    _latestEyeData.verbose_data.combined.eye_data.gaze_direction_normalized,
                    new Vector3(-1, 1, 1));
                var LeftEyeReverse = Vector3.Scale(_latestEyeData.verbose_data.left.gaze_direction_normalized,
                                                   new Vector3(-1, 1, 1));
                var RightEyeReverse = Vector3.Scale(_latestEyeData.verbose_data.right.gaze_direction_normalized,
                                                    new Vector3(-1, 1, 1));

                if (CombinedEyeReverse != new Vector3(1.0f, -1.0f, -1.0f))
                {
                    SRanipalData["EyesX"] = CombinedEyeReverse.x;
                    SRanipalData["EyesY"] = CombinedEyeReverse.y;

                    SRanipalData["LeftEyeX"] = LeftEyeReverse.x;
                    SRanipalData["LeftEyeY"] = LeftEyeReverse.y;

                    SRanipalData["RightEyeX"] = RightEyeReverse.x;
                    SRanipalData["RightEyeY"] = RightEyeReverse.y;
                }

                SRanipalData["LeftEyeLid"]  = _latestEyeData.verbose_data.left.eye_openness;
                SRanipalData["RightEyeLid"] = _latestEyeData.verbose_data.right.eye_openness;

                if (_latestEyeData.verbose_data.right.GetValidity(SingleEyeDataValidity
                                                                  .SINGLE_EYE_DATA_PUPIL_DIAMETER_VALIDITY))
                {
                    CurrentDiameter = _latestEyeData.verbose_data.right.pupil_diameter_mm;
                    if (_latestEyeData.verbose_data.right.eye_openness >= 1f)
                    {
                        UpdateMinMaxDilation(_latestEyeData.verbose_data.right.pupil_diameter_mm);
                    }
                }
                else if (_latestEyeData.verbose_data.left.GetValidity(SingleEyeDataValidity
                                                                      .SINGLE_EYE_DATA_PUPIL_DIAMETER_VALIDITY))
                {
                    CurrentDiameter = _latestEyeData.verbose_data.left.pupil_diameter_mm;
                    if (_latestEyeData.verbose_data.left.eye_openness >= 1f)
                    {
                        UpdateMinMaxDilation(_latestEyeData.verbose_data.left.pupil_diameter_mm);
                    }
                }

                var normalizedFloat = CurrentDiameter / MinOpen / (MaxOpen - MinOpen);
                SRanipalData["EyesDilation"] = Mathf.Clamp(normalizedFloat, 0, 1);

                SRanipalData["EyesWiden"] = _latestEyeData.expression_data.left.eye_wide >
                                            _latestEyeData.expression_data.right.eye_wide
                    ? _latestEyeData.expression_data.left.eye_wide
                    : _latestEyeData.expression_data.right.eye_wide;

                SRanipalData["LeftEyeWiden"]  = _latestEyeData.expression_data.left.eye_wide;
                SRanipalData["RightEyeWiden"] = _latestEyeData.expression_data.right.eye_wide;

                SRanipalData["LeftEyeSqueeze"]  = _latestEyeData.expression_data.left.eye_squeeze;
                SRanipalData["RightEyeSqueeze"] = _latestEyeData.expression_data.right.eye_squeeze;

                SRanipalData["EyesSqueeze"] = _latestEyeData.expression_data.left.eye_squeeze >
                                              _latestEyeData.expression_data.right.eye_squeeze
                    ? _latestEyeData.expression_data.left.eye_squeeze
                    : _latestEyeData.expression_data.right.eye_squeeze;
            }
            catch (Exception e)
            {
                if (!(e.InnerException is ThreadAbortException))
                {
                    MelonLogger.LogError("Threading error occured in SRanipalTrack.Update: " + e.Message);
                }
            }

            Thread.Sleep(5);
        }
    }
Example #13
0
        // this is slightly rewritten code from VRCSDK
        // if only the game was still in IL so that transpiler harmony patches worked
        private static bool GetReflectionData(VRC_MirrorReflection __instance, Camera __0, ref VRC_MirrorReflection.ReflectionData __result)
        {
            try
            {
                var @this         = __instance;
                var currentCamera = __0;

                var reflections = @this._mReflections ??
                                  (@this._mReflections = new Dictionary <Camera, VRC_MirrorReflection.ReflectionData>());

                // TryGetValue crashes in unhollower 0.4
                var reflectionData = reflections.ContainsKey(currentCamera)
                    ? reflections[currentCamera]
                    : reflections[currentCamera] = new VRC_MirrorReflection.ReflectionData
                {
                    propertyBlock = new MaterialPropertyBlock()
                };

                if (@this._temporaryRenderTexture)
                {
                    RenderTexture.ReleaseTemporary(@this._temporaryRenderTexture);
                }
                if (reflectionData.texture[0])
                {
                    RenderTexture.ReleaseTemporary(reflectionData.texture[0]);
                }
                if (reflectionData.texture[1])
                {
                    RenderTexture.ReleaseTemporary(reflectionData.texture[1]);
                }

                int width;
                int height;

                if (ourAllMirrorsAuto || @this.mirrorResolution == VRC_MirrorReflection.Dimension.Auto)
                {
                    width  = Mathf.Min(currentCamera.pixelWidth, ourMaxEyeResolution);
                    height = Mathf.Min(currentCamera.pixelHeight, ourMaxEyeResolution);
                }
                else
                {
                    width = height = (int)@this.mirrorResolution;
                }

                var requestedMsaa = currentCamera.targetTexture?.antiAliasing ?? QualitySettings.antiAliasing;
                if (ourMirrorMsaa != 0)
                {
                    requestedMsaa = ourMsaaIsUpperLimit.Value
                        ? Mathf.Clamp(requestedMsaa, 1, ourMirrorMsaa)
                        : ourMirrorMsaa;
                }
                else
                {
                    requestedMsaa = Mathf.Clamp(requestedMsaa, 1, (int)@this.maximumAntialiasing);
                }
                @this._temporaryRenderTexture = RenderTexture.GetTemporary(width, height, 24, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Default, requestedMsaa);
                reflectionData.texture[0]     = RenderTexture.GetTemporary(width, height, 24, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Default, 1);
                reflectionData.propertyBlock.SetTexture(VRC_MirrorReflection._texturePropertyId[0], reflectionData.texture[0]);
                if (currentCamera.stereoEnabled)
                {
                    reflectionData.texture[1] = RenderTexture.GetTemporary(width, height, 24, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Default, 1);
                    reflectionData.propertyBlock.SetTexture(VRC_MirrorReflection._texturePropertyId[1], reflectionData.texture[1]);
                }

                __result = reflectionData;
                return(false);
            }
            catch (Exception ex)
            {
                MelonLogger.Error("Exception happened in GetReflectionData override" + ex);
            }
            return(true);
        }
Example #14
0
        private static void CleanAvatar(VRCAvatarManager avatarManager, GameObject go)
        {
            if (!AdvancedSafetySettings.AvatarFilteringEnabled)
            {
                return;
            }

            if (AdvancedSafetySettings.AvatarFilteringOnlyInPublic &&
                RoomManager.field_Internal_Static_ApiWorldInstance_0?.InstanceType != ApiWorldInstance.AccessType.Public)
            {
                return;
            }

            var vrcPlayer = avatarManager.field_Private_VRCPlayer_0;

            if (vrcPlayer == null)
            {
                return;
            }

            var userId = vrcPlayer.prop_Player_0?.prop_APIUser_0?.id ?? "";

            if (!AdvancedSafetySettings.IncludeFriends && APIUser.IsFriendsWith(userId))
            {
                return;
            }

            if (AdvancedSafetySettings.AbideByShowAvatar && IsAvatarExplicitlyShown(userId))
            {
                return;
            }

            var start            = Stopwatch.StartNew();
            var scannedObjects   = 0;
            var destroyedObjects = 0;

            var seenTransforms           = 0;
            var seenPolys                = 0;
            var seenMaterials            = 0;
            var seenAudioSources         = 0;
            var seenConstraints          = 0;
            var seenClothVertices        = 0;
            var seenColliders            = 0;
            var seenRigidbodies          = 0;
            var seenAnimators            = 0;
            var seenLights               = 0;
            var seenComponents           = 0;
            var seenParticles            = 0;
            var seenMeshParticleVertices = 0;

            var animator = go.GetComponent <Animator>();

            var componentList           = new Il2CppSystem.Collections.Generic.List <Component>();
            var audioSourcesList        = new List <AudioSource>();
            var skinnedRendererListList = new List <SkinnedMeshRenderer>();

            void Bfs(GameObjectWithPriorityData objWithPriority)
            {
                var obj = objWithPriority.GameObject;

                if (obj == null)
                {
                    return;
                }
                scannedObjects++;

                if (animator?.IsBoneTransform(obj.transform) != true && seenTransforms++ >= AdvancedSafetySettings.MaxTransforms)
                {
                    Object.DestroyImmediate(obj, true);
                    destroyedObjects++;
                    return;
                }

                if (objWithPriority.Depth >= AdvancedSafetySettings.MaxDepth)
                {
                    Object.DestroyImmediate(obj, true);
                    destroyedObjects++;
                    return;
                }

                if (!AdvancedSafetySettings.AllowUiLayer && (obj.layer == 12 || obj.layer == 5))
                {
                    obj.layer = 9;
                }

                obj.GetComponents(componentList);
                foreach (var component in componentList)
                {
                    if (component == null)
                    {
                        continue;
                    }

                    component.TryCast <AudioSource>()?.VisitAudioSource(ref scannedObjects, ref destroyedObjects, ref seenAudioSources, obj, audioSourcesList, objWithPriority.IsActiveInHierarchy);
                    component.TryCast <IConstraint>()?.VisitConstraint(ref scannedObjects, ref destroyedObjects, ref seenConstraints, obj);
                    component.TryCast <Cloth>()?.VisitCloth(ref scannedObjects, ref destroyedObjects, ref seenClothVertices, obj);
                    component.TryCast <Rigidbody>()?.VisitGeneric(ref scannedObjects, ref destroyedObjects, ref seenRigidbodies, AdvancedSafetySettings.MaxRigidBodies);

                    component.TryCast <Collider>()?.VisitCollider(ref scannedObjects, ref destroyedObjects, ref seenColliders, obj);
                    component.TryCast <Animator>()?.VisitGeneric(ref scannedObjects, ref destroyedObjects, ref seenAnimators, AdvancedSafetySettings.MaxAnimators);
                    component.TryCast <Light>()?.VisitGeneric(ref scannedObjects, ref destroyedObjects, ref seenLights, AdvancedSafetySettings.MaxLights);

                    component.TryCast <Renderer>()?.VisitRenderer(ref scannedObjects, ref destroyedObjects, ref seenPolys, ref seenMaterials, obj, skinnedRendererListList);
                    component.TryCast <ParticleSystem>()?.VisitParticleSystem(component.GetComponent <ParticleSystemRenderer>(), ref scannedObjects, ref destroyedObjects, ref seenParticles, ref seenMeshParticleVertices, obj);

                    if (ReferenceEquals(component.TryCast <Transform>(), null))
                    {
                        component.VisitGeneric(ref scannedObjects, ref destroyedObjects, ref seenComponents, AdvancedSafetySettings.MaxComponents);
                    }
                }

                foreach (var child in obj.transform)
                {
                    ourBfsQueue.Enqueue(new GameObjectWithPriorityData(child.Cast <Transform>().gameObject, objWithPriority.Depth + 1, objWithPriority.IsActiveInHierarchy));
                }
            }

            Bfs(new GameObjectWithPriorityData(go, 0, true, true));
            while (ourBfsQueue.Count > 0)
            {
                Bfs(ourBfsQueue.Dequeue());
            }

            ComponentAdjustment.PostprocessSkinnedRenderers(skinnedRendererListList);

            if (!AdvancedSafetySettings.AllowSpawnSounds)
            {
                MelonCoroutines.Start(CheckSpawnSounds(go, audioSourcesList));
            }

            if (MelonDebug.IsEnabled() || destroyedObjects > 100)
            {
                MelonLogger.Msg($"Cleaned avatar ({avatarManager.prop_ApiAvatar_0?.name}) used by \"{vrcPlayer.prop_VRCPlayerApi_0?.displayName}\" in {start.ElapsedMilliseconds}ms, scanned {scannedObjects} things, destroyed {destroyedObjects} things");
            }
        }
Example #15
0
 public override void OnLevelWasInitialized(int level)
 {
     ui.Recreate();
     MelonLogger.Log("Initialized scene " + level.ToString());
 }
Example #16
0
        private static void ConsoleCleaner()
        {
            // Il2CppSystem.Console.SetOut(new Il2CppSystem.IO.StreamWriter(Il2CppSystem.IO.Stream.Null));
            try
            {
                Il2Cppmscorlib = Assembly.Load("Il2Cppmscorlib");
                if (Il2Cppmscorlib == null)
                {
                    throw new Exception("Unable to Find Assembly Il2Cppmscorlib!");
                }

                streamType = Il2Cppmscorlib.GetType("Il2CppSystem.IO.Stream");
                if (streamType == null)
                {
                    throw new Exception("Unable to Find Type Il2CppSystem.IO.Stream!");
                }

                PropertyInfo propertyInfo = streamType.GetProperty("Null", BindingFlags.Static | BindingFlags.Public);
                if (propertyInfo == null)
                {
                    throw new Exception("Unable to Find Property Il2CppSystem.IO.Stream.Null!");
                }

                MethodInfo nullStreamField = propertyInfo.GetGetMethod();
                if (nullStreamField == null)
                {
                    throw new Exception("Unable to Find Get Method of Property Il2CppSystem.IO.Stream.Null!");
                }

                object nullStream = nullStreamField.Invoke(null, new object[0]);
                if (nullStream == null)
                {
                    throw new Exception("Unable to Get Value of Property Il2CppSystem.IO.Stream.Null!");
                }

                Type streamWriterType = Il2Cppmscorlib.GetType("Il2CppSystem.IO.StreamWriter");
                if (streamWriterType == null)
                {
                    throw new Exception("Unable to Find Type Il2CppSystem.IO.StreamWriter!");
                }

                ConstructorInfo streamWriterCtor = streamWriterType.GetConstructor(new[] { streamType });
                if (streamWriterCtor == null)
                {
                    throw new Exception("Unable to Find Constructor of Type Il2CppSystem.IO.StreamWriter!");
                }

                object nullStreamWriter = streamWriterCtor.Invoke(new[] { nullStream });
                if (nullStreamWriter == null)
                {
                    throw new Exception("Unable to Invoke Constructor of Type Il2CppSystem.IO.StreamWriter!");
                }

                Type consoleType = Il2Cppmscorlib.GetType("Il2CppSystem.Console");
                if (consoleType == null)
                {
                    throw new Exception("Unable to Find Type Il2CppSystem.Console!");
                }

                MethodInfo setOutMethod = consoleType.GetMethod("SetOut", BindingFlags.Static | BindingFlags.Public);
                if (setOutMethod == null)
                {
                    throw new Exception("Unable to Find Method Il2CppSystem.Console.SetOut!");
                }

                setOutMethod.Invoke(null, new[] { nullStreamWriter });
            }
            catch (Exception ex) { MelonLogger.Warning($"Console Cleaner Failed: {ex}"); }
        }
Example #17
0
        public async Task <bool> Download(string modDir)
        {
            if (updateInfo.Name == "BloonsTD6 Mod Helper")
            {
                Process.Start(updateInfo.LatestURL);
                MelonLogger.Msg("For the moment, the mod helper can't directly update itself");
                return(false);
            }


            string downloadURL;

            if (updateInfo.GithubReleaseURL != "")
            {
                var releaseInfo = await GetLatestReleaseAsync();

                downloadURL = releaseInfo.Assets.Select(asset => asset.BrowserDownloadUrl.OriginalString)
                              .FirstOrDefault(s => s.EndsWith(".dll") || s.EndsWith(".zip"));
            }
            else
            {
                downloadURL = updateInfo.LatestURL;
            }

            if (downloadURL == "" || downloadURL == default)
            {
                return(false);
            }


            if (!string.IsNullOrEmpty(updateInfo.Location))
            {
                try
                {
                    File.Delete(updateInfo.Location);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }

            var fileName = downloadURL.Substring(downloadURL.LastIndexOf("/", StringComparison.Ordinal));

            if (fileName.Contains("?"))
            {
                fileName = fileName.Substring(0, fileName.IndexOf("?", StringComparison.Ordinal));
            }

            var response = await client.GetAsync(downloadURL);

            var newFile = $"{modDir}\\{fileName}";

            using (var fs = new FileStream(newFile, FileMode.Create))
            {
                await response.Content.CopyToAsync(fs);
            }

            var helperDir = $"{modDir}\\{Assembly.GetExecutingAssembly().GetName().Name}";

            if (fileName.EndsWith(".zip"))
            {
                var zipTemp = $"{helperDir}\\Zip Temp";
                if (Directory.Exists(zipTemp))
                {
                    Directory.Delete(zipTemp, true);
                }
                Directory.CreateDirectory(zipTemp);
                ZipFile.ExtractToDirectory(newFile, zipTemp);

                foreach (var enumerateFile in Directory.EnumerateFiles(zipTemp))
                {
                    var name       = Path.GetFileName(enumerateFile);
                    var targetFile = Path.Combine(modDir, name);
                    if (File.Exists(targetFile))
                    {
                        File.Delete(targetFile);
                    }
                    File.Copy(enumerateFile, targetFile);
                    File.Delete(enumerateFile);
                }
                File.Delete(newFile);
            }

            return(true);
        }
Example #18
0
        private void TransportLayer_OnMessageReceived(ITransportConnection connection, P2PMessage msg)
        {
            MessageType type = (MessageType)msg.ReadByte();

            switch (type)
            {
            case MessageType.GunFire:
            {
                GunFireMessage gfm           = new GunFireMessage(msg);
                byte           LocalplayerId = smallPlayerIds[connection.ConnectedTo];
                if (playerObjects.ContainsKey(LocalplayerId))
                {
                    PlayerRep     pr            = playerObjects[LocalplayerId];
                    AmmoVariables ammoVariables = new AmmoVariables()
                    {
                        AttackDamage   = gfm.ammoDamage,
                        AttackType     = AttackType.Piercing,
                        cartridgeType  = Cart.Cal_9mm,
                        ExitVelocity   = gfm.exitVelocity,
                        ProjectileMass = gfm.projectileMass,
                        Tracer         = false
                    };
                    if ((StressLevelZero.Handedness)gfm.handedness == StressLevelZero.Handedness.RIGHT)
                    {
                        pr.rightGunScript.firePointTransform.position = gfm.firepointPos;
                        pr.rightGunScript.firePointTransform.rotation = gfm.firepointRotation;
                        pr.rightGunScript.muzzleVelocity   = gfm.muzzleVelocity;
                        pr.rightBulletObject.ammoVariables = ammoVariables;
                        pr.leftGunScript.PullCartridge();
                        pr.rightGunScript.Fire();
                    }
                    if ((StressLevelZero.Handedness)gfm.handedness == StressLevelZero.Handedness.LEFT)
                    {
                        pr.leftGunScript.firePointTransform.position = gfm.firepointPos;
                        pr.leftGunScript.firePointTransform.rotation = gfm.firepointRotation;
                        pr.leftGunScript.muzzleVelocity   = gfm.muzzleVelocity;
                        pr.leftBulletObject.ammoVariables = ammoVariables;
                        pr.leftGunScript.PullCartridge();
                        pr.leftGunScript.Fire();
                    }
                    GunFireMessageOther gfmo = new GunFireMessageOther()
                    {
                        playerId          = LocalplayerId,
                        handedness        = gfm.handedness,
                        firepointPos      = gfm.firepointPos,
                        firepointRotation = gfm.firepointRotation,
                        ammoDamage        = gfm.ammoDamage,
                        projectileMass    = gfm.projectileMass,
                        exitVelocity      = gfm.exitVelocity,
                        muzzleVelocity    = gfm.muzzleVelocity
                    };
                    pr.faceAnimator.faceState = Source.Representations.FaceAnimator.FaceState.Angry;
                    pr.faceAnimator.faceTime  = 5;
                    ServerSendToAllExcept(gfmo, MessageSendType.Reliable, connection.ConnectedTo);
                }
                break;
            }

            case MessageType.Join:
            {
                if (msg.ReadByte() != MultiplayerMod.PROTOCOL_VERSION)
                {
                    // Somebody tried to join with an incompatible verison
                    P2PMessage m2 = new P2PMessage();
                    m2.WriteByte((byte)MessageType.JoinRejected);
                    connection.SendMessage(m2, MessageSendType.Reliable);
                    connection.Disconnect();
                }
                else
                {
                    MelonLogger.Log("Player joined with ID: " + connection.ConnectedTo);
                    if (players.Contains(connection.ConnectedTo))
                    {
                        players.Remove(connection.ConnectedTo);
                    }

                    players.Add(connection.ConnectedTo);
                    MelonLogger.Log("Player count: " + players.Count);
                    byte newPlayerId = smallIdCounter;

                    if (smallPlayerIds.ContainsKey(newPlayerId))
                    {
                        smallPlayerIds.Remove(newPlayerId);
                    }

                    smallPlayerIds.Add(connection.ConnectedTo, newPlayerId);

                    if (largePlayerIds.ContainsKey(newPlayerId))
                    {
                        largePlayerIds.Remove(newPlayerId);
                    }

                    largePlayerIds.Add(newPlayerId, connection.ConnectedTo);
                    smallIdCounter++;

                    playerConnections.Add(connection.ConnectedTo, connection);

                    string name = msg.ReadUnicodeString();
                    MelonLogger.Log("Name: " + name);

                    foreach (var smallId in playerNames.Keys)
                    {
                        ClientJoinMessage cjm = new ClientJoinMessage
                        {
                            playerId = smallId,
                            name     = playerNames[smallId],
                            steamId  = largePlayerIds[smallId]
                        };
                        connection.SendMessage(cjm.MakeMsg(), MessageSendType.Reliable);
                    }

                    ClientJoinMessage cjm2 = new ClientJoinMessage
                    {
                        playerId = 0,
                        name     = SteamClient.Name,
                        steamId  = SteamClient.SteamId
                    };
                    connection.SendMessage(cjm2.MakeMsg(), MessageSendType.Reliable);

                    if (playerNames.ContainsKey(newPlayerId))
                    {
                        playerNames.Remove(newPlayerId);
                    }

                    playerNames.Add(newPlayerId, name);

                    ClientJoinMessage cjm3 = new ClientJoinMessage
                    {
                        playerId = newPlayerId,
                        name     = name,
                        steamId  = connection.ConnectedTo
                    };
                    ServerSendToAllExcept(cjm3, MessageSendType.Reliable, connection.ConnectedTo);

                    if (playerObjects.ContainsKey(newPlayerId))
                    {
                        playerObjects.Remove(newPlayerId);
                    }
                    playerObjects.Add(newPlayerId, new PlayerRep(name, connection.ConnectedTo));

                    RichPresence.SetActivity(
                        new Activity()
                        {
                            Details = "Hosting a server",
                            Secrets = new ActivitySecrets()
                            {
                                Join = SteamClient.SteamId.ToString()
                            },
                            Party = new ActivityParty()
                            {
                                Id   = partyId,
                                Size = new PartySize()
                                {
                                    CurrentSize = players.Count + 1,
                                    MaxSize     = MultiplayerMod.MAX_PLAYERS
                                }
                            }
                        });

                    SceneTransitionMessage stm = new SceneTransitionMessage()
                    {
                        sceneName = BoneworksSceneManager.GetCurrentSceneName()
                    };
                    connection.SendMessage(stm.MakeMsg(), MessageSendType.Reliable);

                    SetPartyIdMessage spid = new SetPartyIdMessage()
                    {
                        partyId = partyId
                    };
                    connection.SendMessage(spid.MakeMsg(), MessageSendType.Reliable);

                    SetLocalSmallIdMessage slsi = new SetLocalSmallIdMessage()
                    {
                        smallId = newPlayerId
                    };
                    connection.SendMessage(slsi.MakeMsg(), MessageSendType.Reliable);

                    foreach (var so in syncObjs)
                    {
                        var iam = new IDAllocationMessage
                        {
                            allocatedId  = so.ID,
                            namePath     = BWUtil.GetFullNamePath(so.gameObject),
                            initialOwner = so.owner
                        };
                        connection.SendMessage(iam.MakeMsg(), MessageSendType.Reliable);
                    }

                    ui.SetPlayerCount(players.Count, MultiplayerUIState.Server);

                    foreach (PlayerRep pr in playerObjects.Values)
                    {
                        pr.faceAnimator.faceState = Source.Representations.FaceAnimator.FaceState.Happy;
                        pr.faceAnimator.faceTime  = 15;
                    }
                }
                break;
            }

            case MessageType.Disconnect:
            {
                MelonLogger.Log("Player left with ID: " + connection.ConnectedTo);
                byte smallId = smallPlayerIds[connection.ConnectedTo];

                playerObjects[smallId].Delete();
                playerObjects.Remove(smallId);
                players.RemoveAll((ulong val) => val == connection.ConnectedTo);
                smallPlayerIds.Remove(connection.ConnectedTo);

                P2PMessage disconnectMsg = new P2PMessage();
                disconnectMsg.WriteByte((byte)MessageType.Disconnect);
                disconnectMsg.WriteByte(smallId);

                foreach (SteamId p in players)
                {
                    playerConnections[p].SendMessage(disconnectMsg, MessageSendType.Reliable);
                }
                foreach (PlayerRep pr in playerObjects.Values)
                {
                    pr.faceAnimator.faceState = Source.Representations.FaceAnimator.FaceState.Sad;
                    pr.faceAnimator.faceTime  = 6;
                }
                break;
            }

            case MessageType.FullRig:
            {
                FullRigTransformMessage frtm = new FullRigTransformMessage(msg);

                byte playerId = smallPlayerIds[connection.ConnectedTo];
                if (playerObjects.ContainsKey(playerId))
                {
                    PlayerRep pr = playerObjects[playerId];

                    if (pr.rigTransforms.main != null)
                    {
                        //ApplyTransformMessage(pr, frtm);
                        pr.ApplyTransformMessage(frtm);

                        OtherFullRigTransformMessage ofrtm = new OtherFullRigTransformMessage
                        {
                            playerId = playerId,

                            posMain   = frtm.posMain,
                            posRoot   = frtm.posRoot,
                            posLHip   = frtm.posLHip,
                            posRHip   = frtm.posRHip,
                            posLKnee  = frtm.posLKnee,
                            posRKnee  = frtm.posRKnee,
                            posLAnkle = frtm.posLAnkle,
                            posRAnkle = frtm.posRAnkle,

                            posSpine1    = frtm.posSpine1,
                            posSpine2    = frtm.posSpine2,
                            posSpineTop  = frtm.posSpineTop,
                            posLClavicle = frtm.posLClavicle,
                            posRClavicle = frtm.posRClavicle,
                            posNeck      = frtm.posNeck,
                            posLShoulder = frtm.posLShoulder,
                            posRShoulder = frtm.posRShoulder,
                            posLElbow    = frtm.posLElbow,
                            posRElbow    = frtm.posRElbow,
                            posLWrist    = frtm.posLWrist,
                            posRWrist    = frtm.posRWrist,

                            rotMain      = frtm.rotMain,
                            rotRoot      = frtm.rotRoot,
                            rotLHip      = frtm.rotLHip,
                            rotRHip      = frtm.rotRHip,
                            rotLKnee     = frtm.rotLKnee,
                            rotRKnee     = frtm.rotRKnee,
                            rotLAnkle    = frtm.rotLAnkle,
                            rotRAnkle    = frtm.rotRAnkle,
                            rotSpine1    = frtm.rotSpine1,
                            rotSpine2    = frtm.rotSpine2,
                            rotSpineTop  = frtm.rotSpineTop,
                            rotLClavicle = frtm.rotLClavicle,
                            rotRClavicle = frtm.rotRClavicle,
                            rotNeck      = frtm.rotNeck,
                            rotLShoulder = frtm.rotLShoulder,
                            rotRShoulder = frtm.rotRShoulder,
                            rotLElbow    = frtm.rotLElbow,
                            rotRElbow    = frtm.rotRElbow,
                            rotLWrist    = frtm.rotLWrist,
                            rotRWrist    = frtm.rotRWrist
                        };

                        ServerSendToAllExcept(ofrtm, MessageSendType.Unreliable, connection.ConnectedTo);
                    }
                }
                break;
            }

            case MessageType.IdRequest:
            {
                var idrqm = new IDRequestMessage(msg);
                MelonLogger.Log("ID request: " + idrqm.namePath);
                var obj = BWUtil.GetObjectFromFullPath(idrqm.namePath);

                SetupSyncFor(obj, idrqm.initialOwner);
                break;
            }

            case MessageType.ChangeObjectOwnership:
            {
                var coom = new ChangeObjectOwnershipMessage(msg);

                if (coom.ownerId != smallPlayerIds[connection.ConnectedTo] && coom.ownerId != 0)
                {
                    MelonLogger.LogError("Invalid object ownership change??");
                }

                if (!ObjectIDManager.objects.ContainsKey(coom.objectId))
                {
                    MelonLogger.LogError($"Got ownership change for invalid object ID {coom.objectId}");
                }

                MelonLogger.Log($"Object {coom.objectId} is now owned by {coom.ownerId}");

                var obj = ObjectIDManager.GetObject(coom.objectId);
                var so  = obj.GetComponent <SyncedObject>();
                so.owner = coom.ownerId;

                if (so.owner != 0)
                {
                    coom.linVelocity  = so.rb.velocity;
                    coom.angVelocity  = so.rb.angularVelocity;
                    so.rb.isKinematic = true;
                }
                else if (so.owner == 0)
                {
                    so.rb.isKinematic     = false;
                    so.rb.velocity        = coom.linVelocity;
                    so.rb.angularVelocity = coom.angVelocity;
                }

                ServerSendToAll(coom, MessageSendType.Reliable);
                break;
            }

            case MessageType.ObjectSync:
            {
                ObjectSyncMessage osm = new ObjectSyncMessage(msg);
                GameObject        obj = ObjectIDManager.GetObject(osm.id);

                var so = obj.GetComponent <SyncedObject>();

                if (!obj)
                {
                    MelonLogger.LogError($"Couldn't find object with ID {osm.id}");
                }
                else
                {
                    if (so.owner != smallPlayerIds[connection.ConnectedTo])
                    {
                        MelonLogger.LogError("Got object sync from client that doesn't own the object");
                    }
                    else
                    {
                        obj.transform.position = osm.position;
                        obj.transform.rotation = osm.rotation;

                        ServerSendToAllExcept(osm, MessageSendType.Reliable, connection.ConnectedTo);
                    }
                }

                break;
            }

            default:
                MelonLogger.Log("Unknown message type: " + type.ToString());
                break;
            }
        }
Example #19
0
        private void TransportLayer_OnMessageReceived(ITransportConnection arg1, P2PMessage msg)
        {
            MessageType type = (MessageType)msg.ReadByte();

            try
            {
                switch (type)
                {
                case MessageType.GunFire:
                {
                    GunFireMessageOther gfmo          = new GunFireMessageOther(msg);
                    PlayerRep           pr            = GetPlayerRep(gfmo.playerId);
                    AmmoVariables       ammoVariables = new AmmoVariables()
                    {
                        AttackDamage   = gfmo.ammoDamage,
                        AttackType     = AttackType.Piercing,
                        cartridgeType  = Cart.Cal_9mm,
                        ExitVelocity   = gfmo.exitVelocity,
                        ProjectileMass = gfmo.projectileMass,
                        Tracer         = false
                    };
                    if ((StressLevelZero.Handedness)gfmo.handedness == StressLevelZero.Handedness.RIGHT)
                    {
                        pr.rightGunScript.firePointTransform.position = gfmo.firepointPos;
                        pr.rightGunScript.firePointTransform.rotation = gfmo.firepointRotation;
                        pr.rightGunScript.muzzleVelocity   = gfmo.muzzleVelocity;
                        pr.rightBulletObject.ammoVariables = ammoVariables;
                        pr.rightGunScript.PullCartridge();
                        pr.rightGunScript.Fire();
                    }
                    if ((StressLevelZero.Handedness)gfmo.handedness == StressLevelZero.Handedness.LEFT)
                    {
                        pr.leftGunScript.firePointTransform.position = gfmo.firepointPos;
                        pr.leftGunScript.firePointTransform.rotation = gfmo.firepointRotation;
                        pr.leftGunScript.muzzleVelocity   = gfmo.muzzleVelocity;
                        pr.leftBulletObject.ammoVariables = ammoVariables;
                        pr.leftGunScript.PullCartridge();
                        pr.leftGunScript.Fire();
                    }
                    pr.faceAnimator.faceState = Source.Representations.FaceAnimator.FaceState.Angry;
                    pr.faceAnimator.faceTime  = 5;
                    break;
                }

                case MessageType.OtherPlayerPosition:
                {
                    OtherPlayerPositionMessage oppm = new OtherPlayerPositionMessage(msg);

                    if (playerObjects.ContainsKey(oppm.playerId))
                    {
                        PlayerRep pr = GetPlayerRep(oppm.playerId);

                        pr.head.transform.position   = oppm.headPos;
                        pr.handL.transform.position  = oppm.lHandPos;
                        pr.handR.transform.position  = oppm.rHandPos;
                        pr.pelvis.transform.position = oppm.pelvisPos;
                        pr.ford.transform.position   = oppm.pelvisPos - new Vector3(0.0f, 0.3f, 0.0f);
                        pr.footL.transform.position  = oppm.lFootPos;
                        pr.footR.transform.position  = oppm.rFootPos;

                        pr.head.transform.rotation   = oppm.headRot;
                        pr.handL.transform.rotation  = oppm.lHandRot;
                        pr.handR.transform.rotation  = oppm.rHandRot;
                        pr.pelvis.transform.rotation = oppm.pelvisRot;
                        pr.footL.transform.rotation  = oppm.lFootRot;
                        pr.footR.transform.rotation  = oppm.rFootRot;
                    }

                    break;
                }

                case MessageType.OtherFullRig:
                {
                    OtherFullRigTransformMessage ofrtm = new OtherFullRigTransformMessage(msg);
                    byte playerId = ofrtm.playerId;

                    if (playerObjects.ContainsKey(ofrtm.playerId))
                    {
                        PlayerRep pr = GetPlayerRep(playerId);

                        pr.ApplyTransformMessage(ofrtm);
                    }
                    break;
                }

                case MessageType.ServerShutdown:
                {
                    foreach (PlayerRep pr in playerObjects.Values)
                    {
                        pr.Delete();
                    }
                    break;
                }

                case MessageType.Disconnect:
                {
                    byte pid = msg.ReadByte();
                    playerObjects[pid].Delete();
                    playerObjects.Remove(pid);
                    largePlayerIds.Remove(pid);
                    playerNames.Remove(pid);

                    foreach (PlayerRep pr in playerObjects.Values)
                    {
                        pr.faceAnimator.faceState = Source.Representations.FaceAnimator.FaceState.Sad;
                        pr.faceAnimator.faceTime  = 10;
                    }
                    break;
                }

                case MessageType.JoinRejected:
                {
                    MelonLogger.LogError("Join rejected - you are using an incompatible version of the mod!");
                    Disconnect();
                    break;
                }

                case MessageType.SceneTransition:
                {
                    SceneTransitionMessage stm = new SceneTransitionMessage(msg);
                    if (BoneworksSceneManager.GetCurrentSceneName() != stm.sceneName)
                    {
                        BoneworksSceneManager.LoadScene(stm.sceneName);
                    }
                    break;
                }

                case MessageType.Join:
                {
                    ClientJoinMessage cjm = new ClientJoinMessage(msg);
                    largePlayerIds.Add(cjm.playerId, cjm.steamId);
                    playerNames.Add(cjm.playerId, cjm.name);
                    playerObjects.Add(cjm.playerId, new PlayerRep(cjm.name, cjm.steamId));

                    foreach (PlayerRep pr in playerObjects.Values)
                    {
                        pr.faceAnimator.faceState = Source.Representations.FaceAnimator.FaceState.Happy;
                        pr.faceAnimator.faceTime  = 15;
                    }
                    break;
                }

                case MessageType.SetPartyId:
                {
                    SetPartyIdMessage spid = new SetPartyIdMessage(msg);
                    RichPresence.SetActivity(
                        new Activity()
                        {
                            Details = "Connected to a server",
                            Secrets = new ActivitySecrets()
                            {
                                Join = ServerId.ToString()
                            },
                            Party = new ActivityParty()
                            {
                                Id   = spid.partyId,
                                Size = new PartySize()
                                {
                                    CurrentSize = 1,
                                    MaxSize     = MultiplayerMod.MAX_PLAYERS
                                }
                            }
                        });
                    break;
                }

                case MessageType.EnemyRigTransform:
                {
                    enemyPoolManager.FindMissingPools();
                    EnemyRigTransformMessage ertm = new EnemyRigTransformMessage(msg);
                    Pool pool = enemyPoolManager.GetPool(ertm.enemyType);

                    // HORRID PERFORMANCE
                    Transform              enemyTf = pool.transform.GetChild(ertm.poolChildIdx);
                    GameObject             rootObj = enemyTf.Find("enemyBrett@neutral").gameObject;
                    BoneworksRigTransforms brt     = BWUtil.GetHumanoidRigTransforms(rootObj);
                    BWUtil.ApplyRigTransform(brt, ertm);
                    break;
                }

                case MessageType.IdAllocation:
                {
                    IDAllocationMessage iam = new IDAllocationMessage(msg);
                    GameObject          obj = BWUtil.GetObjectFromFullPath(iam.namePath);
                    if (!obj)
                    {
                        MelonLogger.LogWarning("Got IdAllocation for nonexistent object???");
                    }
                    ObjectIDManager.AddObject(iam.allocatedId, obj);

                    var so = obj.AddComponent <SyncedObject>();
                    so.ID    = iam.allocatedId;
                    so.owner = iam.initialOwner;
                    so.rb    = obj.GetComponent <Rigidbody>();

                    syncedObjects.Add(so);

                    if (so.owner != localSmallId)
                    {
                        so.rb.isKinematic = true;
                    }

                    MelonLogger.Log($"ID Allocation: {iam.namePath}, {so.ID}");
                    break;
                }

                case MessageType.ObjectSync:
                {
                    ObjectSyncMessage osm = new ObjectSyncMessage(msg);
                    GameObject        obj = ObjectIDManager.GetObject(osm.id);

                    if (!obj)
                    {
                        MelonLogger.LogError($"Couldn't find object with ID {osm.id}");
                    }
                    else
                    {
                        obj.transform.position = osm.position;
                        obj.transform.rotation = osm.rotation;
                    }
                    break;
                }

                case MessageType.ChangeObjectOwnership:
                {
                    var coom = new ChangeObjectOwnershipMessage(msg);
                    var obj  = ObjectIDManager.GetObject(coom.objectId);
                    var so   = obj.GetComponent <SyncedObject>();
                    so.owner = coom.ownerId;

                    if (so.owner == localSmallId)
                    {
                        so.rb.isKinematic     = false;
                        so.rb.velocity        = coom.linVelocity;
                        so.rb.angularVelocity = coom.angVelocity;
                    }
                    else
                    {
                        so.rb.isKinematic = true;
                    }

                    MelonLogger.Log($"Object {coom.objectId} is now owned by {coom.ownerId} (kinematic: {so.rb.isKinematic})");

                    break;
                }

                case MessageType.SetLocalSmallId:
                {
                    var slsi = new SetLocalSmallIdMessage(msg);
                    localSmallId = slsi.smallId;
                    break;
                }
                }
            }
            catch (Exception e)
            {
                MelonLogger.LogError($"Caught exception in message handler for message {type}: {e}");
            }
        }
Example #20
0
 private void PlayerHooks_OnPlayerReleaseObject(GameObject obj)
 {
     MelonLogger.Log($"Released {obj.name}");
 }
        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();
            }
        }
        public override void OnPreferencesSaved()
        {
            MelonLogger.Msg("Applying Preferences");

            loadScreenPrefab = GameObject.Find("UserInterface/MenuContent/Popups/LoadingPopup/LoadingBackground(Clone)");
            var music                = loadScreenPrefab.transform.Find("MenuMusic");
            var spaceSound           = loadScreenPrefab.transform.Find("SpaceSound");
            var cube                 = loadScreenPrefab.transform.Find("SkyCube");
            var particles            = loadScreenPrefab.transform.Find("Stars");
            var warpTunnel           = loadScreenPrefab.transform.Find("Tunnel");
            var logo                 = loadScreenPrefab.transform.Find("VRCLogo");
            var InfoPanel            = GameObject.Find("UserInterface/MenuContent/Popups/LoadingPopup/3DElements/LoadingInfoPanel");
            var originalLoadingAudio = GameObject.Find("/UserInterface/MenuContent/Popups/LoadingPopup/LoadingSound");
            var aprfools             = loadScreenPrefab.transform.Find("meme");

            if (OldLoadingScreenSettings.ModSounds.Value)
            {
                music.gameObject.SetActive(true);
                spaceSound.gameObject.SetActive(true);

                originalLoadingAudio.SetActive(false);
            }
            else
            {
                music.gameObject.SetActive(false);
                spaceSound.gameObject.SetActive(false);

                originalLoadingAudio.SetActive(true);
            }

            if (OldLoadingScreenSettings.WarpTunnel.Value)
            {
                warpTunnel.gameObject.SetActive(true);
            }
            else
            {
                warpTunnel.gameObject.SetActive(false);
            }

            if (OldLoadingScreenSettings.VrcLogo.Value)
            {
                logo.gameObject.SetActive(true);
            }
            else
            {
                logo.gameObject.SetActive(false);
            }

            if (OldLoadingScreenSettings.ShowLoadingMessages.Value)
            {
                InfoPanel.SetActive(true);
            }
            else
            {
                InfoPanel.SetActive(false);
            }

            if (DateTime.Today.Month == 4 && DateTime.Now.Day == 1)
            {
                logo.gameObject.SetActive(false);
                aprfools.gameObject.SetActive(true);
            }
        }
Example #23
0
 public override void OnApplicationStart()
 {
     MelonLogger.Log("BTD6 Discord RPC loaded!");
     discord = new Discord.Discord(778339584408027176, (ulong)CreateFlags.Default);
 }
Example #24
0
 public static void Prefix(Notification __0)
 {
     selectedNotification = __0;
     MelonLogger.Msg("Called patch");
     InviteButton.UpdateText();
 }
Example #25
0
        private static int LoadAndRun(LemonFunc <int> functionToWaitForAsync)
        {
            FolderPath = Path.Combine(MelonUtils.UserDataDirectory, "MelonStartScreen");
            if (!Directory.Exists(FolderPath))
            {
                Directory.CreateDirectory(FolderPath);
            }

            ThemesFolderPath = Path.Combine(FolderPath, "Themes");
            if (!Directory.Exists(ThemesFolderPath))
            {
                Directory.CreateDirectory(ThemesFolderPath);
            }

            UIConfig.Load();
            if (!UIConfig.General.Enabled)
            {
                return(functionToWaitForAsync());
            }

            // We try to resolve all the signatures, which are available for Unity 2018.1.0+
            // If we can't find them (signatures changed or <2018.1.0), then we run the function and return.
            try
            {
                if (!NativeSignatureResolver.Apply())
                {
                    return(functionToWaitForAsync());
                }

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

                MelonDebug.Msg("Initializing Screen Renderer");
                if (!ScreenRenderer.Init())
                {
                    UI.Objects.UI_Object.DisposeOfAll();
                    return(functionToWaitForAsync());
                }
                MelonDebug.Msg("Screen Renderer initialized");

                RegisterMessageCallbacks();

                // Initial render
                ScreenRenderer.Render();
                if (ScreenRenderer.disabled)
                {
                    UI.Objects.UI_Object.DisposeOfAll();
                    return(functionToWaitForAsync());
                }
            }
            catch (Exception e)
            {
                MelonLogger.Error(e);
                UI.Objects.UI_Object.DisposeOfAll();
                return(functionToWaitForAsync());
            }

            initialized = true;

            StartFunction(functionToWaitForAsync);
            MainLoop();

            return(functionRunResult);
        }
Example #26
0
        public override void OnUpdate()
        {
            if (Game.instance == null)
            {
                return;
            }
            if (Game.instance.model == null)
            {
                return;
            }
            if (Game.instance.model.towers == null)
            {
                return;
            }
            if (Util.instance.gameModel == null)
            {
                MelonLogger.LogError("Utils gameModel is null while the game isnt! This isnt good!");
            }

            foreach (var moduleFile in pyMods)
            {
                if (!moduleFile.Value)
                {
                    PyEngine.RunScript(moduleFile.Key);
                }
            }

            foreach (var moduleFile in luaMods)
            {
                if (!moduleFile.Value)
                {
                    LuaEngine.RunScript(moduleFile.Key);
                }
            }

            foreach (var moduleFile in booMods)
            {
                if (!moduleFile.Value)
                {
                    BooEngine.RunScript(moduleFile.Key);
                }
            }

            if (hasRunInit)
            {
                return;
            }

            foreach (var moduleFile in pyMods)
            {
                if (moduleFile.Value)
                {
                    PyEngine.RunScript(moduleFile.Key);
                }
            }

            foreach (var moduleFile in luaMods)
            {
                if (moduleFile.Value)
                {
                    LuaEngine.RunScript(moduleFile.Key);
                }
            }

            foreach (var moduleFile in booMods)
            {
                if (moduleFile.Value)
                {
                    BooEngine.RunScript(moduleFile.Key);
                }
            }

            hasRunInit = true;
        }
Example #27
0
        internal static TowerModel CreateTowerModel(ModTower modTower, int[] tiers)
        {
            TowerModel towerModel;

            try
            {
                towerModel       = modTower.GetDefaultTowerModel().Duplicate();
                towerModel.tiers = tiers;
                towerModel.tier  = tiers.Max();
                towerModel.name  = modTower.TowerId(tiers);
            }
            catch (Exception)
            {
                MelonLogger.Error($"Failed to get base TowerModel for ModTower {modTower.Name}");
                throw;
            }

            // add the names to applied upgrades
            try
            {
                towerModel.appliedUpgrades = modTower.upgrades.Cast <ModUpgrade>()
                                             .Where(modUpgrade => modUpgrade != null && tiers[modUpgrade.Path] >= modUpgrade.Tier)
                                             .Select(modUpgrade => modUpgrade.Id)
                                             .ToArray();
            }
            catch (Exception)
            {
                MelonLogger.Error($"Failed to add appliedUpgrades info to TowerModel {towerModel.name}");
                throw;
            }

            // add the upgrade path models
            try
            {
                var towerTiers = modTower.TowerTiers();

                var modTowerTiers = towerTiers.ToList();
                for (var i = 0; i < modTower.UpgradePaths; i++)
                {
                    var tierMax = modTower.tierMaxes[i];
                    if (tiers[i] < tierMax)
                    {
                        var newTiers = tiers.Duplicate();
                        newTiers[i]++;
                        if (modTower is ModHero && tiers.Sum() == 0)
                        {
                            newTiers[i]++; // level 1 heroes are classified as tier 0 for whatever reason
                        }

                        if (modTowerTiers.Any(t => t.SequenceEqual(newTiers)))
                        {
                            var modUpgrade       = modTower.upgrades[i, newTiers[i] - 1];
                            var upgradePathModel = new UpgradePathModel(modUpgrade.Id, modTower.TowerId(newTiers));
                            towerModel.upgrades = towerModel.upgrades.AddTo(upgradePathModel);
                        }
                    }
                }
            }
            catch (Exception)
            {
                MelonLogger.Error($"Failed to add the UpgradePathModels for TowerModel {towerModel.name}");
                throw;
            }

            // maybe add the paragon upgrade
            try
            {
                if (modTower.ShouldCreateParagon && tiers.Any(i => i == 5))
                {
                    towerModel.paragonUpgrade =
                        new UpgradePathModel(modTower.paragonUpgrade.Id, $"{towerModel.baseId}-Paragon");
                }
            }
            catch (Exception)
            {
                MelonLogger.Error($"Failed to add the Paragon Upgrade for TowerModel {towerModel.name}");
                throw;
            }

            // set the tower's portrait
            try
            {
                var portraitUpgrade = modTower.upgrades.Cast <ModUpgrade>()
                                      .Where(modUpgrade => modUpgrade != null &&
                                             tiers[modUpgrade.Path] >= modUpgrade.Tier &&
                                             modUpgrade.PortraitReference)
                                      .OrderByDescending(modUpgrade => modUpgrade.Tier)
                                      .ThenByDescending(modUpgrade => modUpgrade.Path % 2)
                                      .ThenBy(modUpgrade => modUpgrade.Path)
                                      .FirstOrDefault();
                if (portraitUpgrade != null)
                {
                    var sprite = portraitUpgrade.PortraitReference;
                    if (sprite != null)
                    {
                        towerModel.portrait = sprite;
                    }
                }
            }
            catch (Exception)
            {
                MelonLogger.Error($"Failed to set the Portrait of TowerModel {towerModel.name}");
                throw;
            }

            return(towerModel);
        }
Example #28
0
        public override void OnApplicationStart()
        {
            if (!Directory.Exists("ScriptMods/Python"))
            {
                Directory.CreateDirectory("ScriptMods/Python");
            }

            if (!Directory.Exists("ScriptMods/Lua"))
            {
                Directory.CreateDirectory("ScriptMods/Lua");
            }

            if (!Directory.Exists("ScriptMods/Boo"))
            {
                Directory.CreateDirectory("ScriptMods/Boo");
            }

            if (Directory.Exists("PyMods"))
            {
                foreach (var moduleFile in Directory.GetFiles("PyMods", "*.py"))
                {
                    File.Create("ScriptMods/Python/" + moduleFile.Replace("PyMods/", ""));
                    File.WriteAllBytes("ScriptMods/Python/" + moduleFile.Replace("PyMods/", ""), File.ReadAllBytes(moduleFile));
                    File.Delete(moduleFile);
                }
                Directory.Delete("PyMods");
            }

            MelonLogger.Log("");

            foreach (var tmp in requiredDependancies)
            {
                if (!File.Exists("Mods/" + tmp))
                {
                    MelonLogger.Log("DOWNLOADING FILES! AFTER THEY ARE DONE, A MESSAGE WILL APPEAR WITH FURTHER INSTRUCTIONS!");
                    Download();
                    Thread.Sleep(10000);
                    Application.Quit(0);
                    return;
                }
            }


            MelonLogger.Log("Python Mods");
            foreach (var moduleFile in Directory.GetFiles(@"ScriptMods\Python", "*.py"))
            {
                pyMods.Add(File.ReadAllText(moduleFile), moduleFile.Contains("init"));
                MelonLogger.Log(moduleFile + " loaded!");
            }

            MelonLogger.Log("Lua Mods");
            foreach (var moduleFile in Directory.GetFiles(@"ScriptMods\Lua", "*.lua"))
            {
                luaMods.Add(File.ReadAllText(moduleFile), moduleFile.Contains("init"));
                MelonLogger.Log(moduleFile + " loaded!");
            }

            MelonLogger.Log("Boo Mods");
            foreach (var moduleFile in Directory.GetFiles(@"ScriptMods\Boo", "*.boo"))
            {
                booMods.Add(File.ReadAllText(moduleFile), moduleFile.Contains("init"));
                MelonLogger.Log(moduleFile + " loaded!");
            }
        }
Example #29
0
        private void UpdateCameras()
        {
            foreach (var cameraData in _cameras)
            {
                if (cameraData.Camera == null)
                {
                    continue;
                }
                Object.Destroy(cameraData.Camera.gameObject);
            }
            _cameras.Clear();

            var cameraCount = ConfigWatcher.CameraConfigs?.Count ?? 0;

            MelonLogger.Msg($"Creating {cameraCount} cameras");

            for (var i = 0; i < cameraCount; i++)
            {
                // ReSharper disable once PossibleNullReferenceException
                var config = ConfigWatcher.CameraConfigs[i];
                if (config == null)
                {
                    MelonLogger.Warning($"Camera {i} in config is null");
                    continue;
                }

                var child  = new GameObject($"Modded Camera {i}");
                var parent = _cameraParent.transform;
                if (!string.IsNullOrWhiteSpace(config.ParentGameObject))
                {
                    var newParent = GameObject.Find(config.ParentGameObject);
                    if (newParent == null)
                    {
                        MelonLogger.Msg($"Failed to find gameobject '{config.ParentGameObject}'");
                    }
                    else
                    {
                        parent = newParent.transform;
                    }
                }

                for (var j = 0; j < config.ParentAscension; j++)
                {
                    if (parent.parent == null)
                    {
                        MelonLogger.Msg($"Failed to ascend parent {j} times (goal was {config.ParentAscension})");
                        break;
                    }

                    parent = parent.parent;
                }

                child.transform.parent = parent;


                var camera = child.AddComponent <Camera>();
                _cameras.Add(
                    new CameraData
                {
                    Camera = camera,
                    Hold   = config.HoldToToggle,
                    Press  = config.PressToToggle,
                }
                    );

                camera.enabled = config.Enabled;
                child.transform.localPosition = config.LocalPosition;

                if (config.UseRotation)
                {
                    child.transform.localRotation = config.LocalRotation;
                }
                else
                {
                    child.transform.LookAt(
                        _cameraParent.transform,
                        _cameraParent.transform.up
                        );
                }

                if (config.UseAspect)
                {
                    camera.aspect = config.Aspect;
                }

                camera.backgroundColor  = config.BackgroundColor;
                camera.clearFlags       = config.ClearFlags;
                camera.depth            = config.Depth;
                camera.farClipPlane     = config.FarClipPlane;
                camera.nearClipPlane    = config.NearClipPlane;
                camera.orthographic     = config.Orthographic;
                camera.orthographicSize = config.OrthographicSize;
                camera.rect             = config.Rect;
                camera.cullingMask      = (int)config.CullingMask;

                camera.eventMask       = 0;
                camera.stereoTargetEye = StereoTargetEyeMask.None;
            }
        }
Example #30
0
        public static void FoxIdle()
        {
            FoxVars.foxanimator.speed = 1.0f;
            // Advance timer till sit / lay / sleep
            FoxVars.idleStateChangeTimer += Time.deltaTime;

            if (FoxVars.idleStateChangeTimer >= FoxVars.timeToSleep && FoxVars.idleStateCounter != 3)
            {
                FoxVars.idleStateCounter = 3;
                FoxVars.foxanimator.Play("Laying to Sleep", 0, 0f);
                MelonLogger.Log("Fox is sleeping");
            }
            else if (FoxVars.idleStateChangeTimer >= FoxVars.timeToLay && FoxVars.idleStateChangeTimer < FoxVars.timeToSleep && FoxVars.idleStateCounter != 2)
            {
                FoxVars.idleStateCounter = 2;
                FoxVars.foxanimator.Play("Seat to Laying", 0, 0f);
                MelonLogger.Log("Fox is laying");
            }
            else if (FoxVars.idleStateChangeTimer >= FoxVars.timeToSit && FoxVars.idleStateChangeTimer < FoxVars.timeToLay && FoxVars.idleStateCounter != 1)
            {
                if (FoxVars.foxanimator.GetCurrentAnimatorStateInfo(FoxVars.foxanimator.GetLayerIndex("Fox")).IsName("Idle 02") || FoxVars.foxanimator.GetCurrentAnimatorStateInfo(FoxVars.foxanimator.GetLayerIndex("Fox")).IsName("Idle 03") || FoxVars.foxanimator.GetCurrentAnimatorStateInfo(FoxVars.foxanimator.GetLayerIndex("Fox")).IsName("Idle04") || FoxVars.foxanimator.GetCurrentAnimatorStateInfo(FoxVars.foxanimator.GetLayerIndex("Fox")).IsName("Dig"))
                {
                    // Animation is overlapping with one already playing! Not changing
                }
                else
                {
                    FoxVars.idleStateCounter = 1;
                    FoxVars.foxanimator.Play("Stand to Seat", 0, 0f);
                    MelonLogger.Log("Fox is sitting");
                }
            }
            else if (FoxVars.idleStateChangeTimer > FoxVars.timeToIdle && FoxVars.idleStateChangeTimer < FoxVars.timeToSit && FoxVars.idleStateCounter == 0)
            {
                FoxVars.idleChangeTimer += Time.deltaTime;
                //MelonLogger.Log("Fox is idle");

                if (FoxVars.idleChangeTimer > FoxVars.idlechangeTime)
                {
                    if (FoxVars.foxanimator.GetCurrentAnimatorStateInfo(FoxVars.foxanimator.GetLayerIndex("Fox")).IsName("Idle 02") || FoxVars.foxanimator.GetCurrentAnimatorStateInfo(FoxVars.foxanimator.GetLayerIndex("Fox")).IsName("Idle 03") || FoxVars.foxanimator.GetCurrentAnimatorStateInfo(FoxVars.foxanimator.GetLayerIndex("Fox")).IsName("Idle04") || FoxVars.foxanimator.GetCurrentAnimatorStateInfo(FoxVars.foxanimator.GetLayerIndex("Fox")).IsName("Dig"))
                    {
                        // Animation is overlapping with one already playing! Not changing
                    }
                    else
                    {
                        //MelonLogger.Log("Fox is changing idle anim");
                        switch (FoxVars.idleRand)
                        {
                        case 1:
                            //foxanimator.Play("Idle 01", 0, 0f);   // Don't play standard idle again
                            break;

                        case 2:
                            FoxVars.foxanimator.Play("Idle 02", 0, 0f);
                            break;

                        case 3:
                            FoxVars.foxanimator.Play("Idle 03", 0, 0f);
                            break;

                        case 4:
                            FoxVars.foxanimator.Play("Idle04", 0, 0f);
                            break;

                        case 5:
                            FoxVars.foxanimator.Play("Dig", 0, 0f);
                            break;

                        default:
                            // Do nothing :)
                            break;
                        }
                        FoxVars.idleChangeTimer = 0;
                    }
                }
                FoxVars.idleStateCounter = 0;
            }
        }