Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MySix UniqueItems v1.0.3
MySix.UniqueItems.dll
Decompiled 8 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using MySix.Core; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] namespace MySix { internal static class SuiteVersion { public const string Value = "1.0.3"; } } namespace MySix.UniqueItems { public class UniqueItems { public const string FeatureName = "UniqueItems"; private readonly Setting<string> _extraPrefabs; private readonly Setting<bool> _startClockForOldPicks; private readonly HashSet<int> _pickupPrefabHashes = new HashSet<int>(); private readonly HashSet<string> _ordinaryPickups = new HashSet<string>(); private readonly List<string> _locationNames = new List<string>(); private int _clocksStarted; private bool _firstPassDone; public bool Applied { get; private set; } public IEnumerable<string> Pickups => UniqueTargets.Pickups; public IEnumerable<string> Spawners => UniqueTargets.Spawners; public int UniqueLocations => _locationNames.Count; public int ClocksStarted => _clocksStarted; public bool StartClockForOldPicks => _startClockForOldPicks.Value; public UniqueItems(ConfigFile config) { UniqueTargets.Enabled = Settings.Register<bool>("UniqueItems", config.Bind<bool>("UniqueItems", "Enabled", true, "One-of-a-kind pickups and creatures inside unique world locations come back after a while, so every player can have them."), (Scope)0, (string)null); UniqueTargets.Minutes = Settings.Register<float>("UniqueItems", config.Bind<float>("UniqueItems", "RespawnMinutes", 30f, "How long, in minutes of in-game time, before one of them comes back. One game day is 30 minutes."), (Scope)0, (string)null); UniqueTargets.CoverSpawners = Settings.Register<bool>("UniqueItems", config.Bind<bool>("UniqueItems", "CoverSpawners", true, "Also bring back the one-off creatures of those locations, such as Lord Reto, and not only the pickups."), (Scope)0, (string)null); _extraPrefabs = Settings.Register<string>("UniqueItems", config.Bind<string>("UniqueItems", "ExtraPrefabs", "", "Extra pickup or spawner names to treat as one-of-a-kind, separated by commas. Only needed for something the game's location list does not cover."), (Scope)0, (string)null); _startClockForOldPicks = Settings.Register<bool>("UniqueItems", config.Bind<bool>("UniqueItems", "StartClockForOldPicks", false, "On the machine that owns the world, start the respawn clock for pickups taken before this mod was installed, instead of waiting until a player next visits them. Costs one pass over the world."), (Scope)0, (string)null); } public void Apply() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) UniqueTargets.Pickups.Clear(); UniqueTargets.Spawners.Clear(); _pickupPrefabHashes.Clear(); _ordinaryPickups.Clear(); _locationNames.Clear(); _clocksStarted = 0; _firstPassDone = false; Applied = true; if (!UniqueTargets.Enabled.Value) { CorePlugin.Log.LogInfo((object)"UniqueItems: disabled"); return; } Stopwatch stopwatch = Stopwatch.StartNew(); foreach (ZoneLocation location in ZoneSystem.instance.m_locations) { if (location.m_enable && location.m_prefab.IsValid && (location.m_unique || location.m_quantity == 1)) { _locationNames.Add(location.m_prefabName + (location.m_unique ? "" : " (quantity 1)")); location.m_prefab.Load(); GameObject asset = location.m_prefab.Asset; if ((Object)(object)asset == (Object)null) { CorePlugin.Log.LogWarning((object)("UniqueItems: could not load the prefab for location " + location.m_prefabName)); } else { Collect(asset, location.m_prefabName); } location.m_prefab.Release(); } } foreach (string item in from n in _extraPrefabs.Value.Split(new char[1] { ',' }) select n.Trim() into n where n.Length > 0 select n) { UniqueTargets.Pickups.Add(item); UniqueTargets.Spawners.Add(item); } foreach (string pickup in UniqueTargets.Pickups) { _pickupPrefabHashes.Add(StringExtensionMethods.GetStableHashCode(pickup)); } CorePlugin.Log.LogInfo((object)($"UniqueItems: {_locationNames.Count} one-per-world locations hold {UniqueTargets.Pickups.Count} one-of-a-kind " + $"pickups and {UniqueTargets.Spawners.Count} creature spawners that vanilla never brings back; they return after " + $"{UniqueTargets.RespawnMinutes:0} minutes of game time (location list read in {stopwatch.ElapsedMilliseconds} ms)")); CorePlugin.Log.LogInfo((object)("UniqueItems: locations: " + string.Join(", ", _locationNames.OrderBy<string, string>((string n) => n, StringComparer.Ordinal).ToArray()))); CorePlugin.Log.LogInfo((object)("UniqueItems: pickups: " + Join(UniqueTargets.Pickups))); CorePlugin.Log.LogInfo((object)("UniqueItems: ordinary loot left alone: " + Join(_ordinaryPickups))); CorePlugin.Log.LogInfo((object)((UniqueTargets.CoverSpawners.Value ? "UniqueItems: spawners: " : "UniqueItems: spawners, left as the game has them because CoverSpawners is off: ") + Join(UniqueTargets.Spawners))); } private void Collect(GameObject locationAsset, string locationName) { Pickable[] componentsInChildren = locationAsset.GetComponentsInChildren<Pickable>(true); foreach (Pickable val in componentsInChildren) { if (val.m_respawnTimeMinutes > 0f) { continue; } string prefabName = Utils.GetPrefabName(((Component)val).gameObject); if (IsOneOfAKind(val, out var items)) { if (UniqueTargets.Pickups.Add(prefabName)) { CorePlugin.Log.LogInfo((object)("UniqueItems: " + prefabName + " in " + locationName + " gives " + items + " and never comes back in vanilla")); } } else if (_ordinaryPickups.Add(prefabName)) { CorePlugin.Log.LogInfo((object)("UniqueItems: " + prefabName + " in " + locationName + " left as the game has it; it gives " + items)); } } CreatureSpawner[] componentsInChildren2 = locationAsset.GetComponentsInChildren<CreatureSpawner>(true); foreach (CreatureSpawner obj in componentsInChildren2) { string prefabName2 = Utils.GetPrefabName(((Component)obj).gameObject); if (obj.m_respawnTimeMinuts <= 0f && UniqueTargets.Spawners.Add(prefabName2)) { CorePlugin.Log.LogInfo((object)("UniqueItems: " + prefabName2 + " in " + locationName + " never spawns twice in vanilla")); } } } private static bool IsOneOfAKind(Pickable pickup, out string items) { List<string> list = new List<string>(); bool flag = false; foreach (GameObject item in ItemsGiven(pickup)) { ItemDrop component = item.GetComponent<ItemDrop>(); SharedData val = (((Object)(object)component == (Object)null) ? null : component.m_itemData.m_shared); if (val != null) { list.Add($"{Utils.GetPrefabName(item)} (quest item: {val.m_questItem}, stacks to {val.m_maxStackSize})"); flag |= val.m_questItem || val.m_maxStackSize <= 1; } } items = ((list.Count > 0) ? string.Join(" + ", list.ToArray()) : "no item this mod can read"); return flag; } private static IEnumerable<GameObject> ItemsGiven(Pickable pickup) { if ((Object)(object)pickup.m_itemPrefab != (Object)null) { yield return pickup.m_itemPrefab; } if (pickup.m_extraDrops == null || pickup.m_extraDrops.m_drops == null) { yield break; } foreach (DropData drop in pickup.m_extraDrops.m_drops) { if ((Object)(object)drop.m_item != (Object)null) { yield return drop.m_item; } } } public void StartClockIfPickedLongAgo(ZDO zdo, int prefabHash) { if (!_firstPassDone && _pickupPrefabHashes.Contains(prefabHash) && zdo.GetBool(ZDOVars.s_picked, false) && zdo.GetLong(ZDOVars.s_pickedTime, 0L) <= 1 && (!zdo.HasOwner() || zdo.IsOwner()) && Compat.TakeOwnership(zdo)) { zdo.Set(ZDOVars.s_pickedTime, ZNet.instance.GetTime().Ticks); zdo.SetOwner(0L); _clocksStarted++; } } public void EndPass() { if (!_firstPassDone) { _firstPassDone = true; if (_clocksStarted > 0) { CorePlugin.Log.LogInfo((object)$"UniqueItems: started the respawn clock on {_clocksStarted} pickup(s) taken before this mod was installed"); } } } private static string Join(IEnumerable<string> names) { return string.Join(", ", names.OrderBy<string, string>((string n) => n, StringComparer.Ordinal).ToArray()); } } internal static class UniqueTargets { internal static Setting<bool> Enabled; internal static Setting<float> Minutes; internal static Setting<bool> CoverSpawners; internal static readonly HashSet<string> Pickups = new HashSet<string>(); internal static readonly HashSet<string> Spawners = new HashSet<string>(); internal static float RespawnMinutes => Math.Max(1f, Minutes.Value); internal static bool IsUniquePickup(string objectName) { if (Enabled.Value) { return Pickups.Contains(Utils.GetPrefabName(objectName)); } return false; } internal static bool IsUniqueSpawner(string objectName) { if (Enabled.Value && CoverSpawners.Value) { return Spawners.Contains(Utils.GetPrefabName(objectName)); } return false; } } [HarmonyPatch(typeof(Pickable), "Awake")] internal static class PickableAwakePatch { private static void Prefix(Pickable __instance) { if (__instance.m_respawnTimeMinutes <= 0f && UniqueTargets.IsUniquePickup(((Object)__instance).name)) { __instance.m_respawnTimeMinutes = UniqueTargets.RespawnMinutes; } } } [HarmonyPatch(typeof(CreatureSpawner), "Awake")] internal static class CreatureSpawnerAwakePatch { private static void Prefix(CreatureSpawner __instance) { if (__instance.m_respawnTimeMinuts <= 0f && UniqueTargets.IsUniqueSpawner(((Object)__instance).name)) { __instance.m_respawnTimeMinuts = UniqueTargets.RespawnMinutes; } } } [HarmonyPatch(typeof(ZoneSystem), "Start")] internal static class ZoneSystemStartPatch { private static void Postfix() { UniqueItemsPlugin.Feature.Apply(); } } [BepInPlugin("com.mysix.uniqueitems", "MySix Unique Items", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class UniqueItemsPlugin : BaseUnityPlugin, IWorldScanConsumer { public const string PluginGuid = "com.mysix.uniqueitems"; public const string PluginName = "MySix Unique Items"; public const string PluginVersion = "1.0.3"; private const int RequiredCoreApi = 1; private Harmony _harmony; public static UniqueItems Feature { get; private set; } private void Awake() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown if (!CorePlugin.RequireApi("MySix Unique Items", 1)) { return; } Feature = new UniqueItems(((BaseUnityPlugin)this).Config); CorePlugin.Ready += delegate { if (CorePlugin.IsServerSide && Feature.StartClockForOldPicks) { CorePlugin.Instance.Scanner.Add((IWorldScanConsumer)(object)this); } }; _harmony = new Harmony("com.mysix.uniqueitems"); _harmony.PatchAll(typeof(UniqueItemsPlugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"MySix Unique Items 1.0.3 loaded"); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } public void BeginPass() { } public void Visit(ZDO zdo, int prefabHash) { Feature.StartClockIfPickedLongAgo(zdo, prefabHash); } public void EndPass(float realtimeNow) { Feature.EndPass(); } } }