using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using AnarchyBox; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("AnarchyBox")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("3.0.0.0")] [assembly: AssemblyInformationalVersion("3.0.0")] [assembly: AssemblyProduct("AnarchyBox")] [assembly: AssemblyTitle("AnarchyBox")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.0.0.0")] [module: UnverifiableCode] [HarmonyPatch(typeof(ValuableDirector), "SetupHost")] public class ResetPatch { private static void Prefix() { Plugin.ResetRoll(); } } namespace AnarchyBox { [BepInPlugin("anarchy.box", "AnarchyBox", "3.0.0")] public class Plugin : BaseUnityPlugin { public struct SpawnResetPrefixState { public List[] _volumes; public int[] _volumeIndex; public ValuableDirector __instance; } internal static ManualLogSource Log; private static int forcedCount; private Harmony harmony; public static ConfigEntry maxAttemptsConfig; public static ConfigEntry forcedSuccessConfig; public static ConfigEntry commonWeightConfig; public static ConfigEntry uncommonWeightConfig; public static ConfigEntry rareWeightConfig; public static ConfigEntry ultraRareWeightConfig; public static ConfigEntry preventStackingConfig; public static ConfigEntry resetRotationKeyConfig; private bool isRotationLocked; private RigidbodyConstraints originalConstraints; private Rigidbody lockedRigidbody; private PhysGrabObject lastLockedObject; private static bool suppressLoopsClampedGetPostfix; private static readonly FieldInfo targetAmountField; private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Expected O, but got Unknown //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Expected O, but got Unknown //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Expected O, but got Unknown //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Expected O, but got Unknown //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; harmony = new Harmony("anarchy.box"); maxAttemptsConfig = ((BaseUnityPlugin)this).Config.Bind("General", "Max Attempts", 25, new ConfigDescription("The maximum attempts for cosmetic loops", (AcceptableValueBase)(object)new AcceptableValueRange(1, 100), Array.Empty())); forcedSuccessConfig = ((BaseUnityPlugin)this).Config.Bind("General", "Forced Successes", 15, new ConfigDescription("How many box successes to force", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); preventStackingConfig = ((BaseUnityPlugin)this).Config.Bind("General", "Prevent Stacking", true, new ConfigDescription("If enabled, boxes will not spawn on occupied points if all unique locations are taken. Highly recommended for multiplayer to avoid crashes!", (AcceptableValueBase)null, Array.Empty())); commonWeightConfig = ((BaseUnityPlugin)this).Config.Bind("Rarity Weights", "Common Weight", 60, new ConfigDescription("Weight of Common boxes.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); uncommonWeightConfig = ((BaseUnityPlugin)this).Config.Bind("Rarity Weights", "Uncommon Weight", 25, new ConfigDescription("Weight of Uncommon boxes.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); rareWeightConfig = ((BaseUnityPlugin)this).Config.Bind("Rarity Weights", "Epic Weight", 12, new ConfigDescription("Weight of Rare boxes.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ultraRareWeightConfig = ((BaseUnityPlugin)this).Config.Bind("Rarity Weights", "Legendary Weight", 3, new ConfigDescription("Weight of Ultra Rare boxes.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); resetRotationKeyConfig = ((BaseUnityPlugin)this).Config.Bind("Controls", "Reset Rotation Key", (KeyCode)114, new ConfigDescription("Key to reset the rotation of the held box", (AcceptableValueBase)null, Array.Empty())); ((BaseUnityPlugin)this).Config.Save(); Type type = typeof(ValuableDirector).GetNestedTypes(BindingFlags.NonPublic).FirstOrDefault((Type t) => t.Name.Contains("SetupHost")); if (type == null) { Log.LogError((object)"Could not find the compiler-generated enumerator type for SetupHost. Transpiler patch aborted!"); return; } harmony.Patch((MethodBase)AccessTools.Method(typeof(ValuableDirector), "SetupHost", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "ResetRoll", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "SetupHostTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ValuableDirector), "CosmeticWorldObjectLevelLoopsClampedGet", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "LoopsClampedGetPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo = AccessTools.Method(typeof(CosmeticWorldObject), "ExtractRPC", (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ExtractRpcTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); } else { Log.LogError((object)"Could not find CosmeticWorldObject.ExtractRPC! Extraction stability patch skipped."); } harmony.Patch((MethodBase)AccessTools.Method(typeof(ValuableDirector), "SpawnCosmeticWorldObject", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.Method(typeof(Plugin), "SpawnResetPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"AnarchyBox loaded! v3.0.0"); } public static int GuaranteedRoll(int min, int max) { if (forcedCount < forcedSuccessConfig.Value) { forcedCount++; Log.LogInfo((object)$"Forcing box success #{forcedCount}"); return 0; } return Random.Range(min, max); } private static IEnumerable SetupHostTranspiler(IEnumerable instructions) { List list = new List(instructions); MethodInfo methodInfo = AccessTools.Method(typeof(Random), "Range", new Type[2] { typeof(int), typeof(int) }, (Type[])null); MethodInfo operand = AccessTools.Method(typeof(Plugin), "GuaranteedRoll", (Type[])null, (Type[])null); bool flag = false; for (int i = 0; i < list.Count - 2; i++) { if (list[i].opcode == OpCodes.Ldc_I4_0 && (list[i + 1].opcode == OpCodes.Ldc_I4_S || list[i + 1].opcode == OpCodes.Ldc_I4) && Convert.ToInt32(list[i + 1].operand) == 100 && CodeInstructionExtensions.Calls(list[i + 2], methodInfo)) { list[i + 2].operand = operand; flag = true; break; } } if (flag) { Log.LogInfo((object)"SetupHostTranspiler: Patched Random.Range"); } return list; } public static void ResetRoll() { if (SemiFunc.IsMasterClientOrSingleplayer()) { forcedCount = 0; Log.LogInfo((object)"Reset anarchy counter on Host"); } } public static Rarity PickRarity() { int num = commonWeightConfig.Value + uncommonWeightConfig.Value + rareWeightConfig.Value + ultraRareWeightConfig.Value; if (num > 0) { int num2 = Random.Range(0, num); if (num2 >= commonWeightConfig.Value) { num2 -= commonWeightConfig.Value; if (num2 >= uncommonWeightConfig.Value) { num2 -= uncommonWeightConfig.Value; if (num2 < rareWeightConfig.Value) { return (Rarity)2; } return (Rarity)3; } return (Rarity)1; } return (Rarity)0; } return (Rarity)0; } public static bool SpawnResetPrefix(int[] _volumeIndex, List[] _volumes, ref Rarity _cosmeticRarity, ValuableDirector __instance) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected I4, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected I4, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected I4, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected I4, but got Unknown SpawnResetPrefixState A_ = default(SpawnResetPrefixState); A_._volumes = _volumes; A_._volumeIndex = _volumeIndex; A_.__instance = __instance; if (!SemiFunc.IsMasterClientOrSingleplayer()) { return true; } Rarity val = _cosmeticRarity; _cosmeticRarity = (Rarity)(int)PickRarity(); if (A_.__instance.cosmeticWorldObjectSetups == null || (int)_cosmeticRarity >= A_.__instance.cosmeticWorldObjectSetups.Count) { Log.LogError((object)$"Rarity index {(int)_cosmeticRarity} is out of bounds for cosmeticWorldObjectSetups!"); return true; } if (preventStackingConfig.Value) { if (!HasAvailableVolume(_cosmeticRarity, ref A_)) { if (TryFindAvailableRarity(out var rarity, ref A_)) { Log.LogInfo((object)$"Prevented stacking: redirected spawn from rarity {_cosmeticRarity} to alternative rarity {rarity} with free slots."); _cosmeticRarity = (Rarity)(int)rarity; } else { Log.LogWarning((object)"Prevented stacking failed: ALL spawn slots are completely occupied! Stacking is forced to avoid infinite loading screens."); int num = (int)A_.__instance.cosmeticWorldObjectSetups[(int)_cosmeticRarity].volume; if (A_._volumeIndex != null && num < A_._volumeIndex.Length) { A_._volumeIndex[num] = 0; } } } } else { int num2 = (int)A_.__instance.cosmeticWorldObjectSetups[(int)_cosmeticRarity].volume; if (A_._volumes != null && num2 < A_._volumes.Length && A_._volumeIndex != null && num2 < A_._volumeIndex.Length && A_._volumeIndex[num2] >= A_._volumes[num2].Count) { A_._volumeIndex[num2] = 0; Log.LogWarning((object)"Stacking box on old points!"); } } Log.LogInfo((object)$"Box spawn approved on Host: {val} -> {_cosmeticRarity}"); return true; } private void Update() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)PhysGrabber.instance == (Object)null) { ResetLockState(); return; } PhysGrabObject value = Traverse.Create((object)PhysGrabber.instance).Field("grabbedPhysGrabObject").Value; if ((Object)(object)value == (Object)null) { ResetLockState(); return; } if (Input.GetKeyDown(resetRotationKeyConfig.Value)) { isRotationLocked = !isRotationLocked; if (isRotationLocked) { Rigidbody component = ((Component)value).GetComponent(); if ((Object)(object)component != (Object)null) { lockedRigidbody = component; lastLockedObject = value; originalConstraints = component.constraints; component.constraints = (RigidbodyConstraints)112; component.angularVelocity = Vector3.zero; } Log.LogInfo((object)"RL activ"); } else { RestoreOriginalPhysics(); Log.LogInfo((object)"RL deactive"); } } if (!isRotationLocked) { return; } float num = 5f; Quaternion identity = Quaternion.identity; ((Component)value).transform.rotation = Quaternion.Slerp(((Component)value).transform.rotation, identity, Time.deltaTime * num); Rigidbody component2 = ((Component)value).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.rotation = Quaternion.Slerp(component2.rotation, identity, Time.deltaTime * num); component2.angularVelocity = Vector3.zero; component2.constraints = (RigidbodyConstraints)112; } try { Traverse obj = Traverse.Create((object)PhysGrabber.instance); Quaternion value2 = obj.Field("rotation").Value; obj.Field("rotation").SetValue((object)Quaternion.Slerp(value2, identity, Time.deltaTime * num)); object value3 = obj.Field("physGrabPointPuller").GetValue(); if (value3 != null) { Transform val = null; Component val2; GameObject val3; if ((Object)(object)(val2 = (Component)((value3 is Component) ? value3 : null)) != (Object)null && (Object)(object)val2 != (Object)null) { val = val2.transform; } else if ((Object)(object)(val3 = (GameObject)((value3 is GameObject) ? value3 : null)) != (Object)null && (Object)(object)val3 != (Object)null) { val = val3.transform; } if ((Object)(object)val != (Object)null) { val.localRotation = Quaternion.Slerp(val.localRotation, identity, Time.deltaTime * num); } } } catch { } } private void ResetLockState() { if (isRotationLocked) { RestoreOriginalPhysics(); } isRotationLocked = false; lockedRigidbody = null; lastLockedObject = null; } private void RestoreOriginalPhysics() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) try { Rigidbody component = lockedRigidbody; if ((Object)(object)component == (Object)null && (Object)(object)lastLockedObject != (Object)null) { component = ((Component)lastLockedObject).GetComponent(); } if ((Object)(object)component != (Object)null) { component.constraints = originalConstraints; } } catch (Exception ex) { Log.LogWarning((object)("Could not restore original rigidbody constraints: " + ex.Message)); } } private static IEnumerable ExtractRpcTranspiler(IEnumerable instructions) { List list = instructions.ToList(); MethodInfo methodInfo = AccessTools.Method(typeof(ValuableDirector), "CosmeticWorldObjectLevelLoopsClampedGet", (Type[])null, (Type[])null); MethodInfo operand = AccessTools.Method(typeof(Plugin), "CosmeticExtractionLoopLimit", (Type[])null, (Type[])null); List list2 = new List(); for (int i = 0; i < list.Count; i++) { if (CodeInstructionExtensions.Calls(list[i], methodInfo)) { list2.Add(i); } } if (list2.Count != 1) { Log.LogError((object)$"Expected exactly one CosmeticWorldObjectLevelLoopsClampedGet call in CosmeticWorldObject.ExtractRPC, found {list2.Count}. Extraction patch skipped."); return instructions; } list[list2[0]].opcode = OpCodes.Call; list[list2[0]].operand = operand; Log.LogInfo((object)"Patched CosmeticWorldObject.ExtractRPC cosmetic extraction loop limit."); return list; } public static int CosmeticExtractionLoopLimit(ValuableDirector director) { int num = 0; try { if ((Object)(object)director != (Object)null) { suppressLoopsClampedGetPostfix = true; num = director.CosmeticWorldObjectLevelLoopsClampedGet(); } } catch (Exception arg) { Log.LogError((object)$"Failed to read original cosmetic extraction loop limit; using safe fallback. {arg}"); } finally { suppressLoopsClampedGetPostfix = false; } int targetAmount = GetTargetAmount(director); if (targetAmount <= 0) { return num; } return Math.Max(num, targetAmount - 1); } private static int GetTargetAmount(ValuableDirector director) { if ((Object)(object)director == (Object)null || targetAmountField == null || targetAmountField.FieldType != typeof(int)) { return 0; } try { return (int)targetAmountField.GetValue(director); } catch (Exception arg) { Log.LogError((object)$"Failed to read cosmeticWorldObjectTargetAmount. {arg}"); return 0; } } public static void LoopsClampedGetPostfix(ref int __result) { if (!suppressLoopsClampedGetPostfix && SemiFunc.IsMasterClientOrSingleplayer()) { __result = maxAttemptsConfig.Value; } } public static void SyncOnLevelLoad() { if (PhotonNetwork.InRoom) { if (PhotonNetwork.IsMasterClient) { WriteConfigToRoom(); } else { SyncConfigFromRoom(); } } } public static void WriteConfigToRoom() { Log.LogWarning((object)"WriteConfigToRoom stub called!"); } public static void SyncConfigFromRoom() { Log.LogWarning((object)"SyncConfigFromRoom stub called!"); } static Plugin() { suppressLoopsClampedGetPostfix = false; targetAmountField = AccessTools.Field(typeof(ValuableDirector), "cosmeticWorldObjectTargetAmount"); } internal static bool HasAvailableVolume(Rarity rarity, ref SpawnResetPrefixState A_1) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (TryGetVolumeIndexForRarity(rarity, out var volIndex, ref A_1) && A_1._volumes != null && A_1._volumeIndex != null && volIndex >= 0 && volIndex < A_1._volumes.Length && volIndex < A_1._volumeIndex.Length && A_1._volumes[volIndex] != null && A_1._volumeIndex[volIndex] >= 0) { return A_1._volumeIndex[volIndex] < A_1._volumes[volIndex].Count; } return false; } internal static bool TryGetVolumeIndexForRarity(Rarity rarity, out int volIndex, ref SpawnResetPrefixState A_2) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) volIndex = 0; ValuableDirector _instance = A_2.__instance; if ((((Object)(object)_instance != (Object)null) ? _instance.cosmeticWorldObjectSetups : null) == null) { return false; } int num = Convert.ToInt32(rarity); if (num < 0 || num >= A_2.__instance.cosmeticWorldObjectSetups.Count) { return false; } CosmeticWorldObjectSetup val = A_2.__instance.cosmeticWorldObjectSetups[num]; if (val == null) { return false; } volIndex = Convert.ToInt32(val.volume); return true; } internal static bool TryFindAvailableRarity(out Rarity rarity, ref SpawnResetPrefixState A_1) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected I4, but got Unknown ValuableDirector _instance = A_1.__instance; if ((((Object)(object)_instance != (Object)null) ? _instance.cosmeticWorldObjectSetups : null) == null) { rarity = (Rarity)0; return false; } for (int i = 0; i < A_1.__instance.cosmeticWorldObjectSetups.Count; i++) { if (Enum.IsDefined(typeof(Rarity), i) && A_1.__instance.cosmeticWorldObjectSetups[i] != null) { Rarity val = (Rarity)i; if (HasAvailableVolume(val, ref A_1)) { rarity = (Rarity)(int)val; return true; } } } rarity = (Rarity)0; return false; } } public enum SpawnMode { Volume_Offline, All_Offline, AutoLevel_Online } } public enum SpawnMode { Volume_Offline, All_Offline, AutoLevel_Online } namespace AnarchyBox { public enum SpawnMode__0 { Volume_Offline, All_Offline, AutoLevel_Online } } [HarmonyPatch(typeof(ValuableDirector), "SetupHost")] public class ResetPatch__0 { private static void Prefix() { Plugin.ResetRoll(); } } public enum SpawnMode__0 { Volume_Offline, All_Offline, AutoLevel_Online } namespace AnarchyBox { public enum SpawnMode__1 { Volume_Offline, All_Offline, AutoLevel_Online } public enum SpawnMode__0__0 { Volume_Offline, All_Offline, AutoLevel_Online } }