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 ZenWorldSettings v1.10.6
plugins/ZenWorldSettings.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Jotunn.Configs; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using Zen; using Zen.Compatibility; using Zen.Interop; using Zen.Lib; using Zen.Lib.Config; using ZenWorldSettings.Sections; using ZenWorldSettings.Sections.Fireplaces; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ZenWorldSettings")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ZenWorldSettings")] [assembly: AssemblyCopyright("Copyright \ufffd 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.0.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.1.0")] [module: RefSafetyRules(11)] [CompilerGenerated] internal delegate void <>f__AnonymousDelegate0<T1, T2, T3>(T1 arg1, T2 arg2, params T3[] arg3); namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 ZenWorldSettings { [Disable(new Type[] { typeof(TombStone) })] [BepInIncompatibility("org.bepinex.plugins.hildirsquest")] [BepInPlugin("ZenDragon.ZenWorldSettings", "ZenWorldSettings", "1.10.6")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class Plugin : ZenMod<Plugin> { public const string PluginName = "ZenWorldSettings"; public const string PluginVersion = "1.10.6"; public const string PluginGUID = "ZenDragon.ZenWorldSettings"; protected override void Setup() { ((ZenMod)this).RunOnServer = true; base.LanguageChanged += CraftTeleportRules.UpdateTranslations; base.ConfigSync += OnConfigSync; SpawnerRules.InitTerminal(); } private static void OnConfigSync() { DoorKeys.InitKeys(); CraftTeleportRules.Init(); BurnAnything.SetupKiln(); CampfireRules.InitPrefab(); TraderRules.InitPrefabs(); } protected override void TitleScene(bool isFirstBoot) { } protected override void HotRestore() { DoorKeys.InitKeys(); } protected override void WorldStart() { EnvironmentRules.Start(); TurretRules.Start(); ShieldGen.Start(); DoorKeys.UpdateRecipes(); Quests.RegisterRPC(); } protected override void Shutdown() { TurretRules.Shutdown(); ShieldGen.Shutdown(); DoorKeys.Shutdown(); Quests.Shutdown(); } protected override HelpInfo? GetHelpInfo() { //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Expected O, but got Unknown StringBuilder stringBuilder = new StringBuilder(); if (ShipRules.Configs.ShipNoSuddenStop.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(ShipRules.Configs.ShipNoSuddenStop, false, true, true)); } if (ShipRules.Configs.ShipSafeHarbor.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(ShipRules.Configs.ShipSafeHarbor, false, true, true)); } if (ShipRules.Configs.ShipLadderDisembark.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(ShipRules.Configs.ShipLadderDisembark, false, true, true)); } if (ShipRules.Configs.ShipRefundPercent.Value < 1f) { stringBuilder.AppendLine(HelpInfo.Format<float>(ShipRules.Configs.ShipRefundPercent, true, true, true)); } if (ShipRules.Configs.ShipRename.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(ShipRules.Configs.ShipRename, false, true, true)); if (ShipRules.Configs.ShipOwnerIsCaptain.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(ShipRules.Configs.ShipOwnerIsCaptain, false, true, true)); } } if (ShipRules.Configs.ShipCaptainClaimZDO.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(ShipRules.Configs.ShipCaptainClaimZDO, false, true, true)); } if (Configs.CandleRefill.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.CandleRefill, false, true, true)); } if (Configs.CampfireStartEmpty.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.CampfireStartEmpty, false, true, true)); } if (((List<string>)(object)Configs.BurnableItems.Value).Count > 0) { stringBuilder.AppendLine(HelpInfo.Format<StringList>(Configs.BurnableItems, true, true, true)); } if (Configs.SparkEnabled.Value) { if (Configs.SparkWithTorch.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.SparkWithTorch, false, true, true)); } if (!Utility.IsNullOrWhiteSpace(Configs.SparkItem.Value)) { stringBuilder.AppendLine(HelpInfo.Format<string>(Configs.SparkItem, true, true, true)); if (Configs.SparkItemConsume.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.SparkItemConsume, false, true, true)); } } } if (DoorKeys.Configs.UsageLimit.Value > 0) { stringBuilder.AppendLine(HelpInfo.Format<int>(DoorKeys.Configs.UsageLimit, true, true, true)); if (DoorKeys.Configs.Repairable.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(DoorKeys.Configs.Repairable, false, true, true)); } } if (PvPRules.Configs.PvPMode.Value != 0) { stringBuilder.AppendLine(HelpInfo.Format<PvPRules.Mode>(PvPRules.Configs.PvPMode, true, true, true)); } stringBuilder.AppendLine(HelpInfo.Format<bool>(PvPRules.Configs.CanKillTames, true, true, true)); if (Quests.Configs.PerPlayerQuests.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(Quests.Configs.PerPlayerQuests, false, true, true)); } if (ShieldGen.Configs.ShieldProtectsFireFromRain.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(ShieldGen.Configs.ShieldProtectsFireFromRain, false, true, true)); } if (TurretRules.Configs.MaxTargets.Value > 1) { stringBuilder.AppendLine(HelpInfo.Format<int>(TurretRules.Configs.MaxTargets, true, true, true)); } if (!TurretRules.Configs.TargetTamed.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(TurretRules.Configs.TargetTamed, true, true, true)); } if (!TurretRules.Configs.TargetPlayers.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(TurretRules.Configs.TargetPlayers, true, true, true)); } return new HelpInfo("World Settings", stringBuilder.ToString()); } private static void SetupItemCollidersOnShips() { int num = LayerMask.NameToLayer("item"); int num2 = LayerMask.NameToLayer("vehicle"); Physics.IgnoreLayerCollision(num, num2, false); } } } namespace ZenWorldSettings.Sections { [HarmonyPatch] internal static class CraftTeleportRules { private static class Configs { private const string SECTION_CRAFT_TELEPORT = "Craft / Teleport"; public static readonly ConfigEntry<StringList> CraftItemsDeny = Config.Define<StringList>(true, "Craft / Teleport", "Craft Items - Deny", StringList.Empty, "List of items to remove from crafting.\r\nRecipies are removed and new instances of the item can't be crafted.\r\nHowever, any existing items will still remain. Additionlly any loot drops of the item will still be possible.\r\n[reboot required for changes to take effect]"); public static readonly ConfigEntry<StringList> CraftPiecesDeny = Config.Define<StringList>(true, "Craft / Teleport", "Craft Pieces - Deny", StringList.Empty, "List of pieces which can not be crafted.\r\nHowever, nocost flag will still allow them to be built. Existing instances of pieces will still remain.\r\n[reboot required for changes to take effect]"); public static readonly ConfigEntry<StringList> TeleportItemsDeny = Config.Define<StringList>(true, "Craft / Teleport", "Teleport Items - Deny", StringList.Empty, "List of items which CAN NOT be teleported.\r\n[reboot required for changes to take effect]"); public static readonly ConfigEntry<StringList> TeleportItemsAllow; public static readonly ConfigEntry<StringList> TeleportItemsExclusive; static Configs() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0082: Expected O, but got Unknown StringList val = new StringList(); ((List<string>)val).Add("Ironpit"); TeleportItemsAllow = Config.Define<StringList>(true, "Craft / Teleport", "Teleport Items - Allow", val, "List of items which CAN be teleported.\r\nMake items teleportable which would otherwise not be teleportable.\r\nCan be useful for example if you wanted to teleport refined metals but not ore:\r\nCopper, Tin, Bronze, Iron, Silver, BlackMetal, Flametal, FlametalNew\r\n[reboot required for changes to take effect]"); TeleportItemsExclusive = Config.Define<StringList>(true, "Craft / Teleport", "Teleport Items - Exclusive", StringList.Empty, "Exclusive list of item prefab names that are allowed to be teleported.\r\nIf any items are defined it inverts the vanilla behavior of restricting items.\r\nInstead, only allow teleporting the items listed, all others are restricted.\r\nIf you want to deny all items use the keyword: NONE (Vanilla: Leave blank)\r\nOverrides the item allow/deny teleport rules.\r\n[restart required for changes to take effect]"); } } private static bool IsNothingAllowed { get { if (((List<string>)(object)Configs.TeleportItemsExclusive.Value).Count == 1) { return ((List<string>)(object)Configs.TeleportItemsExclusive.Value)[0].ToUpperInvariant() == "NONE"; } return false; } } private static bool IsExclusiveItems { get { if (((List<string>)(object)Configs.TeleportItemsExclusive.Value).Count <= 0) { return IsNothingAllowed; } return true; } } internal static void Init() { DisableItems(); DisablePieces(); SetTeleportRules(); } private static void SetTeleportRules() { if (IsExclusiveItems) { InitExclusiveAllowItems(); return; } foreach (string item in (List<string>)(object)Configs.TeleportItemsDeny.Value) { SetTeleport(item, state: false); } foreach (string item2 in (List<string>)(object)Configs.TeleportItemsAllow.Value) { SetTeleport(item2, state: true); } static void SetTeleport(string prefabName, bool state) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) GameObject val = default(GameObject); if (ObjectDB.instance.TryGetItemPrefab(prefabName, ref val)) { val.GetComponent<ItemDrop>().m_itemData.m_shared.m_teleportable = state; bool flag = default(bool); InterpolatedString<Plugin> val2 = new InterpolatedString<Plugin>(23, 2, ref flag); if (flag) { val2.AppendLiteral("AllowTeleport Item: "); val2.AppendFormatted(((Object)val).name); val2.AppendLiteral(" - "); val2.AppendFormatted<bool>(state); } Logging<Plugin>.Info(val2, 0); } } } private static void DisableItems() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (((List<string>)(object)Configs.CraftItemsDeny.Value).Count == 0) { return; } bool flag = default(bool); foreach (Recipe recipe in ObjectDB.instance.m_recipes) { ItemDrop item = recipe.m_item; string text = ((item != null) ? ItemDataExt.GetPrefabName(item) : null) ?? string.Empty; if (Configs.CraftItemsDeny.Value.Contains(text, true)) { recipe.m_enabled = false; InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(14, 1, ref flag); if (flag) { val.AppendLiteral("NoCraft Item: "); val.AppendFormatted(text); } Logging<Plugin>.Info(val, 0); } } } private static void DisablePieces() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) Piece val = default(Piece); bool flag = default(bool); foreach (string item in (List<string>)(object)Configs.CraftPiecesDeny.Value) { GameObject prefab = ZNetScene.instance.GetPrefab(item); if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<Piece>(ref val)) { val.m_enabled = false; InterpolatedString<Plugin> val2 = new InterpolatedString<Plugin>(15, 1, ref flag); if (flag) { val2.AppendLiteral("NoCraft Piece: "); val2.AppendFormatted(((Object)val).name); } Logging<Plugin>.Info(val2, 0); } } } private static void InitExclusiveAllowItems() { foreach (GameObject item in ObjectDB.instance.m_items) { item.GetComponent<ItemDrop>().m_itemData.m_shared.m_teleportable = !Configs.TeleportItemsExclusive.Value.Contains(((Object)item).name, true); } } public static void UpdateTranslations(string language) { if (IsExclusiveItems) { Localization.instance.m_translations["item_noteleport"] = StringExt.Localize("$item_teleport"); } } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "IsTeleportable")] private static void Inventory_IsTeleportable(Inventory __instance, ref bool __result, ref bool __runOriginal) { if (!IsExclusiveItems) { return; } __runOriginal = false; List<ItemData> inventory = __instance.m_inventory; if (inventory.Count > 0 && IsNothingAllowed) { __result = false; return; } StringList allowItems = Configs.TeleportItemsExclusive.Value; __result = inventory.All((ItemData item) => allowItems.Contains(ItemDataExt.GetPrefabName(item), true)); } [HarmonyTranspiler] [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] [HarmonyPriority(100)] private static IEnumerable<CodeInstruction> InventoryGrid_UpdateGui(IEnumerable<CodeInstruction> codes) { FieldInfo field = AccessTools.DeclaredField(typeof(SharedData), "m_teleportable"); Func<SharedData, bool> intercept = InterceptTeleportable; return Transpilers.Manipulator(codes, (Func<CodeInstruction, bool>)((CodeInstruction c) => CodeInstructionExtensions.Is(c, OpCodes.Ldfld, (MemberInfo)field)), (Action<CodeInstruction>)delegate(CodeInstruction c) { c.opcode = OpCodes.Call; c.operand = intercept.Method; }); static bool InterceptTeleportable(SharedData shared) { if (!shared.m_teleportable) { return IsExclusiveItems; } return true; } } } [HarmonyPatch] internal static class DoorKeys { public static class Configs { public static readonly ConfigEntry<int> UsageLimit; public static readonly ConfigEntry<StringList> UpgradeCost; public static readonly ConfigEntry<int> MaxQuality; public static readonly ConfigEntry<int> StationLevel; public static readonly ConfigEntry<string> Station; public static readonly ConfigEntry<bool> Repairable; public static readonly ConfigEntry<StringList> IndestructibleDoorKeys; public static readonly ConfigEntry<StringList> RemoveBrokenKeys; static Configs() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0053: Expected O, but got Unknown UsageLimit = Config.Define<int>(true, "Door Keys", "Usage Limit", 0, Config.AcceptRange<int>(0, 10), "Door keys break after this many uses. [Set to 0 for infinite use] (Vanilla: 0)\r\nThis is the initial number of uses for level 1 keys. Upgrades add more uses.\r\n[Default config settings do not require repair so that it works with vanilla serers. However, it is recommended to change this to 1 in single player or on modded servers for a more emergent experience]\r\n[logout required for changes to take effect]"); StringList val = new StringList(); ((List<string>)val).Add("Iron:1:1"); ((List<string>)val).Add("Guck:1:1"); UpgradeCost = Config.Define<StringList>(true, "Door Keys", "Upgrade Cost", val, "Comma separated list of resource requirements for upgrading keys.\r\nPrefabName:Cost:IncreasedCostPerLevel\r\n[logout required for changes to take effect]"); MaxQuality = Config.Define<int>(true, "Door Keys", "Max Quality", 4, Config.AcceptRange<int>(1, 9), "Max quality that door keys can be leveled up. (Vanilla: 1)\r\nEach level increases the number of uses by 1.\r\nSet to 1 to disable upgrading keys.\r\n[logout required for changes to take effect]"); StationLevel = Config.Define<int>(true, "Door Keys", "Station Level", 3, Config.AcceptRange<int>(1, 7), "Minimum station level needed to repair keys.\r\nNOTE: Upgrade requires +1 to this level\r\n[logout required for changes to take effect]"); Station = Config.Define<string>(true, "Door Keys", "Station", "Forge", CraftingStations.GetAcceptableValueList(), "The station that can be used to repair and upgrade any keys that are NOT crafted, such as keys dropped from monsters, or found in chests, or purchased.\r\nIf the key is crafted then it repairs and upgrades at the station that was used to craft it.\r\n[logout required for changes to take effect]"); Repairable = Config.Define<bool>(true, "Door Keys", "Repairable", true, "Keys can be repaired when broken. A broken key can not be used to open a door.\r\n[This requires a " + ((ConfigEntryBase)Station).Definition.Key + "]\r\n[logout required for changes to take effect]"); IndestructibleDoorKeys = Config.Define<StringList>(true, "Door Keys", "Indestructible Keys", StringList.Empty, "Comma separted list of item prefab names for Door Keys that should never break.\r\nThese keys will be ignored by the system.\r\n[logout required for changes to take effect]"); RemoveBrokenKeys = Config.Define<StringList>(true, "Door Keys", "Remove Broken Keys", StringList.Empty, "Comma separated list of key prefab names.\r\nKeys will be removed from the inventory when they break.\r\nAny existing broken keys in your inventory will not be affected.\r\nThis will override the repair configs since the key will be erased when it breaks.\r\nExample: CryptKey"); } } private static readonly HashSet<string> KeyNames = new HashSet<string>(); private static readonly List<Recipe> KeyRecipes = new List<Recipe>(); private static readonly string IconText = $"<size=2em><color={UIColor.ValheimTooltipTitle}>\ud83d\udddd</color></size>"; private static bool IsKeysUnlimited => Configs.UsageLimit.Value == 0; private static bool CanUpgrade(ItemData key) { return key.m_shared.m_maxQuality > 1; } private static bool CanRepair(ItemData key) { return key.m_shared.m_canBeReparied; } internal static void Shutdown() { RemoveUpgradeRecipes(); } private static void RemoveUpgradeRecipes() { foreach (Recipe keyRecipe in KeyRecipes) { ObjectDB.instance.m_recipes.Remove(keyRecipe); Object.Destroy((Object)(object)keyRecipe); } KeyRecipes.Clear(); } public static void InitKeys() { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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) Logging<Plugin>.Info("Setup door keys", 0); RemoveUpgradeRecipes(); KeyNames.Clear(); if (IsKeysUnlimited) { Logging<Plugin>.Info("Usage limit set to infinite in configs", 0); return; } bool flag = default(bool); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { Door componentInChildren = prefab.GetComponentInChildren<Door>(); if (!Object.op_Implicit((Object)(object)componentInChildren) || !Object.op_Implicit((Object)(object)componentInChildren.m_keyItem)) { continue; } ItemDrop keyItem = componentInChildren.m_keyItem; string prefabName = ItemDataExt.GetPrefabName(keyItem); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(15, 2, ref flag); if (flag) { val.AppendLiteral("Door "); val.AppendFormatted(((Object)prefab).name); val.AppendLiteral(" has key: "); val.AppendFormatted(prefabName); } Logging<Plugin>.Info(val, 0); if (!KeyNames.Add(prefabName)) { val = new InterpolatedString<Plugin>(28, 1, ref flag); if (flag) { val.AppendLiteral("Key "); val.AppendFormatted(prefabName); val.AppendLiteral(" already added, skipping"); } Logging<Plugin>.Info(val, 0); } else if (IsLimitedUseKey(prefabName)) { InitKeyItem(keyItem.m_itemData); InitKeyRecipe(keyItem); } } } private static void InitKeyItem(ItemData doorKey) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(24, 1, ref flag); if (flag) { val.AppendLiteral("Setup the the door key: "); val.AppendFormatted(ItemDataExt.GetName(doorKey)); } Logging<Plugin>.Info(val, 0); doorKey.m_shared.m_useDurability = true; doorKey.m_shared.m_maxDurability = Configs.UsageLimit.Value; doorKey.m_shared.m_canBeReparied = Configs.Repairable.Value && Configs.Station.Value != CraftingStations.None; doorKey.m_shared.m_durabilityPerLevel = 1f; doorKey.m_shared.m_maxQuality = Configs.MaxQuality.Value; doorKey.m_durability = Mathf.Min(doorKey.m_durability, doorKey.GetMaxDurability()); } private static void InitKeyRecipe(ItemDrop doorKey) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) string prefabName = ItemDataExt.GetPrefabName(doorKey); bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(29, 1, ref flag); if (flag) { val.AppendLiteral("Init limited use key recipe: "); val.AppendFormatted(prefabName); } Logging<Plugin>.Info(val, 0); if (!doorKey.m_itemData.m_shared.m_canBeReparied) { val = new InterpolatedString<Plugin>(66, 1, ref flag); if (flag) { val.AppendFormatted(prefabName); val.AppendLiteral(" can not be repaired, not configured or no repair station defined."); } Logging<Plugin>.Info(val, 0); return; } Recipe recipe = ObjectDB.instance.GetRecipe(doorKey.m_itemData); if (Object.op_Implicit((Object)(object)recipe)) { val = new InterpolatedString<Plugin>(23, 1, ref flag); if (flag) { val.AppendLiteral("Recipe already exists: "); val.AppendFormatted(prefabName); } Logging<Plugin>.Info(val, 0); return; } val = new InterpolatedString<Plugin>(30, 1, ref flag); if (flag) { val.AppendLiteral("Adding repair/upgrade recipe: "); val.AppendFormatted(prefabName); } Logging<Plugin>.Info(val, 0); bool flag2 = doorKey.m_itemData.m_shared.m_maxQuality > 1; recipe = ScriptableObject.CreateInstance<Recipe>(); recipe.m_item = doorKey; recipe.m_enabled = flag2; recipe.m_resources = Configs.UpgradeCost.Value.ToRequirements(':'); CraftingStation craftingStation = PrefabManagerExt.GetCraftingStation(PrefabManager.Instance, Configs.Station.Value); recipe.m_craftingStation = (flag2 ? craftingStation : null); recipe.m_repairStation = craftingStation; recipe.m_minStationLevel = Configs.StationLevel.Value; KeyRecipes.Add(recipe); } private static bool IsLimitedUseKey(this ItemDrop? item) { if ((Object)(object)item != (Object)null) { return IsLimitedUseKey(ItemDataExt.GetPrefabName(item)); } return false; } private static bool IsLimitedUseKey(this ItemData? itemData) { if (itemData != null) { return IsLimitedUseKey(ItemDataExt.GetPrefabName(itemData)); } return false; } private static bool IsLimitedUseKey(string prefabName) { if (Utility.IsNullOrWhiteSpace(prefabName)) { return false; } if (KeyNames.Contains(prefabName)) { return !Configs.IndestructibleDoorKeys.Value.Contains(prefabName, true); } return false; } private static ItemData? FindLimitedKey(this Inventory inventory, ItemDrop? item) { if (!Object.op_Implicit((Object)(object)item)) { return null; } return inventory.FindLimitedKey(ItemDataExt.GetPrefabName(item)); } private static ItemData? FindLimitedKey(this Inventory inventory, ItemData? itemData) { if (itemData == null) { return null; } return inventory.FindLimitedKey(ItemDataExt.GetPrefabName(itemData)); } private static ItemData? FindLimitedKey(this Inventory inventory, string keyPrefabName) { string keyPrefabName2 = keyPrefabName; if (!IsLimitedUseKey(keyPrefabName2)) { return null; } return ((IEnumerable<ItemData>)(from item in inventory.GetAllItems() orderby item.m_durability select item)).FirstOrDefault((Func<ItemData, bool>)((ItemData item) => ItemDataExt.GetPrefabName(item) == keyPrefabName2 && item.m_durability > 0f)); } private static void DegradeItem(this Player player, ItemData key) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = ((Humanoid)player).GetInventory(); key.m_durability = Mathf.Clamp(key.m_durability - 1f, 0f, key.GetMaxDurability()); inventory.Changed(); if (key.m_durability > 0f) { return; } bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(11, 1, ref flag); if (flag) { val.AppendLiteral("Item broke "); val.AppendFormatted(ItemDataExt.GetName(key)); } Logging<Plugin>.Info(val, 0); ((Character)player).Message((MessageType)2, StringExt.Localize("$msg_broke", new string[1] { ItemDataExt.GetName(key) }), 0, (Sprite)null); if (Configs.RemoveBrokenKeys.Value.Contains(ItemDataExt.GetPrefabName(key), true)) { val = new InterpolatedString<Plugin>(28, 1, ref flag); if (flag) { val.AppendLiteral("Removing key "); val.AppendFormatted(ItemDataExt.GetPrefabName(key)); val.AppendLiteral(" from inventory"); } Logging<Plugin>.Info(val, 0); inventory.RemoveItem(key); } } private static void UseLimitedKey(this Player player, ItemDrop item) { player.UseLimitedKey(ItemDataExt.GetPrefabName(item)); } private static void UseLimitedKey(this Player player, string keyPrefabName) { ItemData val = ((Humanoid)player).GetInventory().FindLimitedKey(keyPrefabName); if (val != null) { player.DegradeItem(val); } } [HarmonyPostfix] [HarmonyPatch(typeof(Door), "Interact")] private static void Door_Interact(Door __instance, Humanoid character, bool hold, bool alt, bool __result) { if (!IsKeysUnlimited && !(hold || alt) && __result && Object.op_Implicit((Object)(object)__instance.m_keyItem)) { Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { val.UseLimitedKey(__instance.m_keyItem); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Door), "HaveKey")] private static void Door_HaveKey(Door __instance, Humanoid player, ref bool __result) { if (!IsKeysUnlimited && Object.op_Implicit((Object)(object)__instance.m_keyItem) && __result) { __result = player.GetInventory().FindLimitedKey(__instance.m_keyItem) != null; } } internal static void UpdateRecipes() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) List<Recipe> recipes = ObjectDB.instance.m_recipes; bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(25, 1, ref flag); if (flag) { val.AppendLiteral("UpgradeKeyRecipes Count: "); val.AppendFormatted<int>(KeyRecipes.Count); } Logging<Plugin>.Info(val, 0); foreach (Recipe keyRecipe in KeyRecipes) { val = new InterpolatedString<Plugin>(12, 1, ref flag); if (flag) { val.AppendLiteral("Add recipe: "); val.AppendFormatted(ItemDataExt.GetPrefabName(keyRecipe.m_item)); } Logging<Plugin>.Info(val, 0); if (!recipes.Contains(keyRecipe)) { recipes.Add(keyRecipe); } } } [HarmonyTranspiler] [HarmonyPatch(typeof(Player), "GetAvailableRecipes")] private static IEnumerable<CodeInstruction> Player_GetAvailableRecipes(IEnumerable<CodeInstruction> codes) { MethodInfo methodInfo = AccessTools.Method(typeof(List<Recipe>), "Add", (Type[])null, (Type[])null); Action<List<Recipe>, Recipe> action = RecipeAdd_Intercept; return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)action.Method); } private static void RecipeAdd_Intercept(List<Recipe> recipes, Recipe recipe) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (KeyRecipes.Contains(recipe) && InventoryGui.instance.InCraftTab()) { bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(29, 1, ref flag); if (flag) { val.AppendLiteral("Skip recipe on crafting tab: "); val.AppendFormatted(ItemDataExt.GetPrefabName(recipe.m_item)); } Logging<Plugin>.Info(val, 0); } else { recipes.Add(recipe); } } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int) })] private static void Inventory_AddItem(Inventory __instance, ItemData item) { if (!IsKeysUnlimited && item.IsLimitedUseKey()) { InitKeyItem(item); } } [HarmonyPostfix] [HarmonyPatch(typeof(InventoryGui), "Update")] private static void InventoryGui_Update(InventoryGui __instance) { HandleAdminForcedKeyDegrade(); } private static void HandleAdminForcedKeyDegrade() { if (InventoryGui.IsVisible() && Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Character)Player.m_localPlayer).InGodMode()) { ItemData dragItem = InventoryGui.instance.m_dragItem; if (dragItem != null && ZInput.GetKey((KeyCode)303, true) && ZInput.GetKeyDown((KeyCode)305, true) && dragItem.IsLimitedUseKey()) { Logging<Plugin>.Warning((object)("ADMIN: " + ItemDataExt.GetPrefabName(dragItem) + " Removed Durability"), 0); Player.m_localPlayer.DegradeItem(dragItem); } } } [HarmonyPostfix] [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(int) })] private static void ItemData_GetTooltip(ItemData __instance, ref string __result) { if (!__instance.IsLimitedUseKey()) { return; } bool flag = CanRepair(__instance); bool flag2 = CanUpgrade(__instance); if (!flag && !flag2) { ItemDataExt.SetTooltipExtra(__instance, IconText); return; } CraftingStation craftingStation = PrefabManagerExt.GetCraftingStation(PrefabManager.Instance, Configs.Station.Value); string text = (Object.op_Implicit((Object)(object)craftingStation) ? craftingStation.m_name : string.Empty); if (!Utility.IsNullOrWhiteSpace(text)) { int value = Configs.StationLevel.Value; string text2 = ((value > 1) ? $" $msg_level {value}" : string.Empty); string text3 = (flag2 ? "$inventory_upgradebutton" : string.Empty); string text4 = (flag ? "$piece_repair" : string.Empty); string text5 = ((flag && flag2) ? " / " : string.Empty); string text6 = IconText + "\n\n" + text4 + text5 + text3 + "\n" + text + text2; ItemDataExt.SetTooltipExtra(__instance, text6); string text7 = "$piece_repair: <color=orange>" + text + "</color>"; __result = Regex.Replace(__result, "\\$item_repairlevel.*\n?", text7 + "\n$0"); } } } [HarmonyPatch] internal static class EnvironmentRules { private static class Configs { private const string SECTION_ENVIRONMENT = "Environment"; public static readonly ConfigEntry<bool> ShowSkyTree; public static readonly ConfigEntry<bool> ShowWindPixels; public static readonly ConfigEntry<int> DayLengthSeconds; public static readonly ConfigEntry<bool> ShowDayNumber; public static readonly ConfigEntry<int> SnowStormParticlesMax; static Configs() { ShowSkyTree = Config.Define<bool>(true, "Environment", "Show Sky Tree", false, "Navigate with only the sun and stars."); ShowWindPixels = Config.Define<bool>(true, "Environment", "Show Wind Pixels", false, "Enable the chunky wind pixels"); DayLengthSeconds = Config.Define<int>(true, "Environment", "Day Length Seconds", 0, Config.AcceptRange<int>(0, 10800), "Length of an in game day in seconds. (Vanilla: 1800)\r\nSet to 0 to disable this setting.\r\nNOTE: When multiplayer, this mod must be installed on the server and all clients for this setting to work."); ShowDayNumber = Config.Define<bool>(true, "Environment", "Show Day Number", false, "Display the day number each morning. (Vanilla: true)"); SnowStormParticlesMax = (SnowStormParticlesMax = Config.Define<int>(true, "Environment", "SnowStorm Particles Max", -1, Config.AcceptRange<int>(-1, 5000), "Set the snow max particles (Vanilla: 2000-5000)\r\nSet to -1 to disable this setting and use vanilla values\r\n[logout required to revert to vanilla]")); ShowSkyTree.SettingChanged += delegate { if (ZenMod<Plugin>.Initialized) { SetSkyTree(); } else _ = 0; }; ShowWindPixels.SettingChanged += delegate { if (ZenMod<Plugin>.Initialized) { SetWindPixels(); } else _ = 0; }; DayLengthSeconds.SettingChanged += delegate { if (ZenMod<Plugin>.Initialized) { SetDayLength(); } else _ = 0; }; SnowStormParticlesMax.SettingChanged += delegate { if (ZenMod<Plugin>.Initialized) { SetSnowStormParticles(); } else _ = 0; }; } } internal static void Start() { SetDayLength(); SetSkyTree(); SetWindPixels(); SetSnowStormParticles(); } private static bool SetSkyTree() { GameObject val = GameObject.Find("_GameMain/_Environment/YggdrasilBranch"); if (Object.op_Implicit((Object)(object)val)) { val.SetActive(Configs.ShowSkyTree.Value); return true; } Logging<Plugin>.Warning((object)"Unable to set sky tree visibility, node not found", 0); return false; } private static bool SetWindPixels() { GameObject val = GameObject.Find("_GameMain/_Environment/FollowPlayer/GlobalWindParticles/particles_pixel"); if (Object.op_Implicit((Object)(object)val)) { val.SetActive(Configs.ShowWindPixels.Value); return true; } Logging<Plugin>.Warning((object)"Unable to set wind pixels visibility, node not found", 0); return false; } private static bool SetDayLength() { if (Configs.DayLengthSeconds.Value > 0) { if (!ZenMod<Plugin>.IsOnServerAndAllClients) { Logging<Plugin>.Warning((object)"Changing day length requires this mod to be installed on the server and all clients.", 0); return false; } EnvMan.instance.m_dayLengthSec = Configs.DayLengthSeconds.Value; } Logging<Plugin>.Message((object)$"Day Length: {EnvMan.instance.m_dayLengthSec} seconds", 0); return true; } private static bool SetSnowStormParticles() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown int value = Configs.SnowStormParticlesMax.Value; if (value < 0) { return true; } GameObject val = GameObject.Find("_GameMain/_Environment/FollowPlayer"); if (!Object.op_Implicit((Object)(object)val)) { Logging<Plugin>.Warning((object)"Unable to locate environment node, can not set snow storm particles", 0); return false; } foreach (Transform item in val.transform) { Transform val2 = item; if (((Object)val2).name.Contains("SnowStorm")) { SetMaxParticles(((Component)val2).gameObject, value); } } return true; static void SetMaxParticles(GameObject obj, int max) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Logging<Plugin>.Message((object)$"Set max particles for env: {((Object)obj).name} {max}", 0); ParticleSystem[] componentsInChildren = obj.GetComponentsInChildren<ParticleSystem>(); for (int i = 0; i < componentsInChildren.Length; i++) { MainModule main = componentsInChildren[i].main; ((MainModule)(ref main)).maxParticles = max; } } } [HarmonyTranspiler] [HarmonyPatch(typeof(EnvMan), "OnMorning")] [HarmonyPriority(100)] private static IEnumerable<CodeInstruction> EnvMan_OnMorning_Transpile(IEnumerable<CodeInstruction> codes) { MethodInfo methodInfo = AccessTools.Method(typeof(Character), "Message", (Type[])null, (Type[])null); Action<Character, MessageType, string, int, Sprite> action = MorningMessageIntercept; return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)action.Method); static void MorningMessageIntercept(Character p, MessageType type, string msg, int amount, Sprite sprite) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (Configs.ShowDayNumber.Value) { p.Message(type, msg, amount, sprite); } else { Logging<Plugin>.Message((object)("Morning message suppressed: " + msg), 0); } } } } [HarmonyPatch] internal static class Loot { private static class Configs { private const string SECTION_LOOT = "Loot"; public static readonly ConfigEntry<StringList> LootItems = Config.Define<StringList>(true, "Loot", "Loot Items", StringList.Empty, "Comma separated list of items to drop per player.\r\nHildir's Quest items: chest_hildir1, chest_hildir2, chest_hildir3\r\nNOTE: Hildir's Quest items are not enabled by default because \r\nQuest Keys are flagged by proximity to the trader when turning in a chest.\r\nHowever, the item names are provided here for reference if desired."); public static readonly ConfigEntry<bool> LootItemsPerPlayer = Config.Define<bool>(true, "Loot", "Loot Items - Per Player", false, "Drop one Loot Item per player in range so that everyone can have a copy."); public static readonly ConfigEntry<float> LootDropPlayerRange = Config.Define<float>(true, "Loot", "Player Range", 25f, Config.AcceptRange<float>(10f, 100f), "Range to check for players around the area when dropping loot per player."); public static readonly ConfigEntry<int> LootDespawnDays = Config.Define<int>(true, "Loot", "Item Despawn Days", 2, Config.AcceptRange<int>(0, 10), "Items despawn if they are in the wild after this many days. (Vanilla: 3600s aka 2days)\r\nThis opton changes the item despawn timer to use the environment's day duration instead of a fixed constant 3600s.\r\nIf set to 0 will disable this option and revert to vanilla's default static value of 3600s.\r\n(NOTE: If ZenRaids is installed then items are protected by firelight)"); } [HarmonyPostfix] [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] private static void CharacterDrop_GenerateDropList(CharacterDrop __instance, List<KeyValuePair<GameObject, int>> __result) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (!Configs.LootItemsPerPlayer.Value) { return; } int playersInRangeXZ = Player.GetPlayersInRangeXZ(((Component)__instance).transform.position, Configs.LootDropPlayerRange.Value); bool flag = default(bool); for (int i = 0; i < __result.Count; i++) { GameObject key = __result[i].Key; if (Configs.LootItems.Value.Contains(((Object)key).name, true)) { __result[i] = new KeyValuePair<GameObject, int>(key, playersInRangeXZ); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(18, 2, ref flag); if (flag) { val.AppendLiteral("Drop "); val.AppendFormatted(((Object)key).name); val.AppendLiteral(" per player x"); val.AppendFormatted<int>(playersInRangeXZ); } Logging<Plugin>.Info(val, 0); } } } [HarmonyTranspiler] [HarmonyPatch(typeof(ItemDrop), "TimedDestruction")] [HarmonyPriority(100)] private static IEnumerable<CodeInstruction> ItemDrop_TimedDestruction(IEnumerable<CodeInstruction> codes) { Func<float> getDespawnTime = GetDespawnTime; return Transpilers.Manipulator(codes, (Func<CodeInstruction, bool>)IsVanillaDuration, (Action<CodeInstruction>)delegate(CodeInstruction c) { c.opcode = OpCodes.Call; c.operand = getDespawnTime.Method; }); static float GetDespawnTime() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) int value = Configs.LootDespawnDays.Value; float num = ((value > 0) ? ((float)(value * EnvMan.instance.m_dayLengthSec)) : 3600f); bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(20, 1, ref flag); if (flag) { val.AppendLiteral("Item despawn time: "); val.AppendFormatted<float>(num); val.AppendLiteral("s"); } Logging<Plugin>.Debug(val, 0); return num; } static bool IsVanillaDuration(CodeInstruction c) { if (!CodeInstructionExtensions.Is(c, OpCodes.Ldc_R8, (object)3600f)) { return CodeInstructionExtensions.Is(c, OpCodes.Ldc_R4, (object)3600f); } return true; } } } [HarmonyPatch] internal static class LootContainers { private static class Configs { private const string SECTION_LOOT_CONTAINER = "Loot - Containers"; public static readonly ConfigEntry<StringList> LimitedUseContainers; public static readonly ConfigEntry<int> LimitedUseMax; static Configs() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0030: Expected O, but got Unknown StringList val = new StringList(); ((List<string>)val).Add("Player_tombstone"); ((List<string>)val).Add("CargoCrate"); LimitedUseContainers = Config.Define<StringList>(true, "Loot - Containers", "Limited Use Containers", val, "Some containers are free indestructable storage that can be exploited.\r\nAdd any prefab names of containers that should have a limited number of uses before thy self destruct.\r\nContents are dropped on the ground when they break."); LimitedUseMax = Config.Define<int>(true, "Loot - Containers", "Limited Use Max", 5, Config.AcceptRange<int>(1, 9), "The max number of times a limited use container can be opened before it breaks appart."); } } [HarmonyPrefix] [HarmonyPatch(typeof(InventoryGui), "Hide")] [HarmonyPriority(800)] private static void InventoryGui_Hide(InventoryGui __instance) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || ((Character)Player.m_localPlayer).InGodMode()) { return; } Container currentContainer = __instance.m_currentContainer; if (currentContainer.IsLimitedUse()) { currentContainer.m_nview.ClaimOwnership(); ZDO zDO = currentContainer.m_nview.GetZDO(); int @int = zDO.GetInt(ZDOVars.s_pickedUp, 0); @int++; zDO.Set(ZDOVars.s_pickedUp, @int, false); if (currentContainer.GetInventory().NrOfItems() > 0) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$container_decay", 0, (Sprite)null); } if (@int >= Configs.LimitedUseMax.Value) { DestroyAfterDelay(currentContainer); } } } private static void DestroyAfterDelay(Container container) { Container container2 = container; Timing.Delay((MonoBehaviour)(object)container2, 2f, (Action)delegate { if (Object.op_Implicit((Object)(object)container2) && Object.op_Implicit((Object)(object)container2.m_nview) && container2.m_nview.IsValid()) { InventoryGui instance = InventoryGui.instance; if (Object.op_Implicit((Object)(object)instance) && !((Object)(object)instance.m_currentContainer == (Object)(object)container2)) { container2.DropAllItems(); TombStone val = default(TombStone); Destructible val2 = default(Destructible); if (((Component)container2).TryGetComponent<TombStone>(ref val)) { val.UpdateDespawn(); } else if (((Component)container2).TryGetComponent<Destructible>(ref val2)) { val2.Destroy((HitData)null); } else { container2.m_nview.Destroy(); } } } }); } [HarmonyPostfix] [HarmonyPatch(typeof(Container), "GetHoverText")] [HarmonyPriority(100)] private static void Container_GetHoverText(Container __instance, ref string __result) { __result += GetHoverTextContainerDecay(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(TombStone), "GetHoverText")] [HarmonyPriority(100)] private static void TombStone_GetHoverText(TombStone __instance, ref string __result) { __result += GetHoverTextContainerDecay(__instance.m_container); } private static string GetHoverTextContainerDecay(Container c) { if (!c.IsLimitedUse()) { return string.Empty; } ZDO zDO = c.m_nview.GetZDO(); int value = Configs.LimitedUseMax.Value; int num = Mathf.Clamp(zDO.GetInt(ZDOVars.s_pickedUp, 0), 0, value); if (num <= 0) { return string.Empty; } string arg = UI.CreateMeter("◉", "◉", UIColor.MajorInfo, UIColor.DarkOrange, (float)(value - num), (float)value, value); return StringExt.Localize($"\n\n<color={UIColor.MajorInfo}>$container_decay\n{arg}</color>"); } private static bool IsLimitedUse(this Container? c) { if (!Object.op_Implicit((Object)(object)c) || !Object.op_Implicit((Object)(object)c.m_nview) || !c.m_nview.IsValid()) { return false; } string prefabName = c.m_nview.GetPrefabName(); return Configs.LimitedUseContainers.Value.Contains(prefabName, true); } } [HarmonyPatch] internal static class PvPRules { public static class Configs { private const string SECTION_PVP = "PvP"; public static readonly ConfigEntry<Mode> PvPMode; public static readonly ConfigEntry<bool> CanKillTames; public static readonly ConfigEntry<bool> CanHarpoonTames; static Configs() { PvPMode = Config.Define<Mode>(true, "PvP", "PvP Mode", Mode.Toggleable, "The PvP mode for the world"); CanKillTames = Config.Define<bool>(true, "PvP", "Can Kill Tames", false, "Can you kill tames with any weapon in PvP mode, not just the Butcher Knife? (vanilla: true)"); CanHarpoonTames = Config.Define<bool>(true, "PvP", "Can Harpoon Tames", true, "Can you can harpoon tames? Works even when PvP mode is off (vanilla: true)"); } } public enum Mode : byte { Toggleable, War, Peace } private static bool _currentPvP; private const string HarpoonPrefabName = "SpearChitin"; private static bool IsRequired() { return Configs.PvPMode.Value == Mode.War; } private static bool IsHarpoon(this ItemData? weapon) { return ((weapon != null) ? ItemDataExt.GetPrefabName(weapon) : null) == "SpearChitin"; } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Update")] private static void Player_Update(Player __instance) { if (Configs.PvPMode.Value == Mode.Toggleable) { return; } _currentPvP = IsRequired(); if (__instance.m_pvp != _currentPvP) { __instance.SetPVP(_currentPvP); if (Object.op_Implicit((Object)(object)InventoryGui.instance)) { InventoryGui.instance.m_pvp.isOn = _currentPvP; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "CanSwitchPVP")] private static void Player_CanSwitchPVP(ref bool __result) { if (Configs.PvPMode.Value != 0) { __result = false; } } [HarmonyTranspiler] [HarmonyPatch(typeof(Attack), "DoMeleeAttack")] private static IEnumerable<CodeInstruction> Attack_DoMeleeAttack(IEnumerable<CodeInstruction> codes) { return FindHitObject_Intercept(codes); } [HarmonyTranspiler] [HarmonyPatch(typeof(Projectile), "OnHit")] private static IEnumerable<CodeInstruction> Projectile_OnHit(IEnumerable<CodeInstruction> codes) { return FindHitObject_Intercept(codes).AdjustHarpoonDamage(); } private static IEnumerable<CodeInstruction> FindHitObject_Intercept(IEnumerable<CodeInstruction> codes) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(Projectile), "FindHitObject", (Type[])null, (Type[])null), (string)null) }; Func<Collider, object, GameObject> func = HandlePvPAttackForTames; return new CodeMatcher(codes, (ILGenerator)null).Start().MatchStartForward(array).ThrowIfInvalid("Unable to match IL sequence") .Set(OpCodes.Call, (object)func.Method) .Insert((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Ldarg_0, (object)null) }) .InstructionEnumeration(); static GameObject? HandlePvPAttackForTames(Collider collider, object caller) { GameObject val = Projectile.FindHitObject(collider); if (!Object.op_Implicit((Object)(object)val)) { return null; } if (Configs.CanKillTames.Value) { return val; } Attack val2 = (Attack)((caller is Attack) ? caller : null); (Character, ItemData) tuple; if (val2 == null) { Projectile val3 = (Projectile)((caller is Projectile) ? caller : null); tuple = ((val3 == null) ? (null, null) : (val3.m_owner, val3.m_weapon)); } else { tuple = ((Character)(object)val2.m_character, val2.m_weapon); } var (val4, val5) = tuple; if (!Object.op_Implicit((Object)(object)val4) || !val4.IsPlayer() || val5 == null) { return val; } Character component = val.GetComponent<Character>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsTamed()) { return val; } if (val5.m_shared.m_tamedOnly) { return val; } if (Configs.CanHarpoonTames.Value && val5.IsHarpoon()) { Logging<Plugin>.Info("Harpooned!", 0); return val; } return ((Component)val4).gameObject; } } [HarmonyTranspiler] [HarmonyPatch(typeof(Projectile), "IsValidTarget")] private static IEnumerable<CodeInstruction> Projectile_IsValidTarget(IEnumerable<CodeInstruction> codes) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.DeclaredMethod(typeof(Character), "IsPVPEnabled", (Type[])null, (Type[])null), (string)null) }; Func<bool, Projectile, IDestructible, bool> func = IsHarpoonAttack; CodeInstruction[] array2 = (CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)func.Method) }; return new CodeMatcher(codes, (ILGenerator)null).MatchStartForward(array).ThrowIfInvalid("Unable to match IL sequence").Advance(1) .Insert(array2) .InstructionEnumeration(); static bool IsHarpoonAttack(bool isPvPEnabled, Projectile projectile, IDestructible dest) { int num; if (Configs.CanHarpoonTames.Value) { Character val = (Character)(object)((dest is Character) ? dest : null); if (val != null && val.IsTamed()) { num = (projectile.m_weapon.IsHarpoon() ? 1 : 0); goto IL_002c; } } num = 0; goto IL_002c; IL_002c: return (byte)((uint)num | (isPvPEnabled ? 1u : 0u)) != 0; } } private static IEnumerable<CodeInstruction> AdjustHarpoonDamage(this IEnumerable<CodeInstruction> codes) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.DeclaredField(typeof(Projectile), "m_damage"), (string)null), new CodeMatch((OpCode?)OpCodes.Stfld, (object)AccessTools.DeclaredField(typeof(HitData), "m_damage"), (string)null) }; Func<DamageTypes, Projectile, IDestructible, DamageTypes> func = HarpoonDamage; CodeInstruction[] array2 = (CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldloc_S, (object)(byte)4), new CodeInstruction(OpCodes.Call, (object)func.Method) }; return new CodeMatcher(codes, (ILGenerator)null).Start().MatchEndForward(array).ThrowIfInvalid("Unable to match IL sequence") .Insert(array2) .InstructionEnumeration(); static DamageTypes HarpoonDamage(DamageTypes vanillaDamages, Projectile projectile, IDestructible destructible) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (Configs.CanHarpoonTames.Value && projectile.m_weapon.IsHarpoon()) { Character val = (Character)(object)((destructible is Character) ? destructible : null); if (val != null && val.IsTamed()) { return default(DamageTypes); } } return vanillaDamages; } } } [HarmonyPatch] internal static class Quests { public static class Configs { private const string SECTION_QUESTS = "Quests"; public static readonly ConfigEntry<bool> PerPlayerQuests = Config.Define<bool>(true, "Quests", "Active Per Player", true, "Quests such as Hidler's Quest are per player instead of worldwide. (Vanilla: false)"); public static readonly ConfigEntry<StringList> QuestKeys; public static readonly ConfigEntry<float> QuestKeyRange; public static readonly ConfigEntry<StringList> QuestTraders; static Configs() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0056: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00f0: Expected O, but got Unknown StringList val = new StringList(); ((List<string>)val).Add("Hildir1"); ((List<string>)val).Add("Hildir2"); ((List<string>)val).Add("Hildir3"); QuestKeys = Config.Define<StringList>(true, "Quests", "Quest Keys", val, "Comma separated list conditional keys used to flag quest status.\r\nNormally these are global keys, define them here to treat them as per player keys instead.\r\nNOTE: when debugging you can manually add/remove these keys to your player keys.\r\nHowever, you will need to leave the area for the scene to reload before you can see the changes.\r\nYou can view the active keys via the vanilla console command: listkeys\r\nGoogle for more info on vanilla key commands."); QuestKeyRange = Config.Define<float>(true, "Quests", "Quest Key Range", 20f, Config.AcceptRange<float>(0f, 100f), "When performing an action that applies a Quest Key, such as turning in a quest item, \r\nall players in the area will also be flagged with the key.\r\nThis way you have the option to share rewards without duplicating quest loot.\r\nInstead, replicate the reward flag to all players nearby when turning in a quest item.\r\nSet to 0 to disable this feature."); StringList val2 = new StringList(); ((List<string>)val2).Add("Hildir"); QuestTraders = Config.Define<StringList>(true, "Quests", "Quest Traders", val2, "Comma separated list of traders which give quests which use " + ((ConfigEntryBase)QuestKeys).Definition.Key + "\r\nThey have inventories determined by " + ((ConfigEntryBase)QuestKeys).Definition.Key + "\r\nNormally the global keys are checked. This will force them to use per player keys instead."); } } [HarmonyPatch] private static class ActiveTrader { private static Trader? _trader; public static bool IsAllowed() { Trader trader; return IsAllowed(out trader); } public static bool IsAllowed(out Trader trader) { trader = null; if (!Object.op_Implicit((Object)(object)_trader)) { return true; } trader = _trader; string prefabName = GameObjectExt.GetPrefabName(((Component)_trader).gameObject); return Configs.QuestTraders.Value.Contains(prefabName, true); } [UsedImplicitly] private static IEnumerable<MethodInfo> TargetMethods() { return new <>z__ReadOnlyArray<MethodInfo>(new MethodInfo[2] { AccessTools.DeclaredMethod(typeof(Trader), "UseItem", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(Trader), "Interact", (Type[])null, (Type[])null) }); } [UsedImplicitly] private static void Prefix(Trader __instance) { _trader = __instance; } [UsedImplicitly] private static void Postfix(Trader __instance) { _trader = null; } } [HarmonyPatch] private static class TraderTranspiler { [UsedImplicitly] private static IEnumerable<MethodInfo> TargetMethods() { return new <>z__ReadOnlyArray<MethodInfo>(new MethodInfo[2] { AccessTools.DeclaredMethod(typeof(Trader), "UseItem", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(Trader), "GetAvailableItems", (Type[])null, (Type[])null) }); } [UsedImplicitly] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> codes) { return GlobalToPlayerKeys(codes); } } internal static void RegisterRPC() { ZRoutedRpc.instance.Register<Vector3, string>("RPC_SetKeyProximity", (Action<long, Vector3, string>)RPC_SetKeyProximity); } internal static void Shutdown() { if (ZRoutedRpc.instance != null) { ZRoutedRpcExt.Unregister(ZRoutedRpc.instance, "RPC_SetKeyProximity"); } } private static bool IsPerPlayerQuestKey(string key) { return Configs.QuestKeys.Value.Contains(key, true); } private static void SetKey(string key) { //IL_005d: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (!Configs.PerPlayerQuests.Value || !IsPerPlayerQuestKey(key)) { ZoneSystem.instance.SetGlobalKey(key); return; } ((Humanoid)Player.m_localPlayer).AddUniqueKey(key); if (!(Configs.QuestKeyRange.Value <= 0f)) { Trader trader; Vector3 val = (ActiveTrader.IsAllowed(out trader) ? ((Component)trader).transform.position : ((Component)Player.m_localPlayer).transform.position); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RPC_SetKeyProximity", new object[2] { val, key }); } } private static void RPC_SetKeyProximity(long sender, Vector3 position, string key) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!ZNet.instance.IsDedicated() && ZDOMan.GetSessionID() != sender && MathExt.DistanceTo((MonoBehaviour)(object)Player.m_localPlayer, position) < Configs.QuestKeyRange.Value) { ((Humanoid)Player.m_localPlayer).AddUniqueKey(key); } } private static bool GetKey(string key) { if (!Configs.PerPlayerQuests.Value || !ActiveTrader.IsAllowed() || !IsPerPlayerQuestKey(key)) { return ZoneSystem.instance.GetGlobalKey(key); } if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return ((Humanoid)Player.m_localPlayer).HaveUniqueKey(key); } return false; } [HarmonyPostfix] [HarmonyPatch(typeof(ConditionalObject), "ShouldBeVisible")] private static void ConditionalObject_ShouldBeVisible(ConditionalObject __instance, ref bool __result) { string globalKeyCondition = __instance.m_globalKeyCondition; if (!Utility.IsNullOrWhiteSpace(globalKeyCondition) && IsPerPlayerQuestKey(globalKeyCondition)) { __result = GetKey(__instance.m_globalKeyCondition); } } private static IEnumerable<CodeInstruction> GlobalToPlayerKeys(IEnumerable<CodeInstruction> codes) { return Transpilers.Manipulator(Transpilers.Manipulator(Transpilers.Manipulator(codes, (Func<CodeInstruction, bool>)ZoneSystemInstance, (Action<CodeInstruction>)Nop), (Func<CodeInstruction, bool>)GetGlobalKey, (Action<CodeInstruction>)GetPlayerKey), (Func<CodeInstruction, bool>)SetGlobalKey, (Action<CodeInstruction>)SetPlayerKey); static bool GetGlobalKey(CodeInstruction c) { MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(ZoneSystem), "GetGlobalKey", new Type[1] { typeof(string) }, (Type[])null); if (c.opcode == OpCodes.Callvirt) { return (MethodInfo)c.operand == methodInfo2; } return false; } static void GetPlayerKey(CodeInstruction c) { Func<string, bool> func = GetKey; c.opcode = OpCodes.Call; c.operand = func.Method; } static void Nop(CodeInstruction c) { c.opcode = OpCodes.Nop; c.operand = null; } static bool SetGlobalKey(CodeInstruction c) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZoneSystem), "SetGlobalKey", new Type[1] { typeof(string) }, (Type[])null); if (c.opcode == OpCodes.Callvirt) { return (MethodInfo)c.operand == methodInfo; } return false; } static void SetPlayerKey(CodeInstruction c) { Action<string> action = SetKey; c.opcode = OpCodes.Call; c.operand = action.Method; } static bool ZoneSystemInstance(CodeInstruction c) { MethodInfo methodInfo3 = AccessTools.PropertyGetter(typeof(ZoneSystem), "instance"); if (c.opcode == OpCodes.Call) { return (MethodInfo)c.operand == methodInfo3; } return false; } } } [HarmonyPatch] internal static class ShieldGen { public static class Configs { private const string SECTION_SHIELDGEN = "Shield Generator"; public static readonly ConfigEntry<bool> EnableEjectFuel = Config.Define<bool>(true, "Shield Generator", "Enable Eject Fuel", true, "Add an option to eject the fuel on shield generators and cause them to shutdown."); public static readonly ConfigEntry<bool> ShieldProtectsFireFromRain = Config.Define<bool>(true, "Shield Generator", "Shield Protects Fire From Rain", true, "Shield Generator protects fireplaces from the rain so they stay lit without a roof. (Vanilla: False)"); } public static void Start() { ZRoutedRpc.instance.Register<ZDOID>("RPC_EjectShieldFuel", (Action<long, ZDOID>)RPC_EjectShieldFuel); } public static void Shutdown() { ZRoutedRpcExt.Unregister(ZRoutedRpc.instance, "RPC_EjectShieldFuel"); } private static void RPC_EjectShieldFuel(long sender, ZDOID shieldGenID) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) GameObject val = ZNetScene.instance.FindInstance(shieldGenID); if (!Object.op_Implicit((Object)(object)val)) { Logging<Plugin>.Error((object)$"Shield Generator not found for ZDOID: {shieldGenID}", (ushort)0); } else { EjectFuel(val.GetComponent<ShieldGenerator>()); } } private static GameObject GetFuelPrefab(ShieldGenerator shieldGenerator) { return ZNetScene.instance.GetPrefab("BoneFragments"); } private static void EjectFuel(ShieldGenerator shieldGenerator) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (shieldGenerator.m_nview.IsOwner()) { int num = Mathf.CeilToInt(shieldGenerator.GetFuel()); GameObject fuelPrefab = GetFuelPrefab(shieldGenerator); Transform transform = ((Component)shieldGenerator).transform; for (int i = 0; i < num; i++) { Vector3 val = transform.position + transform.forward + Vector3.up + Random.insideUnitSphere * 0.3f; Quaternion val2 = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f); Object.Instantiate<GameObject>(fuelPrefab, val, val2).GetComponent<ItemDrop>().m_autoPickup = false; } shieldGenerator.m_nview.GetZDO().Set(ZDOVars.s_fuel, 0f); shieldGenerator.m_fuelAddedEffects.Create(transform.position, transform.rotation, transform, 1f, -1); } } [HarmonyPostfix] [HarmonyPatch(typeof(Switch), "GetHoverText")] private static void Switch_ShieldGenerator_GetHoverText(Switch __instance, ref string __result) { if (Configs.EnableEjectFuel.Value && WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false)) { ShieldGenerator componentInParent = ((Component)__instance).GetComponentInParent<ShieldGenerator>(); if (Object.op_Implicit((Object)(object)componentInParent) && componentInParent.GetFuel() > 0f) { __result += Localization.instance.Localize("\n" + UI.PromptInteractAlt + " $hud_remove $piece_shieldgenerator_fuelname"); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Switch), "Interact")] private static void Switch_ShieldGenerator_Interact(Switch __instance, bool alt, ref bool __result, ref bool __runOriginal) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (!Configs.EnableEjectFuel.Value || !alt) { return; } if (!WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false)) { __result = false; __runOriginal = false; return; } ShieldGenerator componentInParent = ((Component)__instance).GetComponentInParent<ShieldGenerator>(); if (Object.op_Implicit((Object)(object)componentInParent)) { ZDO zDO = componentInParent.m_nview.GetZDO(); ZRoutedRpc.instance.InvokeRoutedRPC(zDO.GetOwner(), "RPC_EjectShieldFuel", new object[1] { zDO.m_uid }); __runOriginal = false; } } [HarmonyPostfix] [HarmonyPatch(typeof(Fireplace), "CheckWet")] private static void Fireplace_CheckWet(Fireplace __instance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (__instance.m_wet && Configs.ShieldProtectsFireFromRain.Value) { __instance.m_wet = !ShieldGenerator.IsInsideShield(((Component)__instance).transform.position); } } } [HarmonyPatch] internal static class ShipRules { public static class Configs { public static readonly ConfigEntry<float> ShipRefundPercent; public static readonly ConfigEntry<bool> ShipSafeHarbor; public static readonly ConfigEntry<bool> ShipRename; public static readonly ConfigEntry<bool> ShipOwnerIsCaptain; public static readonly ConfigEntry<bool> ShipCaptainClaimZDO; public static readonly ConfigEntry<bool> ShipNoSuddenStop; public static readonly ConfigEntry<bool> ShipLadderDisembark; static Configs() { ShipCaptainClaimZDO = Config.Define<bool>(true, "Ships", "Captain Claims Control", true, "The ship captain takes control of the ZDO.\r\nWhen the captain is at the rudder the storage can not be opened.\r\nWhen the storage is open the rudder can not be used.\r\n[Help ships feel more responsive in multiplayer games since the ship simulation is run by the captain's CPU]\r\n(vanilla: false)"); ShipRename = Config.Define<bool>(true, "Ships", "Rename Ships", true, "Ships can be renamed by interacting with the rudder.\r\nOnly the person who owns the ship can rename it.\r\nA ship without a name has no owner.\r\n[Admin in god mode can always rename ships]"); ShipOwnerIsCaptain = Config.Define<bool>(true, "Ships", "Owner Is Captain", false, "Only the ship owner can pilot the ship.\r\nIf the ship has no owner anyone can pilot it.\r\nA ship is owned by the person who named it.\r\n[Has no effect if " + ((ConfigEntryBase)ShipRename).Definition.Key + " is false]\r\n[Admin in god mode can always pilot ships]\r\n(vanilla: false)"); ShipRefundPercent = Config.Define<float>(true, "Ships", "Refund Percent", 0.5f, Config.AcceptRange<float>(0f, 1f), "The percentage of the ship's construction materials refunded when destroyed. (Vanilla: 100%)\r\n[Default is 50% to discourage boat-in-a-box]"); ShipSafeHarbor = Config.Define<bool>(true, "Ships", "Safe Harbor", true, "Ships are ignored by monsters when no crew is onboard. (Vanilla: false)\r\nHowever, if you were on the ship and then jump off while a monster was nearby they may still attack the ship.\r\nThis helps to protect ships in the harbor from being attacked by monsters when nobody is around.\r\nBut if you are onboard they will see you and attack and may keep attacking the ship even once you disembark."); ShipNoSuddenStop = Config.Define<bool>(true, "Ships", "No Sudden Stop", true, "Ships do not suddenly stop when everyone jumps off. They drift a short distance and then stop.\r\nIt's more immersive. Dock correctly or run into the rocks, your choice. (vanilla: false)"); ShipLadderDisembark = Config.Define<bool>(true, "Ships", "Ship Ladder Can Disembark", true, "You can use ship ladders to disembark from a ship.\r\n(Vanilla: false)"); } } [HarmonyPatch] private static class NoCrew { [UsedImplicitly] private static IEnumerable<MethodInfo> TargetMethods() { return new <>z__ReadOnlyArray<MethodInfo>(new MethodInfo[2] { AccessTools.DeclaredMethod(typeof(Piece), "IsPriorityTarget", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(Piece), "IsRandomTarget", (Type[])null, (Type[])null) }); } [UsedImplicitly] private static void Prefix(Piece __instance, ref bool __runOriginal, ref bool __result) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (Configs.ShipSafeHarbor.Value && __instance.IsPlayerCreatedShip(out Ship ship) && !ship.HasPlayerOnboard()) { bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(45, 1, ref flag); if (flag) { val.AppendLiteral("Safe Harbor: No crew on "); val.AppendFormatted(((Object)__instance).name); val.AppendLiteral(", not a valid target."); } Logging<Plugin>.Info(val, 0); __runOriginal = (__result = false); } } } [HarmonyPatch] private static class ShipCaptain { private static string GetShipName(ZNetView? nview, bool formatted = true) { if (!Object.op_Implicit((Object)(object)nview) || !nview.IsValid()) { return string.Empty; } string @string = nview.GetZDO().GetString(ZDOVars.s_tamedName, ""); long @long = nview.GetZDO().GetLong(ZDOVars.s_owner, 0L); if (Utility.IsNullOrWhiteSpace(@string) || @long == 0L) { return string.Empty; } if (!formatted) { return @string; } return $"\n<color={UIColor.MinorInfo}>{@string}</color>"; } private static bool IsShipOwner(Player? player, ZNetView? nview) { string ownerName; long ownerID; return IsShipOwner(player, nview, out ownerName, out ownerID); } private static bool IsShipOwner(Player? player, ZNetView? nview, out string ownerName, out long ownerID) { if (!Object.op_Implicit((Object)(object)player) || !Object.op_Implicit((Object)(object)nview) || !nview.IsValid()) { ownerID = 0L; ownerName = string.Empty; return false; } ownerID = nview.GetZDO().GetLong(ZDOVars.s_owner, 0L); ownerName = nview.GetZDO().GetString(ZDOVars.s_ownerName, ""); if (ownerID == 0L || ((Character)player).InGodMode()) { return true; } return player.GetPlayerID() == ownerID; } [HarmonyPostfix] [HarmonyPatch(typeof(ShipControlls), "GetHoverText")] private static void ShipControls_GetHoverText(ShipControlls __instance, ref string __result) { if (Configs.ShipRename.Value && __instance.InUseDistance((Humanoid)(object)Player.m_localPlayer)) { string text = StringExt.Localize("\n" + UI.PromptInteractAlt + " $hud_rename"); if (!IsShipOwner(Player.m_localPlayer, __instance.m_nview)) { text = "<s>" + text + "</s>"; } __result += StringExt.Localize(text); __result += GetShipName(__instance.m_nview); } } [HarmonyPostfix] [HarmonyPatch(typeof(Chair), "GetHoverText")] private static void ShipChair_GetHoverText(Chair __instance, ref string __result) { if (Configs.ShipRename.Value && __instance.m_inShip && __instance.InUseDistance((Humanoid)(object)Player.m_localPlayer)) { ZNetView componentInParent = ((Component)__instance).GetComponentInParent<ZNetView>(); __result += GetShipName(componentInParent); } } [HarmonyPrefix] [HarmonyPatch(typeof(ShipControlls), "Interact")] private static void ShipControls_Interact(ShipControlls __instance, Humanoid character, bool repeat, bool alt, ref bool __runOriginal, ref bool __result) { ShipControlls __instance2 = __instance; Humanoid character2 = character; if (!Configs.ShipRename.Value || !__instance2.InUseDistance(character2)) { return; } if (!alt) { if (Configs.ShipOwnerIsCaptain.Value && !CheckOwner(out var _)) { __runOriginal = false; __result = true; } return; } __runOriginal = false; if (repeat) { return; } __result = true; if (!CheckOwner(out var ownerID)) { return; } string shipName2 = GetShipName(__instance2.m_nview, formatted: false); TextPrompt.Show("$hud_rename", shipName2, (Action<string>)delegate(string shipName) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) shipName = shipName.Trim(); __instance2.m_nview.ClaimOwnership(); ZDO zDO = __instance2.m_nview.GetZDO(); Player val = (Player)character2; bool flag = !Utility.IsNullOrWhiteSpace(shipName); bool num = PlayerExt.IsGodMode(val) && val.GetPlayerID() != ownerID && ownerID != 0; zDO.Set(ZDOVars.s_tamedName, shipName); if (num && flag) { ((Character)val).Message((MessageType)2, "Ship renamed by Admin - Existing owner not changed", 0, (Sprite)null); Logging<Plugin>.Info("Ship renamed by Admin - Existing owner not changed", 0); } else { bool flag2 = default(bool); InterpolatedString<Plugin> val2 = new InterpolatedString<Plugin>(17, 2, ref flag2); if (flag2) { val2.AppendLiteral("Renamed ship: "); val2.AppendFormatted(shipName); val2.AppendLiteral(" @ "); val2.AppendFormatted<Vector3>(MathExt.XZY(((Component)val).transform.position)); } Logging<Plugin>.Info(val2, 0); zDO.Set(ZDOVars.s_owner, flag ? val.GetPlayerID() : 0); zDO.Set(ZDOVars.s_ownerName, flag ? val.GetPlayerName() : string.Empty); } }, 15); bool CheckOwner(out long id) { Humanoid obj = character2; if (IsShipOwner((Player?)(object)((obj is Player) ? obj : null), __instance2.m_nview, out string ownerName, out id)) { return true; } if (!Utility.IsNullOrWhiteSpace(ownerName)) { Piece componentInParent = ((Component)__instance2).GetComponentInParent<Piece>(); if (Object.op_Implicit((Object)(object)componentInParent)) { ((Character)character2).Message((MessageType)1, "$piece_guardstone_owner " + ownerName, 0, componentInParent.m_icon); } } ((Character)character2).Message((MessageType)2, "$ship_not_owner", 0, (Sprite)null); return false; } } } private static double _lastDisembarkTime; private static bool IsPlayerCreatedShip(this Piece? piece) { Ship ship; return piece.IsPlayerCreatedShip(out ship); } private static bool IsPlayerCreatedShip(this Piece? piece, out Ship ship) { if (Object.op_Implicit((Object)(object)piece) && piece.IsPlacedByPlayer()) { ship = ((Component)piece).GetComponent<Ship>(); return Object.op_Implicit((Object)(object)ship); } ship = null; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Ladder), "Interact")] private static void Ladder_Interact(Ladder __instance, Humanoid character, bool hold, bool alt, ref bool __runOriginal) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!Configs.ShipLadderDisembark.Value) { return; } if (Time.timeAsDouble < _lastDisembarkTime + 1.0) { Logging<Plugin>.Info("Disembark cooldown not expired, wait a moment", 0); __runOriginal = false; return; } bool flag = __instance.InUseDistance(character); if (!(hold || alt) && flag) { if (!Object.op_Implicit((Object)(object)((Character)character).GetStandingOnShip())) { Logging<Plugin>.Info("Not standing on ship, using vanilla ladder behavior.", 0); return; } Logging<Plugin>.Info("Disembarking from ship", 0); _lastDisembarkTime = Time.timeAsDouble; __runOriginal = false; Transform targetPos = __instance.m_targetPos; Vector3 val = -targetPos.forward; val.y = 0f; Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 val2 = targetPos.position + normalized * 1.5f; ((Component)character).transform.SetPositionAndRotation(val2, Quaternion.LookRotation(normalized, Vector3.up)); Physics.SyncTransforms(); } } [HarmonyTranspiler] [HarmonyPatch(typeof(Piece), "DropResources")] private static IEnumerable<CodeInstruction> Piece_DropResources(IEnumerable<CodeInstruction> codes, ILGenerator gen) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(Requirement), "m_amount"), (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_S, (object)null, (string)null) }; Func<int, Piece, Requirement, int> func = AdjustAmount; CodeInstruction[] array2 = (CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldloc_S, (object)(byte)4), new CodeInstruction(OpCodes.Call, (object)func.Method) }; return new CodeMatcher(codes, gen).MatchEndForward(array).ThrowIfInvalid("Unable to match IL sequence").Insert(array2) .InstructionEnumeration(); static int AdjustAmount(int amount, Piece piece, Requirement resource) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (!piece.IsPlayerCreatedShip()) { return amount; } float value = Configs.ShipRefundPercent.Value; int num = Mathf.RoundToInt((float)amount * value); ItemDrop resItem = resource.m_resItem; string text = ((resItem != null) ? ItemDataExt.GetPrefabName(resItem) : null) ?? "Unknown"; bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(19, 4, ref flag); if (flag) { val.AppendLiteral("Ship refund "); val.AppendFormatted(((Object)piece).name); val.AppendLiteral(" "); val.AppendFormatted(text); val.AppendLiteral(": "); val.AppendFormatted<float>(value * 100f, "n0"); val.AppendLiteral("% = "); val.AppendFormatted<int>(num); } Logging<Plugin>.Info(val, 0); return num; } } [HarmonyTranspiler] [HarmonyPatch(typeof(Container), "RPC_RequestOpen")] private static IEnumerable<CodeInstruction> Container_RPC_RequestOpen(IEnumerable<CodeInstruction> codes) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Container), "IsInUse", (Type[])null, (Type[])null); Func<bool, Container, bool> func = IsShipInUse; CodeInstruction[] array = (CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Call, (object)func.Method) }; return new CodeMatcher(codes, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)methodInfo, (string)null) }).ThrowIfInvalid("Unable to match IL").Advance(1) .Insert(array) .InstructionEnumeration(); static bool IsShipInUse(bool isContainerInUse, Container container) { if (!Configs.ShipCaptainClaimZDO.Value) { return isContainerInUse; } if (isContainerInUse) { return true; } Ship val = default(Ship); if (Object.op_Implicit((Object)(object)container.m_nview) && ((Component)container.m_nview).TryGetComponent<Ship>(ref val)) { return val.HaveControllingPlayer(); } return false; } } [HarmonyTranspiler] [HarmonyPatch(typeof(ShipControlls), "RPC_RequestControl")] private static IEnumerable<CodeInstruction> ShipControls_RequestControl(IEnumerable<CodeInstruction> codes) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ShipControlls), "HaveValidUser", (Type[])null, (Type[])null); Func<ShipControlls, bool> func = IsValidUserOrContainerInUse; CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.DeclaredField(typeof(ShipControlls), "m_nview"), (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.DeclaredMethod(typeof(ZNetView), "GetZDO", (Type[])null, (Type[])null), (string)null) }; Func<ZDO, long, ZDO> func2 = SetOwner; CodeInstruction[] array2 = (CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)func2.Method) }; return Transpilers.MethodReplacer(new CodeMatcher(codes, (ILGenerator)null).MatchEndForward(array).ThrowIfInvalid("Unable to match IL sequence").Advance(1) .Insert(array2) .InstructionEnumeration(), (MethodBase)methodInfo, (MethodBase)func.Method); static bool IsValidUserOrContainerInUse(ShipControlls shipControls) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!Configs.ShipCaptainClaimZDO.Value) { return shipControls.HaveValidUser(); } if (shipControls.HaveValidUser()) { return true; } bool flag2 = shipControls.m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1; bool flag3 = default(bool); InterpolatedString<Plugin> val2 = new InterpolatedString<Plugin>(21, 1, ref flag3); if (flag3) { val2.AppendLiteral("Ship storage in use? "); val2.AppendFormatted<bool>(flag2); } Logging<Plugin>.Info(val2, 0); return flag2; } static ZDO SetOwner(ZDO zdo, long uid) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (Configs.ShipCaptainClaimZDO.Value) { bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(28, 1, ref flag); if (flag) { val.AppendLiteral("Assign ship ZDO to captain: "); val.AppendFormatted<long>(uid); } Logging<Plugin>.Info(val, 0); zdo.SetOwner(uid); } return zdo; } } [HarmonyTranspiler] [HarmonyPatch(typeof(Ship), "CustomFixedUpdate")] [HarmonyPriority(100)] private static IEnumerable<CodeInstruction> Ship_CustomFixedUpdate(IEnumerable<CodeInstruction> codes) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Expected O, but got Unknown Func<int, int> func = GetShipPlayerCountIntercept; CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[4] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.DeclaredField(typeof(Ship), "m_players"), (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.DeclaredPropertyGetter(typeof(List<Player>), "Count"), (string)null), new CodeMatch((OpCode?)OpCodes.Brtrue, (object)null, (string)null) }; Func<Vector3, Ship, float, Vector3> func2 = AdjustVelocity; CodeMatch[] array2 = (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.DeclaredPropertySetter(typeof(Rigidbody), "linearVelocity"), (string)null) }; CodeInstruction[] array3 = (CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)func2.Method) }; return new CodeMatcher(codes, (ILGenerator)null).End().MatchStartBackwards(array2).ThrowIfInvalid("Unable to match set velocity IL") .Insert(array3) .MatchEndBackwards(array) .ThrowIfInvalid("Unable to match ship player count IL") .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)func.Method) }) .InstructionEnumeration(); static Vector3 AdjustVelocity(Vector3 original, Ship ship, float fixedDeltaTime) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!Configs.ShipNoSuddenStop.Value || ship.HasPlayerOnboard()) { return original; } Vector3 zero = Vector3.zero; zero.y = original.y; Vector3 val = zero; return Vector3.MoveTowards(original, val, fixedDeltaTime * 0.3f); } static int GetShipPlayerCountIntercept(int shipPlayerCount) { if (!Configs.ShipNoSuddenStop.Value) { return shipPlayerCount; } return Mathf.Max(1, shipPlayerCount); } } } [HarmonyPatch] internal static class SpawnerRules { private struct SpawnRule { public ConfigEntry<StringList> BlockedGlobalKeys; public ConfigEntry<StringList> BlockedPrefabs; public ConfigEntry<StringList> AllowedPrefabs; public ConfigEntry<bool> DisableHuntPlayer; } private static class Configs { private const string SECTION_SPAWNERS = "Spawners"; public static readonly ConfigEntry<bool> EnableSpawnRules; public static readonly Dictionary<Biome, SpawnRule> BiomeRules; private const string KilledEikthyr = "defeated_eikthyr"; private const string KilledTheElder = "defeated_gdking"; private const string KilledBonemass = "defeated_bonemass"; private const string KilledDragon = "defeated_dragon"; private const string KilledGoblinKing = "defeated_goblinking"; private const string KilledQueen = "defeated_queen"; private const string KilledFader = "defeated_fader"; private static readonly List<Biome> BiomeOrder; private static readonly Dictionary<Biome, StringList> DefaultBlockedKeys; static Configs() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_0098: Unknown result type (might be