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 DafoertNite Patches v1.2.0
plugins/DafoertNitePatches.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace InventoryHarmonizer { internal static class AutomaticFuelNewContainers { internal const string AutomaticFuelGuid = "TastyChickenLegs.AutomaticFuel"; private static MethodInfo _addContainer; private static FieldInfo _containerList; internal static void Apply(ConfigFile config, Harmony harmony) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown if (HarmonizerPlugin.Loaded("TastyChickenLegs.AutomaticFuel") && config.Bind<bool>("AutomaticFuel + new containers", "Enabled", true, "Let freshly built modded containers supply fuel right away instead of after the area reloads.").Value) { _addContainer = AccessTools.Method("AutomaticFuel.TastyUtils:AddContainer", new Type[2] { typeof(Container), typeof(ZNetView) }, (Type[])null); Type type = AccessTools.TypeByName("AutomaticFuel.AutomaticFuelPlugin"); _containerList = ((type != null) ? AccessTools.Field(type, "ContainerList") : null); MethodInfo methodInfo = AccessTools.Method(typeof(Piece), "SetCreator", (Type[])null, (Type[])null); if (_addContainer == null || _containerList == null || methodInfo == null) { HarmonizerPlugin.Log.LogWarning((object)"AutomaticFuel + new containers: a mod changed internally; this fix is inactive."); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(AutomaticFuelNewContainers), "SetCreatorPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonizerPlugin.Log.LogInfo((object)"AutomaticFuel + new containers: newly built containers supply fuel right away."); } } private static void SetCreatorPostfix(Piece __instance) { Container component = ((Component)__instance).GetComponent<Container>(); if (!((Object)(object)component == (Object)null) && _containerList.GetValue(null) is List<Container> list && !list.Contains(component)) { _addContainer.Invoke(null, new object[2] { component, ((Component)component).GetComponent<ZNetView>() }); } } } internal static class GoblinSoundpack { private sealed class Sound { public ConfigEntry<string> ClipList; public AudioClip[] Clips; public float MinPitch; public float MaxPitch; public float MinVol; public float MaxVol; } internal const string OldModGuid = "dafoertnite.goblins"; private const string Section = "Goblin soundpack"; private static ConfigEntry<bool> _enabled; private static ConfigEntry<bool> _pitchVariation; private static ConfigEntry<string> _excluded; private static ConfigEntry<string> _idleClips; private static ConfigEntry<string> _alertClips; private static ConfigEntry<string> _hitClips; private static ConfigEntry<string> _deathClips; private static ConfigEntry<float> _chance; private static ConfigEntry<float> _cooldown; private static ConfigEntry<float> _idleFrequency; private static ConfigEntry<float> _originalChance; private static readonly Dictionary<string, AudioClip> Clips = new Dictionary<string, AudioClip>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Sound> Sounds = new Dictionary<string, Sound>(); private static readonly Dictionary<string, float> IdleIntervals = new Dictionary<string, float>(StringComparer.Ordinal); private static float _nextAllowed; internal static void Apply(BaseUnityPlugin plugin, ConfigFile config, Harmony harmony) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Expected O, but got Unknown //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Expected O, but got Unknown _enabled = config.Bind<bool>("Goblin soundpack", "Enabled", true, "Goblins have something to say."); _idleClips = config.Bind<string>("Goblin soundpack", "IdleClips", "fortnite.wav*5, laugh.wav*2, goblin-idle.wav*3", "Clips for idle grunts. Comma-separated clip file names from the sounds folder; one is picked at random. Add *N to weight a clip, e.g. fortnite.wav*3 is three times as likely. Empty keeps the normal goblin sound. Changes apply live."); _alertClips = config.Bind<string>("Goblin soundpack", "AlertClips", "fortnite.wav*12, something-of-a-scientist.wav*5, goblin-spotted.wav*3", "Clips when a goblin spots you. Comma-separated clip file names from the sounds folder; one is picked at random. Add *N to weight a clip, e.g. fortnite.wav*3 is three times as likely. Empty keeps the normal goblin sound. Changes apply live."); _hitClips = config.Bind<string>("Goblin soundpack", "HitClips", "fortnite.wav*7, goblin-idle.wav*3", "Clips when a goblin gets hit. Comma-separated clip file names from the sounds folder; one is picked at random. Add *N to weight a clip, e.g. fortnite.wav*3 is three times as likely. Empty keeps the normal goblin sound. Changes apply live."); _deathClips = config.Bind<string>("Goblin soundpack", "DeathClips", "dying.wav*2, goblin-death.wav, skeleton-death.wav", "Clips when a goblin dies. Comma-separated clip file names from the sounds folder; one is picked at random. Add *N to weight a clip, e.g. fortnite.wav*3 is three times as likely. Empty keeps the normal goblin sound. Changes apply live."); _chance = config.Bind<float>("Goblin soundpack", "Chance", 1f, new ConfigDescription("Chance that a goblin sound plays a clip.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); _cooldown = config.Bind<float>("Goblin soundpack", "CooldownSeconds", 0f, new ConfigDescription("Minimum seconds between clips across all goblins.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), Array.Empty<object>())); _originalChance = config.Bind<float>("Goblin soundpack", "OriginalSoundChance", 0f, new ConfigDescription("When a clip can't play (cooldown or Chance), how often the normal goblin sound plays instead; otherwise it stays silent.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); _pitchVariation = config.Bind<bool>("Goblin soundpack", "PitchVariation", true, "Keep the game's random pitch variation on the clips."); _idleFrequency = config.Bind<float>("Goblin soundpack", "IdleSoundFrequency", 2f, new ConfigDescription("How often goblins make idle sounds, relative to normal (2 = twice as often). Applies after a world load.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>())); _excluded = config.Bind<string>("Goblin soundpack", "ExcludedGoblins", "GoblinKing", "Comma-separated creature prefab names starting with \"Goblin\" that are left alone (GoblinKing is Yagluth)."); if (!_enabled.Value) { return; } if (HarmonizerPlugin.Loaded("dafoertnite.goblins")) { HarmonizerPlugin.Log.LogWarning((object)"Goblin soundpack: the old DafoertGoblins mod is installed; remove it. Skipping the soundpack so goblins don't speak twice."); return; } string path = Path.Combine(Path.GetDirectoryName(plugin.Info.Location), "sounds"); if (!Directory.Exists(path)) { HarmonizerPlugin.Log.LogInfo((object)"Goblin soundpack: no sounds folder; goblins sound normal."); return; } string[] files = Directory.GetFiles(path); foreach (string text in files) { if (text.EndsWith(".wav", StringComparison.OrdinalIgnoreCase) || text.EndsWith(".ogg", StringComparison.OrdinalIgnoreCase)) { ((MonoBehaviour)plugin).StartCoroutine(LoadClip(text)); } } harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNetScene), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(GoblinSoundpack), "ScanPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ZSFX), "Play", (Type[])null, (Type[])null), new HarmonyMethod(typeof(GoblinSoundpack), "PlayPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonizerPlugin.Log.LogInfo((object)"Goblin soundpack: active."); } private static IEnumerator LoadClip(string path) { AudioType val = (AudioType)(path.EndsWith(".ogg", StringComparison.OrdinalIgnoreCase) ? 14 : 20); UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, val); try { yield return request.SendWebRequest(); AudioClip val2 = (((int)request.result == 1) ? DownloadHandlerAudioClip.GetContent(request) : null); if ((Object)(object)val2 == (Object)null || val2.length <= 0f) { HarmonizerPlugin.Log.LogError((object)("Goblin soundpack: could not load " + path + " (" + request.error + "). Use WAV or Ogg Vorbis.")); yield break; } string key = (((Object)val2).name = Path.GetFileName(path)); Clips[key] = val2; } finally { ((IDisposable)request)?.Dispose(); } } private static string PrefabName(GameObject go) { return ((Object)go).name.Replace("(Clone)", "").Trim(); } private static bool IsGoblin(GameObject go) { string name = PrefabName(go); if (!name.StartsWith("Goblin", StringComparison.Ordinal) || (Object)(object)go.GetComponent<BaseAI>() == (Object)null) { return false; } return _excluded.Value.Split(',').All((string excluded) => excluded.Trim() != name); } private static void ScanPostfix(ZNetScene __instance) { Sounds.Clear(); int num = 0; foreach (GameObject prefab in __instance.m_prefabs) { if (!((Object)(object)prefab == (Object)null) && IsGoblin(prefab)) { num++; BaseAI component = prefab.GetComponent<BaseAI>(); if (!IdleIntervals.TryGetValue(((Object)prefab).name, out var value)) { value = (IdleIntervals[((Object)prefab).name] = component.m_idleSoundInterval); } component.m_idleSoundInterval = value / Mathf.Max(_idleFrequency.Value, 0.1f); Register(component.m_alertedEffects, _alertClips); Register(component.m_idleSound, _idleClips); Character component2 = prefab.GetComponent<Character>(); if (!((Object)(object)component2 == (Object)null)) { Register(component2.m_hitEffects, _hitClips); Register(component2.m_deathEffects, _deathClips); } } } HarmonizerPlugin.Log.LogInfo((object)("Goblin soundpack: " + num + " goblin types, " + Sounds.Count + " sounds replaced, " + Clips.Count + " clips loaded.")); } private static void Register(EffectList effects, ConfigEntry<string> clipList) { if (effects == null || effects.m_effectPrefabs == null) { return; } EffectData[] effectPrefabs = effects.m_effectPrefabs; foreach (EffectData val in effectPrefabs) { if ((Object)(object)val.m_prefab == (Object)null) { continue; } ZSFX[] componentsInChildren = val.m_prefab.GetComponentsInChildren<ZSFX>(true); foreach (ZSFX val2 in componentsInChildren) { if (!Sounds.ContainsKey(((Object)((Component)val2).gameObject).name)) { Sounds[((Object)((Component)val2).gameObject).name] = new Sound { ClipList = clipList, Clips = val2.m_audioClips, MinPitch = val2.m_minPitch, MaxPitch = val2.m_maxPitch, MinVol = val2.m_minVol, MaxVol = val2.m_maxVol }; } } } } private static void PlayPrefix(ZSFX __instance) { if (!_enabled.Value || !Sounds.TryGetValue(PrefabName(((Component)__instance).gameObject), out var value)) { return; } __instance.m_audioClips = value.Clips; __instance.m_minPitch = value.MinPitch; __instance.m_maxPitch = value.MaxPitch; __instance.m_minVol = value.MinVol; __instance.m_maxVol = value.MaxVol; AudioClip val = PickClip(value.ClipList.Value); if ((Object)(object)val == (Object)null) { return; } if (Time.time >= _nextAllowed && Random.value < _chance.Value) { _nextAllowed = Time.time + _cooldown.Value; __instance.m_audioClips = (AudioClip[])(object)new AudioClip[1] { val }; if (!_pitchVariation.Value) { __instance.m_minPitch = 1f; __instance.m_maxPitch = 1f; } } else if (Random.value >= _originalChance.Value) { __instance.m_minVol = 0f; __instance.m_maxVol = 0f; } } private static AudioClip PickClip(string list) { if (string.IsNullOrEmpty(list)) { return null; } List<AudioClip> list2 = new List<AudioClip>(); string[] array = list.Split(','); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split('*'); if (array2.Length < 2 || !int.TryParse(array2[1].Trim(), out var result)) { result = 1; } if (Clips.TryGetValue(array2[0].Trim(), out var value)) { for (int j = 0; j < Mathf.Clamp(result, 0, 100); j++) { list2.Add(value); } } } if (list2.Count <= 0) { return null; } return list2[Random.Range(0, list2.Count)]; } } [BepInPlugin("dafoertnite.patches", "DafoertNite Patches", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class HarmonizerPlugin : BaseUnityPlugin { public const string Guid = "dafoertnite.patches"; public const string Name = "DafoertNite Patches"; public const string Version = "1.2.0"; private const string OldGuid = "inventoryharmonizer"; internal static ManualLogSource Log; private FileSystemWatcher _watcher; private volatile bool _reloadConfig; private DateTime _configWritten; private void Awake() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; if (Loaded("inventoryharmonizer")) { Log.LogWarning((object)"Inventory Harmonizer (the old name of this mod) is also installed; remove it. DafoertNite Patches stays inactive until then."); return; } Harmony harmony = new Harmony("dafoertnite.patches"); VssModdedContainers.Apply(((BaseUnityPlugin)this).Config, harmony); MultiCraftChestNetwork.Apply(((BaseUnityPlugin)this).Config, harmony); MultiCraftAdventureBackpacks.Apply(((BaseUnityPlugin)this).Config, harmony); AutomaticFuelNewContainers.Apply(((BaseUnityPlugin)this).Config, harmony); GoblinSoundpack.Apply((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Config, harmony); _watcher = new FileSystemWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath), Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath)); _watcher.Changed += delegate { _reloadConfig = true; }; _watcher.EnableRaisingEvents = true; _configWritten = File.GetLastWriteTimeUtc(((BaseUnityPlugin)this).Config.ConfigFilePath); } private void Update() { if (_reloadConfig) { _reloadConfig = false; if (!(File.GetLastWriteTimeUtc(((BaseUnityPlugin)this).Config.ConfigFilePath) == _configWritten)) { ((BaseUnityPlugin)this).Config.Reload(); _configWritten = File.GetLastWriteTimeUtc(((BaseUnityPlugin)this).Config.ConfigFilePath); Log.LogInfo((object)"Config reloaded."); } } } private void OnDestroy() { if (_watcher != null) { _watcher.Dispose(); } } internal static bool Loaded(string guid) { return Chainloader.PluginInfos.ContainsKey(guid); } } internal static class MultiCraftAdventureBackpacks { internal const string AdventureBackpacksGuid = "vapok.mods.adventurebackpacks"; private static MethodInfo _enter; private static MethodInfo _exit; internal static void Apply(ConfigFile config, Harmony harmony) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_0112: Expected O, but got Unknown if (HarmonizerPlugin.Loaded("vapok.mods.adventurebackpacks") && HarmonizerPlugin.Loaded("maximods.valheim.multicraft") && config.Bind<bool>("MultiCraft + AdventureBackpacks", "Enabled", true, "Let MultiCraft count materials in your equipped backpack when working out how many items you can craft.").Value) { MethodInfo methodInfo = AccessTools.Method("MultiCraft.Helper:GetAvailableItems", new Type[1] { typeof(string) }, (Type[])null); Type type = AccessTools.TypeByName("AdventureBackpacks.Features.CraftingContext"); _enter = ((type != null) ? type.GetMethod("Enter", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null) : null); _exit = ((type != null) ? type.GetMethod("Exit", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null) : null); if (methodInfo == null || _enter == null || _exit == null) { HarmonizerPlugin.Log.LogWarning((object)"MultiCraft + AdventureBackpacks: a mod changed internally; this fix is inactive."); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(MultiCraftAdventureBackpacks), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(MultiCraftAdventureBackpacks), "Finalizer", (Type[])null), (HarmonyMethod)null); HarmonizerPlugin.Log.LogInfo((object)"MultiCraft + AdventureBackpacks: MultiCraft now counts backpack contents."); } } private static void Prefix(out bool __state) { __state = false; try { _enter.Invoke(null, null); __state = true; } catch (Exception ex) { HarmonizerPlugin.Log.LogWarning((object)("MultiCraft + AdventureBackpacks: " + ex.Message)); } } private static Exception Finalizer(bool __state, Exception __exception) { if (__state) { _exit.Invoke(null, null); } return __exception; } } internal static class MultiCraftChestNetwork { internal const string ChestNetworkGuid = "jordan.chestnetwork"; internal const string MultiCraftGuid = "maximods.valheim.multicraft"; internal static void Apply(ConfigFile config, Harmony harmony) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_00e0: Expected O, but got Unknown if (HarmonizerPlugin.Loaded("jordan.chestnetwork") && HarmonizerPlugin.Loaded("maximods.valheim.multicraft") && config.Bind<bool>("MultiCraft + ChestNetwork", "Enabled", true, "Let MultiCraft count materials in ChestNetwork chests when working out how many items you can craft.").Value) { MethodInfo methodInfo = AccessTools.Method("MultiCraft.Helper:GetAvailableItems", new Type[1] { typeof(string) }, (Type[])null); Type type = AccessTools.Inner(AccessTools.TypeByName("ChestNetwork.Plugin.Patches.RequirementPatches"), "CheckScope"); MethodInfo methodInfo2 = ((type != null) ? AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null) : null); MethodInfo methodInfo3 = ((type != null) ? AccessTools.Method(type, "Finalizer", (Type[])null, (Type[])null) : null); if (methodInfo == null || methodInfo2 == null || methodInfo3 == null) { HarmonizerPlugin.Log.LogWarning((object)"MultiCraft + ChestNetwork: a mod changed internally; this fix is inactive."); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo3), (HarmonyMethod)null); HarmonizerPlugin.Log.LogInfo((object)"MultiCraft + ChestNetwork: MultiCraft now counts ChestNetwork chests."); } } } internal static class VssModdedContainers { internal const string VssGuid = "georo.vss"; private const string OldBridgeGuid = "vssbridge.containers"; private static ConfigEntry<bool> _logContainers; private static MethodInfo _vssRegister; private static readonly HashSet<string> Extra = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> Excluded = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, bool> Cache = new Dictionary<string, bool>(); internal static void Apply(ConfigFile config, Harmony harmony) { //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown if (!HarmonizerPlugin.Loaded("georo.vss")) { return; } ConfigEntry<bool> obj = config.Bind<bool>("VSS + modded containers", "Enabled", true, "Let VSS link standalone containers from other mods that players build with the hammer. Carts, ships, graves, the Obliterator and world loot stay excluded."); ConfigEntry<string> val = config.Bind<string>("VSS + modded containers", "ExtraPrefabs", "", "Comma-separated prefab names to always link."); ConfigEntry<string> val2 = config.Bind<string>("VSS + modded containers", "ExcludedPrefabs", "", "Comma-separated prefab names to never link through this fix."); _logContainers = config.Bind<bool>("VSS + modded containers", "LogContainerPrefabs", false, "Log each container prefab this fix evaluates (once per prefab), to find names for the lists above."); if (!obj.Value) { return; } if (HarmonizerPlugin.Loaded("vssbridge.containers")) { HarmonizerPlugin.Log.LogWarning((object)"VSS: the old VSS Container Bridge is installed; remove it. Skipping this fix to avoid patching twice."); return; } Type type = AccessTools.TypeByName("VSS.VssStorageScanner"); if (type != null && type.GetMethod("Supported", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(Container), typeof(bool) }, null) != null) { HarmonizerPlugin.Log.LogInfo((object)"VSS: this VSS version supports modded containers itself; fix not needed."); return; } MethodInfo methodInfo = AccessTools.Method("VSS.VssStorageScanner:Supported", new Type[1] { typeof(Container) }, (Type[])null); if (methodInfo == null) { HarmonizerPlugin.Log.LogWarning((object)"VSS: VssStorageScanner.Supported(Container) not found; this fix is inactive."); return; } Parse(val.Value, Extra); Parse(val2.Value, Excluded); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(VssModdedContainers), "SupportedPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _vssRegister = AccessTools.Method("VSS.VssContainerAwakePatch:Postfix", new Type[1] { typeof(Container) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Piece), "SetCreator", (Type[])null, (Type[])null); if (_vssRegister != null && methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(VssModdedContainers), "SetCreatorPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { HarmonizerPlugin.Log.LogWarning((object)"VSS: could not hook piece placement; new modded containers link after the area reloads."); } HarmonizerPlugin.Log.LogInfo((object)"VSS: modded containers can be linked."); } private static void SupportedPostfix(Container container, ref bool __result) { if (__result || (Object)(object)container == (Object)null || (Object)(object)container.m_wagon != (Object)null || container.m_autoDestroyEmpty) { return; } ZNetView component = ((Component)container).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(component.GetZDO().GetPrefab()) : null); string text = (((Object)(object)val != (Object)null) ? ((Object)val).name : ((Object)((Component)container).gameObject).name.Replace("(Clone)", "").Trim()); if (!Cache.TryGetValue(text, out var value)) { value = Evaluate(container, component, text); Cache[text] = value; if (_logContainers.Value) { HarmonizerPlugin.Log.LogInfo((object)("VSS: container prefab '" + text + "' -> " + (value ? "linked" : "ignored"))); } } __result = value && component.GetZDO().GetLong(ZDOVars.s_creator, 0L) != 0; } private static bool Evaluate(Container container, ZNetView view, string name) { if (Excluded.Contains(name)) { return false; } if (Extra.Contains(name)) { return true; } if ((Object)(object)container.m_rootObjectOverride != (Object)null) { return false; } if ((Object)(object)((Component)view).GetComponent<Piece>() == (Object)null) { return false; } if ((Object)(object)((Component)view).GetComponent<Ship>() == (Object)null && (Object)(object)((Component)view).GetComponent<TombStone>() == (Object)null) { return (Object)(object)((Component)view).GetComponent<Incinerator>() == (Object)null; } return false; } private static void SetCreatorPostfix(Piece __instance) { Container component = ((Component)__instance).GetComponent<Container>(); if ((Object)(object)component == (Object)null) { return; } try { _vssRegister.Invoke(null, new object[1] { component }); } catch (Exception ex) { HarmonizerPlugin.Log.LogWarning((object)("VSS: registration failed: " + ex.Message)); } } private static void Parse(string value, HashSet<string> into) { if (string.IsNullOrEmpty(value)) { return; } string[] array = value.Split(','); foreach (string text in array) { if (text.Trim().Length > 0) { into.Add(text.Trim()); } } } } }