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 HH Mods v1.0.0
Plugins/Advize_PlantEverything.dll
Decompiled 2 years 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.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using SoftReferenceableAssets; using TMPro; using UnityEngine; [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyFileVersion("1.18.0.0")] [assembly: Guid("85f3bb36-d51d-4e6c-a523-feb593b3156f")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyProduct("Valheim Game Modification")] [assembly: AssemblyCompany("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("Advize_PlantEverything")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.18.0.0")] [module: <f9f9a229-dc19-4d38-b6fb-0b374d4210b5>RefSafetyRules(11)] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<5c57a976-0286-4c7f-aa8d-e0175835a3be>Embedded] internal sealed class <5c57a976-0286-4c7f-aa8d-e0175835a3be>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [<5c57a976-0286-4c7f-aa8d-e0175835a3be>Embedded] internal sealed class <620737d2-74a2-4263-8f12-353eee49a0ff>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <620737d2-74a2-4263-8f12-353eee49a0ff>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <620737d2-74a2-4263-8f12-353eee49a0ff>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [<5c57a976-0286-4c7f-aa8d-e0175835a3be>Embedded] [CompilerGenerated] internal sealed class <baed80af-2136-4897-bc60-57e517bae1ff>NullableContextAttribute : Attribute { public readonly byte Flag; public <baed80af-2136-4897-bc60-57e517bae1ff>NullableContextAttribute(byte P_0) { Flag = P_0; } } [<5c57a976-0286-4c7f-aa8d-e0175835a3be>Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [CompilerGenerated] internal sealed class <f9f9a229-dc19-4d38-b6fb-0b374d4210b5>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <f9f9a229-dc19-4d38-b6fb-0b374d4210b5>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Advize_PlantEverything { internal static class ConfigEventHandlers { internal static void CoreSettingChanged(object o, EventArgs e) { PlantEverything.Dbgl("Config setting changed, re-initializing mod", forceLog: false, (LogLevel)16); PlantEverything.InitPieceRefs(); PlantEverything.InitPieces(); PlantEverything.InitSaplingRefs(); PlantEverything.InitSaplings(); PlantEverything.InitCrops(); PlantEverything.InitVines(); PlantEverything.InitCultivator(); } internal static void PieceSettingChanged(object o, EventArgs e) { PlantEverything.Dbgl("Config setting changed, re-initializing pieces", forceLog: false, (LogLevel)16); PlantEverything.InitPieceRefs(); PlantEverything.InitPieces(); PlantEverything.InitCultivator(); } internal static void SaplingSettingChanged(object o, EventArgs e) { PlantEverything.Dbgl("Config setting changed, re-initializing saplings", forceLog: false, (LogLevel)16); PlantEverything.InitSaplingRefs(); PlantEverything.InitSaplings(); PlantEverything.InitCultivator(); } internal static void SeedSettingChanged(object o, EventArgs e) { PlantEverything.Dbgl("Config setting changed, modifying TreeBase drop tables", forceLog: false, (LogLevel)16); PlantEverything.ModifyTreeDrops(); } internal static void CropSettingChanged(object o, EventArgs e) { PlantEverything.Dbgl("Config setting changed, re-initializing crops", forceLog: false, (LogLevel)16); PlantEverything.InitCrops(); } internal static void VineSettingChanged(object o, EventArgs e) { PlantEverything.Dbgl("Config setting changed, re-initializing vines", forceLog: false, (LogLevel)16); PlantEverything.InitVines(); } internal static void ExtraResourcesChanged() { PlantEverything.Dbgl("ExtraResourcesChanged", forceLog: false, (LogLevel)16); PlantEverything.deserializedExtraResources.Clear(); foreach (string item2 in PlantEverything.config.SyncedExtraResources.Value) { ExtraResource item = PluginUtils.DeserializeExtraResource(item2); PlantEverything.deserializedExtraResources.Add(item); } if (Object.op_Implicit((Object)(object)ZNetScene.s_instance)) { PlantEverything.InitExtraResourceRefs(ZNetScene.s_instance); PieceSettingChanged(null, null); } } internal static void ExtraResourcesFileOrSettingChanged(object sender, EventArgs e) { PlantEverything.Dbgl("ExtraResources file or setting has changed", forceLog: false, (LogLevel)16); if (PlantEverything.config.IsSourceOfTruth) { if (PlantEverything.config.EnableExtraResources) { PlantEverything.Dbgl("IsSourceOfTruth: true, loading extra resources from disk", forceLog: false, (LogLevel)16); PluginUtils.LoadExtraResources(); } else { PlantEverything.config.SyncedExtraResources.AssignLocalValue(new List<string>()); } } else { PlantEverything.Dbgl("IsSourceOfTruth: false, extra resources will not be loaded from disk", forceLog: false, (LogLevel)16); } } } internal struct ExtraResource { public string prefabName; public string resourceName; public int resourceCost; public bool groundOnly; public string pieceName; public string pieceDescription; internal readonly bool IsValid() { if (prefabName != null && !prefabName.StartsWith("PE_Fake") && resourceName != null) { return resourceCost != 0; } return false; } } internal sealed class ModLocalization { public List<string> LocalizedStrings = new List<string>(); } internal static class PluginUtils { internal static bool HoldingCultivator { get { Player localPlayer = Player.m_localPlayer; return ((localPlayer == null) ? null : ((Humanoid)localPlayer).GetRightItem()?.m_shared.m_name) == "$item_cultivator"; } } internal static AssetBundle LoadAssetBundle(string fileName) { return AssetBundle.LoadFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("Advize_PlantEverything.Assets." + fileName)); } internal static GameObject CreatePrefab(string name) { GameObject obj = PlantEverything.assetBundle.LoadAsset<GameObject>(name); obj.SetActive(true); return obj; } internal static Piece GetOrAddPieceComponent(GameObject go) { return go.GetComponent<Piece>() ?? go.AddComponent<Piece>(); } internal static string GetPrefabName(Component c) { return ((Object)c.transform.root).name.Replace("(Clone)", ""); } internal static bool IsModdedPrefab(Component c) { if (Object.op_Implicit((Object)(object)c)) { return PlantEverything.prefabRefs.ContainsKey(GetPrefabName(c)); } return false; } internal static bool IsModdedPrefabOrSapling(string s) { if (!s.StartsWith("$pe")) { return s.EndsWith("_sapling"); } return true; } internal static void RemoveFromCultivator(List<PrefabDB> prefabs) { if (HoldingCultivator) { SheatheCultivator(); } PieceTable pieceTable = PlantEverything.prefabRefs["Cultivator"].GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces; prefabs.ForEach(delegate(PrefabDB x) { pieceTable.m_pieces.Remove(x.Prefab); }); } internal static void SheatheCultivator() { PlantEverything.PELogger.LogWarning((object)"Cultivator updated through config change, unequipping cultivator"); ((Humanoid)Player.m_localPlayer).HideHandItems(); } internal static Piece CreatePiece(PieceDB pdb) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) Piece orAddPieceComponent = GetOrAddPieceComponent(PlantEverything.prefabRefs[pdb.key]); orAddPieceComponent.m_name = (pdb.extraResource ? pdb.pieceName : ("$pe" + pdb.Name + "Name")); orAddPieceComponent.m_description = (pdb.extraResource ? pdb.pieceDescription : ("$pe" + pdb.Name + "Description")); orAddPieceComponent.m_category = (PieceCategory)0; orAddPieceComponent.m_cultivatedGroundOnly = (pdb.key.Contains("berryBush") || pdb.key.Contains("Pickable")) && PlantEverything.config.RequireCultivation; bool num = pdb.isGrounded ?? (!PlantEverything.config.PlaceAnywhere); bool groundOnly = num; orAddPieceComponent.m_groundPiece = num; orAddPieceComponent.m_groundOnly = groundOnly; orAddPieceComponent.m_canBeRemoved = pdb.canBeRemoved.GetValueOrDefault(true); orAddPieceComponent.m_targetNonPlayerBuilt = false; ((StaticTarget)orAddPieceComponent).m_randomTarget = PlantEverything.config.EnemiesTargetPieces; return orAddPieceComponent; } internal static Sprite CreateSprite(string fileName, Rect spriteSection) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) try { Texture2D val = LoadTexture(fileName); Sprite val2; if (PlantEverything.cachedSprites.ContainsKey(val)) { val2 = PlantEverything.cachedSprites[val]; } else { val2 = Sprite.Create(val, spriteSection, Vector2.zero); PlantEverything.cachedSprites.Add(val, val2); } return val2; } catch { PlantEverything.Dbgl("Unable to load texture", forceLog: true, (LogLevel)2); } return null; } private static Texture2D LoadTexture(string fileName) { //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_0056: Expected O, but got Unknown //IL_0058: Expected O, but got Unknown Texture2D val; if (PlantEverything.cachedTextures.ContainsKey(fileName)) { val = PlantEverything.cachedTextures[fileName]; } else { Stream? manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Advize_PlantEverything.Assets." + fileName); byte[] array = new byte[manifestResourceStream.Length]; manifestResourceStream.Read(array, 0, array.Length); Texture2D val2 = new Texture2D(0, 0); ImageConversion.LoadImage(val2, array); val = val2; PlantEverything.cachedTextures.Add(fileName, val); } return val; } internal static Texture2D DuplicateTexture(Sprite sprite) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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) //IL_00b5: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown Rect textureRect = sprite.textureRect; int num = (int)((Rect)(ref textureRect)).width; textureRect = sprite.textureRect; int num2 = (int)((Rect)(ref textureRect)).height; Texture2D texture = sprite.texture; RenderTexture active = RenderTexture.active; RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)2); Graphics.Blit((Texture)(object)texture, temporary); RenderTexture.active = temporary; Texture2D val = new Texture2D(((Texture)texture).width, ((Texture)texture).height); val.ReadPixels(new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); Texture2D val2 = new Texture2D(num, num2); textureRect = sprite.textureRect; int num3 = (int)((Rect)(ref textureRect)).x; textureRect = sprite.textureRect; Color[] pixels = val.GetPixels(num3, (int)((Rect)(ref textureRect)).y, num, num2); val2.SetPixels(pixels); val2.Apply(); return val2; } internal static Sprite ModifyTextureColor(Texture2D baseTexture, int width, int height, Color targetColor) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(width, height); float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(targetColor, ref num, ref num2, ref num3); Color[] pixels = baseTexture.GetPixels(); float[] array = new float[width * height]; float[] array2 = new float[width * height]; float[] array3 = new float[width * height]; float num4 = default(float); float num5 = default(float); float num6 = default(float); for (int i = 0; i < width * height; i++) { Color.RGBToHSV(pixels[i], ref num4, ref num5, ref num6); array[i] = num - num4; array2[i] = num2 - num5; array3[i] = num3 - num6; } float num7 = default(float); float num8 = default(float); float num9 = default(float); for (int j = 0; j < width; j++) { for (int k = 0; k < height; k++) { Color pixel = baseTexture.GetPixel(j, k); float a = pixel.a; val.SetPixel(j, k, Color.clear); if (pixel.a != 0f) { Color.RGBToHSV(pixel, ref num7, ref num8, ref num9); num7 += array[j + k * width]; num8 += array2[j + k * width]; float num10 = ((array3[j + k * width] > 0f) ? 1.5f : (1f / 3f)); num9 *= num9 + array3[j + k * width] * num10; pixel = Color.HSVToRGB(num7, num8, num9); pixel.a = a; val.SetPixel(j, k, pixel); } } } val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, (float)width, (float)height), Vector2.zero); } private static string SerializeExtraResource(ExtraResource extraResource, bool prettyPrint = true) { return JsonUtility.ToJson((object)extraResource, prettyPrint); } internal static ExtraResource DeserializeExtraResource(string extraResource) { return JsonUtility.FromJson<ExtraResource>(extraResource); } private static void SaveExtraResources() { string text = Path.Combine(PlantEverything.CustomConfigPath, "PlantEverything_ExtraResources.cfg"); PlantEverything.Dbgl($"deserializedExtraResources.Count is {PlantEverything.deserializedExtraResources.Count}", forceLog: false, (LogLevel)16); string text2 = ""; text2 = text2 + SerializeExtraResource(PlantEverything.deserializedExtraResources[0]) + ";\n\n"; text2 = text2 + SerializeExtraResource(PlantEverything.deserializedExtraResources[1], prettyPrint: false) + ";\n"; File.WriteAllText(text, text2); PlantEverything.Dbgl("Serialized extraResources to " + text, forceLog: true, (LogLevel)16); } internal static void LoadExtraResources() { PlantEverything.Dbgl("LoadExtraResources", forceLog: false, (LogLevel)16); PlantEverything.deserializedExtraResources.Clear(); string text = "PlantEverything_ExtraResources.cfg"; string text2 = Path.Combine(PlantEverything.CustomConfigPath, text); try { string[] array = File.ReadAllText(text2).Split(new char[1] { ';' }); foreach (string text3 in array) { if (!Utility.IsNullOrWhiteSpace(text3)) { ExtraResource item = DeserializeExtraResource(text3); if (item.IsValid()) { PlantEverything.deserializedExtraResources.Add(item); } else if (!item.prefabName.StartsWith("PE_Fake")) { PlantEverything.Dbgl("Invalid resource, " + item.prefabName + ", configured in " + text + ", skipping entry", forceLog: true, (LogLevel)4); } } } PlantEverything.Dbgl("Loaded extra resources from " + text2, forceLog: true, (LogLevel)16); PlantEverything.Dbgl("Assigning local value from deserializedExtraResources", forceLog: false, (LogLevel)16); List<string> resourcesToSync = new List<string>(); PlantEverything.deserializedExtraResources.ForEach(delegate(ExtraResource er) { resourcesToSync.Add(SerializeExtraResource(er)); }); PlantEverything.config.SyncedExtraResources.AssignLocalValue(resourcesToSync); } catch (Exception ex) { if (ex is FileNotFoundException) { PlantEverything.Dbgl("Error loading data from " + text + ". Generating new file with example values", forceLog: true, (LogLevel)4); PlantEverything.deserializedExtraResources = StaticContent.GenerateExampleResources(); SaveExtraResources(); } else { PlantEverything.Dbgl("Error loading data from " + text + ". Additional resources have not been added", forceLog: false, (LogLevel)4); PlantEverything.deserializedExtraResources.Clear(); } } } internal static void LoadLocalizedStrings() { string path = PlantEverything.config.Language + "_PlantEverything.json"; string text = Path.Combine(PlantEverything.CustomConfigPath, path); try { foreach (string localizedString in JsonUtility.FromJson<ModLocalization>(File.ReadAllText(text)).LocalizedStrings) { string[] array = localizedString.Split(new char[1] { ':' }); StaticContent.DefaultLocalizedStrings.Remove(array[0]); StaticContent.DefaultLocalizedStrings.Add(array[0], array[1]); } PlantEverything.Dbgl("Loaded localized strings from " + text, forceLog: false, (LogLevel)16); return; } catch { PlantEverything.Dbgl("EnableLocalization is true but unable to load localized text file, generating new one from default English values", forceLog: true, (LogLevel)16); } SerializeDict(); } private static void SerializeDict() { string text = Path.Combine(PlantEverything.CustomConfigPath, "english_PlantEverything.json"); ModLocalization modLocalization = new ModLocalization(); foreach (KeyValuePair<string, string> defaultLocalizedString in StaticContent.DefaultLocalizedStrings) { modLocalization.LocalizedStrings.Add(defaultLocalizedString.Key + ":" + defaultLocalizedString.Value); } File.WriteAllText(text, JsonUtility.ToJson((object)modLocalization, true)); PlantEverything.Dbgl("Saved english localized strings to " + text, forceLog: false, (LogLevel)16); } } internal static class StaticContent { private const Biome TemperateBiomes = 25; internal const Biome AllBiomes = 895; internal static readonly int ModdedVineHash = StringExtensionMethods.GetStableHashCode("pe_ModdedVine"); internal static readonly int VineColorHash = StringExtensionMethods.GetStableHashCode("pe_VineColor"); internal static readonly int BerryColor1Hash = StringExtensionMethods.GetStableHashCode("pe_BerryColor1"); internal static readonly int BerryColor2Hash = StringExtensionMethods.GetStableHashCode("pe_BerryColor2"); internal static readonly int BerryColor3Hash = StringExtensionMethods.GetStableHashCode("pe_BerryColor3"); internal static readonly Vector3 ColorBlackVector3 = new Vector3(0.00012345f, 0.00012345f, 0.00012345f); internal static readonly Color ColorVineGreen = new Color(0.729f, 1f, 0.525f, 1f); internal static readonly Color ColorVineRed = new Color(0.867f, 0f, 0.278f, 1f); internal static readonly Color ColorBerryGreen = new Color(1f, 1f, 1f, 1f); internal static readonly Color ColorBerryRed = new Color(1f, 0f, 0f, 1f); internal static string[] layersForPieceRemoval = new string[4] { "item", "piece_nonsolid", "Default_small", "Default" }; internal static Dictionary<string, string> DefaultLocalizedStrings = new Dictionary<string, string> { { "AncientSaplingName", "Ancient Sapling" }, { "AncientSaplingDescription", "" }, { "YggaSaplingName", "Ygga Sapling" }, { "YggaSaplingDescription", "" }, { "AutumnBirchSaplingName", "Autumn Birch Sapling" }, { "AutumnBirchSaplingDescription", "Plains Variant" }, { "AshwoodSaplingName", "Ashwood Sapling" }, { "AshwoodSaplingDescription", "" }, { "VineAshSaplingName", "Custom Ashvine" }, { "VineAshSaplingDescription", "Plants an Ashvine sapling with the colours defined in the mod config." }, { "RaspberryBushName", "Raspberry Bush" }, { "RaspberryBushDescription", "Plant raspberries to grow raspberry bushes." }, { "BlueberryBushName", "Blueberry Bush" }, { "BlueberryBushDescription", "Plant blueberries to grow blueberry bushes." }, { "CloudberryBushName", "Cloudberry Bush" }, { "CloudberryBushDescription", "Plant cloudberries to grow cloudberry bushes." }, { "PickableMushroomName", "Pickable Mushrooms" }, { "PickableMushroomDescription", "Plant mushrooms to grow more pickable mushrooms." }, { "PickableYellowMushroomName", "Pickable Yellow Mushrooms" }, { "PickableYellowMushroomDescription", "Plant yellow mushrooms to grow more pickable yellow mushrooms." }, { "PickableBlueMushroomName", "Pickable Blue Mushrooms" }, { "PickableBlueMushroomDescription", "Plant blue mushrooms to grow more pickable blue mushrooms." }, { "PickableThistleName", "Pickable Thistle" }, { "PickableThistleDescription", "Plant thistle to grow more pickable thistle." }, { "PickableDandelionName", "Pickable Dandelion" }, { "PickableDandelionDescription", "Plant dandelion to grow more pickable dandelion." }, { "BeechSmallName", "Small Beech Tree" }, { "BeechSmallDescription", "Plant a small beech tree." }, { "FirSmallName", "Small Fir Tree" }, { "FirSmallDescription", "Plant a small fir tree." }, { "FirSmallDeadName", "Small Dead Fir Tree" }, { "FirSmallDeadDescription", "Plant a small dead fir tree." }, { "Bush01Name", "Small Bush 1" }, { "Bush01Description", "Plant a small bush." }, { "Bush02Name", "Small Bush 2" }, { "Bush02Description", "Plant a small bush." }, { "PlainsBushName", "Small Plains Bush" }, { "PlainsBushDescription", "Plant a bush native to the plains." }, { "Shrub01Name", "Small Shrub 1" }, { "Shrub01Description", "Plant a small shrub." }, { "Shrub02Name", "Small Shrub 2" }, { "Shrub02Description", "Plant a small shrub." }, { "YggaShootName", "Small Ygga Shoot" }, { "YggaShootDescription", "Plant a small ygga shoot." }, { "VinesName", "Vines" }, { "VinesDescription", "Plant vines." }, { "AshlandsFernName", "Ashlands Fern" }, { "AshlandsFernDescription", "Plant a fern native to the ashlands." }, { "PickableBranchName", "Pickable Branch" }, { "PickableBranchDescription", "Plant respawning pickable branches." }, { "PickableStoneName", "Pickable Stone" }, { "PickableStoneDescription", "Plant pickable stone." }, { "PickableFlintName", "Pickable Flint" }, { "PickableFlintDescription", "Plant respawning pickable flint." }, { "PickableSmokePuffName", "Pickable Smoke Puff" }, { "PickableSmokePuffDescription", "Plant smoke puffs to grow more pickable smoke puffs." }, { "PickableFiddleheadName", "Pickable Fiddlehead" }, { "PickableFiddleheadDescription", "Plant fiddlehead to grow more pickable fiddlehead." } }; internal static readonly List<string> VanillaPrefabRefs = new List<string> { "Acorn", "AncientSeed", "BeechSeeds", "BirchSeeds", "FirCone", "PineCone", "Sap", "Pickable_Branch", "Pickable_Dandelion", "Pickable_Fiddlehead", "Pickable_Flint", "Pickable_Mushroom", "Pickable_Mushroom_blue", "Pickable_Mushroom_yellow", "Pickable_SmokePuff", "Pickable_Stone", "Pickable_Thistle", "Cultivator", "sfx_build_cultivator", "vfx_Place_wood_pole", "sapling_barley", "sapling_carrot", "sapling_flax", "sapling_jotunpuffs", "sapling_magecap", "sapling_onion", "sapling_seedcarrot", "sapling_seedonion", "sapling_seedturnip", "sapling_turnip", "FernAshlands", "AshlandsTree3", "AshlandsTree4", "AshlandsTree5", "AshlandsTree6_big", "Beech1", "Beech_Sapling", "Beech_small1", "Birch1", "Birch1_aut", "Birch2", "Birch2_aut", "Birch_Sapling", "BlueberryBush", "Bush01", "Bush01_heath", "Bush02_en", "RaspberryBush", "CloudberryBush", "FirTree", "FirTree_Sapling", "FirTree_small", "FirTree_small_dead", "PineTree_Sapling", "Pinetree_01", "YggaShoot1", "YggaShoot2", "YggaShoot3", "YggaShoot_small1", "shrub_2", "shrub_2_heath", "SwampTree1", "vines", "VineAsh", "VineAsh_sapling", "Oak1", "Oak_Sapling" }; internal static readonly List<string> CustomPrefabRefs = new List<string> { "Ancient_Sapling", "Ygga_Sapling", "Autumn_Birch_Sapling", "Ashwood_Sapling", "Pickable_Dandelion_Picked", "Pickable_Thistle_Picked", "Pickable_Mushroom_Picked", "Pickable_Mushroom_yellow_Picked", "Pickable_Mushroom_blue_Picked", "Pickable_SmokePuff_Picked", "Pickable_Fiddlehead_Picked" }; private static Dictionary<GameObject, GameObject> treesToSeeds; internal static bool OverrideVines => PlantEverything.config.AshVineStyle != AshVineStyle.Custom; internal static bool OverrideBerries => PlantEverything.config.VineBerryStyle != VineBerryStyle.Custom; internal static Color VineColorFromConfig { get { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (PlantEverything.config.AshVineStyle != AshVineStyle.Custom) { if (PlantEverything.config.AshVineStyle != AshVineStyle.MeadowsGreen) { return ColorVineRed; } return ColorVineGreen; } return PlantEverything.config.VinesColor; } } internal static List<Color> BerryColorsFromConfig { get { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (PlantEverything.config.VineBerryStyle != VineBerryStyle.Custom) { if (PlantEverything.config.VineBerryStyle != VineBerryStyle.RedGrapes) { return Enumerable.Repeat<Color>(ColorBerryGreen, 3).ToList(); } return Enumerable.Repeat<Color>(ColorBerryRed, 3).ToList(); } return PlantEverything.config.BerryColors.Select((ConfigEntry<Color> x) => x.Value).ToList(); } } internal static Dictionary<GameObject, GameObject> TreesToSeeds { get { object obj = treesToSeeds; if (obj == null) { obj = new Dictionary<GameObject, GameObject> { { PlantEverything.prefabRefs["Birch1"], PlantEverything.prefabRefs["BirchSeeds"] }, { PlantEverything.prefabRefs["Birch2"], PlantEverything.prefabRefs["BirchSeeds"] }, { PlantEverything.prefabRefs["Birch2_aut"], PlantEverything.prefabRefs["BirchSeeds"] }, { PlantEverything.prefabRefs["Birch1_aut"], PlantEverything.prefabRefs["BirchSeeds"] }, { PlantEverything.prefabRefs["Oak1"], PlantEverything.prefabRefs["Acorn"] }, { PlantEverything.prefabRefs["SwampTree1"], PlantEverything.prefabRefs["AncientSeed"] }, { PlantEverything.prefabRefs["Beech1"], PlantEverything.prefabRefs["BeechSeeds"] }, { PlantEverything.prefabRefs["Pinetree_01"], PlantEverything.prefabRefs["PineCone"] }, { PlantEverything.prefabRefs["FirTree"], PlantEverything.prefabRefs["FirCone"] } }; treesToSeeds = (Dictionary<GameObject, GameObject>)obj; } return (Dictionary<GameObject, GameObject>)obj; } } internal static Vector3 ColorToVector3(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!(color == Color.black)) { return new Vector3(color.r, color.g, color.b); } return ColorBlackVector3; } internal static Color Vector3ToColor(Vector3 vector3) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!(vector3 == ColorBlackVector3)) { return new Color(vector3.x, vector3.y, vector3.z); } return Color.black; } internal static List<ExtraResource> GenerateExampleResources() { return new List<ExtraResource>(2) { new ExtraResource { prefabName = "PE_FakePrefab1", resourceName = "PretendSeeds1", resourceCost = 1, groundOnly = true, pieceName = "PickableMushrooms", pieceDescription = "Plant this to grow more pickable mushrooms." }, new ExtraResource { prefabName = "PE_FakePrefab2", resourceName = "PretendSeeds2", resourceCost = 2, groundOnly = false } }; } internal static List<PieceDB> GeneratePieceRefs() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0744: Unknown result type (might be due to invalid IL or missing references) //IL_075e: Unknown result type (might be due to invalid IL or missing references) //IL_0778: Unknown result type (might be due to invalid IL or missing references) //IL_0792: Unknown result type (might be due to invalid IL or missing references) bool enforceBiomes = PlantEverything.config.EnforceBiomes; List<PieceDB> list = new List<PieceDB>(10) { new PieceDB { key = "RaspberryBush", ResourceCost = PlantEverything.config.RaspberryCost, resourceReturn = PlantEverything.config.RaspberryReturn, respawnTime = PlantEverything.config.RaspberryRespawnTime, biome = (Biome)(enforceBiomes ? 1 : 0), icon = true, recover = PlantEverything.config.RecoverResources }, new PieceDB { key = "BlueberryBush", ResourceCost = PlantEverything.config.BlueberryCost, resourceReturn = PlantEverything.config.BlueberryReturn, respawnTime = PlantEverything.config.BlueberryRespawnTime, biome = (Biome)(enforceBiomes ? 8 : 0), icon = true, recover = PlantEverything.config.RecoverResources }, new PieceDB { key = "CloudberryBush", ResourceCost = PlantEverything.config.CloudberryCost, resourceReturn = PlantEverything.config.CloudberryReturn, respawnTime = PlantEverything.config.CloudberryRespawnTime, biome = (Biome)(enforceBiomes ? 16 : 0), icon = true, recover = PlantEverything.config.RecoverResources }, new PieceDB { key = "Pickable_Mushroom", ResourceCost = PlantEverything.config.MushroomCost, resourceReturn = PlantEverything.config.MushroomReturn, respawnTime = PlantEverything.config.MushroomRespawnTime, recover = PlantEverything.config.RecoverResources, Name = "PickableMushroom", isGrounded = true }, new PieceDB { key = "Pickable_Mushroom_yellow", ResourceCost = PlantEverything.config.YellowMushroomCost, resourceReturn = PlantEverything.config.YellowMushroomReturn, respawnTime = PlantEverything.config.YellowMushroomRespawnTime, recover = PlantEverything.config.RecoverResources, Name = "PickableYellowMushroom", isGrounded = true }, new PieceDB { key = "Pickable_Mushroom_blue", ResourceCost = PlantEverything.config.BlueMushroomCost, resourceReturn = PlantEverything.config.BlueMushroomReturn, respawnTime = PlantEverything.config.BlueMushroomRespawnTime, recover = PlantEverything.config.RecoverResources, Name = "PickableBlueMushroom", isGrounded = true }, new PieceDB { key = "Pickable_Thistle", ResourceCost = PlantEverything.config.ThistleCost, resourceReturn = PlantEverything.config.ThistleReturn, respawnTime = PlantEverything.config.ThistleRespawnTime, biome = (Biome)(enforceBiomes ? 8 : 0), recover = PlantEverything.config.RecoverResources, Name = "PickableThistle", isGrounded = true }, new PieceDB { key = "Pickable_Dandelion", ResourceCost = PlantEverything.config.DandelionCost, resourceReturn = PlantEverything.config.DandelionReturn, respawnTime = PlantEverything.config.DandelionRespawnTime, biome = (Biome)(enforceBiomes ? 1 : 0), recover = PlantEverything.config.RecoverResources, Name = "PickableDandelion", isGrounded = true }, new PieceDB { key = "Pickable_SmokePuff", ResourceCost = PlantEverything.config.SmokePuffCost, resourceReturn = PlantEverything.config.SmokePuffReturn, respawnTime = PlantEverything.config.SmokePuffRespawnTime, recover = PlantEverything.config.RecoverResources, Name = "PickableSmokePuff", isGrounded = true }, new PieceDB { key = "Pickable_Fiddlehead", ResourceCost = PlantEverything.config.FiddleheadCost, resourceReturn = PlantEverything.config.FiddleheadReturn, respawnTime = PlantEverything.config.FiddleheadRespawnTime, icon = true, recover = PlantEverything.config.RecoverResources, Name = "PickableFiddlehead", isGrounded = true, extraDrops = true } }; if (PlantEverything.config.EnableMiscFlora) { list.AddRange(new <>z__ReadOnlyArray<PieceDB>(new PieceDB[11] { new PieceDB { key = "Beech_small1", Resource = new KeyValuePair<string, int>("BeechSeeds", 1), icon = true, Name = "BeechSmall", canBeRemoved = false }, new PieceDB { key = "FirTree_small", Resource = new KeyValuePair<string, int>("FirCone", 1), icon = true, Name = "FirSmall", canBeRemoved = false }, new PieceDB { key = "FirTree_small_dead", Resource = new KeyValuePair<string, int>("FirCone", 1), icon = true, Name = "FirSmallDead", canBeRemoved = false }, new PieceDB { key = "Bush01", Resource = new KeyValuePair<string, int>("Wood", 2), icon = true, canBeRemoved = false }, new PieceDB { key = "Bush01_heath", Resource = new KeyValuePair<string, int>("Wood", 2), icon = true, Name = "Bush02", canBeRemoved = false }, new PieceDB { key = "Bush02_en", Resource = new KeyValuePair<string, int>("Wood", 3), icon = true, Name = "PlainsBush", canBeRemoved = false }, new PieceDB { key = "shrub_2", Resource = new KeyValuePair<string, int>("Wood", 2), icon = true, Name = "Shrub01", canBeRemoved = false }, new PieceDB { key = "shrub_2_heath", Resource = new KeyValuePair<string, int>("Wood", 2), icon = true, Name = "Shrub02", canBeRemoved = false }, new PieceDB { key = "YggaShoot_small1", Resources = new Dictionary<string, int> { { "YggdrasilWood", 1 }, { "Wood", 2 } }, icon = true, Name = "YggaShoot", canBeRemoved = false }, new PieceDB { key = "vines", Resource = new KeyValuePair<string, int>("Wood", 2), icon = true, recover = true, Name = "Vines", isGrounded = false, snapPoints = new List<Vector3> { new Vector3(1f, 0.5f, 0f), new Vector3(-1f, 0.5f, 0f), new Vector3(1f, -1f, 0f), new Vector3(-1f, -1f, 0f) } }, new PieceDB { key = "FernAshlands", Resource = new KeyValuePair<string, int>("Wood", 2), icon = true, Name = "AshlandsFern", canBeRemoved = false } })); } if (PlantEverything.config.EnableDebris) { list.AddRange(new <>z__ReadOnlyArray<PieceDB>(new PieceDB[3] { new PieceDB { key = "Pickable_Branch", ResourceCost = PlantEverything.config.PickableBranchCost, resourceReturn = PlantEverything.config.PickableBranchReturn, respawnTime = PlantEverything.config.PickableBranchRespawnTime, recover = PlantEverything.config.RecoverResources, Name = "PickableBranch", isGrounded = true }, new PieceDB { key = "Pickable_Stone", ResourceCost = PlantEverything.config.PickableStoneCost, resourceReturn = PlantEverything.config.PickableStoneReturn, respawnTime = PlantEverything.config.PickableStoneRespawnTime, recover = PlantEverything.config.RecoverResources, Name = "PickableStone", isGrounded = true, hideWhenPicked = true }, new PieceDB { key = "Pickable_Flint", ResourceCost = PlantEverything.config.PickableFlintCost, resourceReturn = PlantEverything.config.PickableFlintReturn, respawnTime = PlantEverything.config.PickableFlintRespawnTime, recover = PlantEverything.config.RecoverResources, Name = "PickableFlint", isGrounded = true } })); } if (PlantEverything.config.EnableExtraResources) { string[] array = layersForPieceRemoval; List<string> list2 = new List<string>(array.Length); list2.AddRange(array); List<string> list3 = list2; bool resolveMissingReferences = false; foreach (ExtraResource deserializedExtraResource in PlantEverything.deserializedExtraResources) { if (!PlantEverything.prefabRefs.ContainsKey(deserializedExtraResource.prefabName) || !Object.op_Implicit((Object)(object)PlantEverything.prefabRefs[deserializedExtraResource.prefabName])) { PlantEverything.Dbgl(deserializedExtraResource.prefabName + " is not in dictionary of prefab references or has a null value", forceLog: false, (LogLevel)4); resolveMissingReferences = true; continue; } ObjectDB instance = ObjectDB.instance; object obj; if (instance == null) { obj = null; } else { GameObject itemPrefab = instance.GetItemPrefab(deserializedExtraResource.resourceName); obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); } if (!Object.op_Implicit((Object)obj)) { PlantEverything.Dbgl(deserializedExtraResource.prefabName + "'s required resource " + deserializedExtraResource.resourceName + " not found", forceLog: false, (LogLevel)4); resolveMissingReferences = true; continue; } list.Add(new PieceDB { key = deserializedExtraResource.prefabName, Resource = new KeyValuePair<string, int>(deserializedExtraResource.resourceName, deserializedExtraResource.resourceCost), isGrounded = deserializedExtraResource.groundOnly, extraResource = true, pieceName = ((deserializedExtraResource.pieceName == "") ? deserializedExtraResource.prefabName : deserializedExtraResource.pieceName), pieceDescription = deserializedExtraResource.pieceDescription }); Collider[] componentsInChildren = PlantEverything.prefabRefs[deserializedExtraResource.prefabName].GetComponentsInChildren<Collider>(); for (int i = 0; i < componentsInChildren.Length; i++) { string item = LayerMask.LayerToName(((Component)componentsInChildren[i]).gameObject.layer); list3.Add(item); } } layersForPieceRemoval = list3.Distinct().ToArray(); PlantEverything.resolveMissingReferences = resolveMissingReferences; } return list; } internal static List<SaplingDB> GenerateCustomSaplingRefs() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) List<SaplingDB> list = new List<SaplingDB>(4); list.Add(new SaplingDB { key = "Ashwood_Sapling", biome = (Biome)(PlantEverything.config.EnforceBiomes ? 57 : 895), source = "AshlandsTree3", Resources = new Dictionary<string, int> { { "BeechSeeds", 1 }, { "SulfurStone", 1 } }, icon = true, growTime = PlantEverything.config.AshwoodGrowthTime, growRadius = PlantEverything.config.AshwoodGrowRadius, minScale = PlantEverything.config.AshwoodMinScale, maxScale = PlantEverything.config.AshwoodMaxScale, grownPrefabs = (GameObject[])(object)new GameObject[4] { PlantEverything.prefabRefs["AshlandsTree3"], PlantEverything.prefabRefs["AshlandsTree4"], PlantEverything.prefabRefs["AshlandsTree5"], PlantEverything.prefabRefs["AshlandsTree6_big"] }, tolerateHeat = true }); list.Add(new SaplingDB { key = "Ygga_Sapling", biome = (Biome)(PlantEverything.config.EnforceBiomes ? 537 : 895), source = "YggaShoot_small1", Resource = new KeyValuePair<string, int>("Sap", 1), icon = true, growTime = PlantEverything.config.YggaGrowthTime, growRadius = PlantEverything.config.YggaGrowRadius, minScale = PlantEverything.config.YggaMinScale, maxScale = PlantEverything.config.YggaMaxScale, grownPrefabs = (GameObject[])(object)new GameObject[3] { PlantEverything.prefabRefs["YggaShoot1"], PlantEverything.prefabRefs["YggaShoot2"], PlantEverything.prefabRefs["YggaShoot3"] } }); list.Add(new SaplingDB { key = "Ancient_Sapling", biome = (Biome)(PlantEverything.config.EnforceBiomes ? 27 : 895), source = "SwampTree1", Resource = new KeyValuePair<string, int>("AncientSeed", 1), icon = true, growTime = PlantEverything.config.AncientGrowthTime, growRadius = PlantEverything.config.AncientGrowRadius, minScale = PlantEverything.config.AncientMinScale, maxScale = PlantEverything.config.AncientMaxScale, grownPrefabs = (GameObject[])(object)new GameObject[1] { PlantEverything.prefabRefs["SwampTree1"] } }); list.Add(new SaplingDB { key = "Autumn_Birch_Sapling", biome = (Biome)(PlantEverything.config.EnforceBiomes ? 25 : 895), source = "Birch1_aut", Resource = new KeyValuePair<string, int>("BirchSeeds", 1), icon = true, growTime = PlantEverything.config.AutumnBirchGrowthTime, growRadius = PlantEverything.config.AutumnBirchGrowRadius, minScale = PlantEverything.config.AutumnBirchMinScale, maxScale = PlantEverything.config.AutumnBirchMaxScale, grownPrefabs = (GameObject[])(object)new GameObject[2] { PlantEverything.prefabRefs["Birch1_aut"], PlantEverything.prefabRefs["Birch2_aut"] } }); return list; } internal static List<SaplingDB> GenerateVanillaSaplingRefs() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) return new List<SaplingDB>(5) { new SaplingDB { key = "Beech_Sapling", biome = (Biome)(PlantEverything.config.EnforceBiomesVanilla ? 25 : 895), growTime = PlantEverything.config.BeechGrowthTime, growRadius = PlantEverything.config.BeechGrowRadius, minScale = PlantEverything.config.BeechMinScale, maxScale = PlantEverything.config.BeechMaxScale }, new SaplingDB { key = "PineTree_Sapling", biome = (Biome)(PlantEverything.config.EnforceBiomesVanilla ? 25 : 895), growTime = PlantEverything.config.PineGrowthTime, growRadius = PlantEverything.config.PineGrowRadius, minScale = PlantEverything.config.PineMinScale, maxScale = PlantEverything.config.PineMaxScale }, new SaplingDB { key = "FirTree_Sapling", biome = (Biome)(PlantEverything.config.EnforceBiomesVanilla ? 29 : 895), growTime = PlantEverything.config.FirGrowthTime, growRadius = PlantEverything.config.FirGrowRadius, minScale = PlantEverything.config.FirMinScale, maxScale = PlantEverything.config.FirMaxScale, tolerateCold = true }, new SaplingDB { key = "Birch_Sapling", biome = (Biome)(PlantEverything.config.EnforceBiomesVanilla ? 25 : 895), growTime = PlantEverything.config.BirchGrowthTime, growRadius = PlantEverything.config.BirchGrowRadius, minScale = PlantEverything.config.BirchMinScale, maxScale = PlantEverything.config.BirchMaxScale }, new SaplingDB { key = "Oak_Sapling", biome = (Biome)(PlantEverything.config.EnforceBiomesVanilla ? 25 : 895), growTime = PlantEverything.config.OakGrowthTime, growRadius = PlantEverything.config.OakGrowRadius, minScale = PlantEverything.config.OakMinScale, maxScale = PlantEverything.config.OakMaxScale } }; } internal static List<PrefabDB> GenerateCropRefs() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) bool enableCropOverrides = PlantEverything.config.EnableCropOverrides; bool enforceBiomesVanilla = PlantEverything.config.EnforceBiomesVanilla; return new List<PrefabDB>(10) { new PrefabDB { key = "sapling_barley", biome = (Biome)(enforceBiomesVanilla ? 16 : 895), resourceCost = ((!enableCropOverrides) ? 1 : PlantEverything.config.BarleyCost), resourceReturn = (enableCropOverrides ? PlantEverything.config.BarleyReturn : 2) }, new PrefabDB { key = "sapling_carrot", biome = (Biome)(enforceBiomesVanilla ? 25 : 895), resourceCost = ((!enableCropOverrides) ? 1 : PlantEverything.config.CarrotCost), resourceReturn = ((!enableCropOverrides) ? 1 : PlantEverything.config.CarrotReturn) }, new PrefabDB { key = "sapling_flax", biome = (Biome)(enforceBiomesVanilla ? 16 : 895), resourceCost = ((!enableCropOverrides) ? 1 : PlantEverything.config.FlaxCost), resourceReturn = (enableCropOverrides ? PlantEverything.config.FlaxReturn : 2) }, new PrefabDB { key = "sapling_onion", biome = (Biome)(enforceBiomesVanilla ? 25 : 895), resourceCost = ((!enableCropOverrides) ? 1 : PlantEverything.config.OnionCost), resourceReturn = ((!enableCropOverrides) ? 1 : PlantEverything.config.OnionReturn) }, new PrefabDB { key = "sapling_seedcarrot", biome = (Biome)(enforceBiomesVanilla ? 25 : 895), resourceCost = ((!enableCropOverrides) ? 1 : PlantEverything.config.SeedCarrotCost), resourceReturn = (enableCropOverrides ? PlantEverything.config.SeedCarrotReturn : 3) }, new PrefabDB { key = "sapling_seedonion", biome = (Biome)(enforceBiomesVanilla ? 25 : 895), resourceCost = ((!enableCropOverrides) ? 1 : PlantEverything.config.SeedOnionCost), resourceReturn = (enableCropOverrides ? PlantEverything.config.SeedOnionReturn : 3) }, new PrefabDB { key = "sapling_seedturnip", biome = (Biome)(enforceBiomesVanilla ? 539 : 895), resourceCost = ((!enableCropOverrides) ? 1 : PlantEverything.config.SeedTurnipCost), resourceReturn = (enableCropOverrides ? PlantEverything.config.SeedTurnipReturn : 3) }, new PrefabDB { key = "sapling_turnip", biome = (Biome)(enforceBiomesVanilla ? 539 : 895), resourceCost = ((!enableCropOverrides) ? 1 : PlantEverything.config.TurnipCost), resourceReturn = ((!enableCropOverrides) ? 1 : PlantEverything.config.TurnipReturn) }, new PrefabDB { key = "sapling_magecap", biome = (Biome)(enforceBiomesVanilla ? 512 : 895), resourceCost = ((!enableCropOverrides) ? 1 : PlantEverything.config.MagecapCost), resourceReturn = ((!enableCropOverrides) ? 1 : PlantEverything.config.MagecapReturn), extraDrops = true }, new PrefabDB { key = "sapling_jotunpuffs", biome = (Biome)(enforceBiomesVanilla ? 512 : 895), resourceCost = ((!enableCropOverrides) ? 1 : PlantEverything.config.JotunPuffsCost), resourceReturn = ((!enableCropOverrides) ? 1 : PlantEverything.config.JotunPuffsReturn), extraDrops = true } }; } internal static List<CustomPlantDB> GenerateCustomPlantRefs(List<GameObject> customPlants) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) List<CustomPlantDB> list = new List<CustomPlantDB>(); foreach (GameObject customPlant in customPlants) { Plant component = customPlant.GetComponent<Plant>(); list.Add(new CustomPlantDB { key = ((Object)customPlant).name, biome = component.m_biome, tolerateCold = component.m_tolerateCold, tolerateHeat = component.m_tolerateHeat, minScale = component.m_minScale, maxScale = component.m_maxScale, growTime = component.m_growTime, growTimeMax = component.m_growTimeMax, growRadius = component.m_growRadius }); PlantEverything.prefabRefs[((Object)customPlant).name] = customPlant; } return list; } } internal sealed class ModConfig { internal class ConfigurationManagerAttributes { public bool? Browsable; [<620737d2-74a2-4263-8f12-353eee49a0ff>Nullable(2)] public string Category; public int? Order; public bool? ReadOnly; } [<620737d2-74a2-4263-8f12-353eee49a0ff>Nullable(0)] [<baed80af-2136-4897-bc60-57e517bae1ff>NullableContext(2)] internal class ConfigManagerHelper { private static Assembly BepinexConfigManager => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault([<baed80af-2136-4897-bc60-57e517bae1ff>NullableContext(0)] (Assembly a) => a.GetName().Name == "ConfigurationManager"); private static Type ConfigManagerType => BepinexConfigManager?.GetType("ConfigurationManager.ConfigurationManager"); private static object ConfigManager { get { if (!(ConfigManagerType == null)) { return Chainloader.ManagerObject.GetComponent(ConfigManagerType); } return null; } } internal static void ReloadConfigDisplay() { ConfigManager?.GetType().GetMethod("BuildSettingList").Invoke(ConfigManager, Array.Empty<object>()); } } private readonly ConfigFile ConfigFile; private readonly ConfigSync ConfigSync; private readonly ConfigEntry<bool> serverConfigLocked; internal readonly ConfigEntry<int> nexusID; private readonly ConfigEntry<bool> enableDebugMessages; private readonly ConfigEntry<bool> showPickableSpawners; private readonly ConfigEntry<bool> enableMiscFlora; private readonly ConfigEntry<bool> enableDebris; private readonly ConfigEntry<bool> enableExtraResources; private readonly ConfigEntry<bool> snappableVines; private readonly ConfigEntry<bool> enableLocalization; private readonly ConfigEntry<string> language; private readonly ConfigEntry<string> disabledResourceNames; private readonly ConfigEntry<bool> requireCultivation; private readonly ConfigEntry<bool> placeAnywhere; private readonly ConfigEntry<bool> enforceBiomes; private readonly ConfigEntry<bool> enforceBiomesVanilla; private readonly ConfigEntry<bool> plantsRequireShielding; private readonly ConfigEntry<bool> canRemoveFlora; private readonly ConfigEntry<bool> recoverResources; private readonly ConfigEntry<bool> resourcesSpawnEmpty; private readonly ConfigEntry<bool> enemiesTargetPieces; private readonly ConfigEntry<int> raspberryCost; private readonly ConfigEntry<int> blueberryCost; private readonly ConfigEntry<int> cloudberryCost; private readonly ConfigEntry<int> raspberryRespawnTime; private readonly ConfigEntry<int> blueberryRespawnTime; private readonly ConfigEntry<int> cloudberryRespawnTime; private readonly ConfigEntry<int> raspberryReturn; private readonly ConfigEntry<int> blueberryReturn; private readonly ConfigEntry<int> cloudberryReturn; private readonly ConfigEntry<bool> enableCropOverrides; private readonly ConfigEntry<bool> overrideModdedCrops; private readonly ConfigEntry<bool> cropRequireCultivation; private readonly ConfigEntry<bool> cropRequireSunlight; private readonly ConfigEntry<bool> cropRequireGrowthSpace; private readonly ConfigEntry<bool> enemiesTargetCrops; private readonly ConfigEntry<float> cropMinScale; private readonly ConfigEntry<float> cropMaxScale; private readonly ConfigEntry<float> cropGrowTimeMin; private readonly ConfigEntry<float> cropGrowTimeMax; private readonly ConfigEntry<float> cropGrowRadius; private readonly ConfigEntry<int> barleyCost; private readonly ConfigEntry<int> barleyReturn; private readonly ConfigEntry<int> carrotCost; private readonly ConfigEntry<int> carrotReturn; private readonly ConfigEntry<int> flaxCost; private readonly ConfigEntry<int> flaxReturn; private readonly ConfigEntry<int> onionCost; private readonly ConfigEntry<int> onionReturn; private readonly ConfigEntry<int> seedCarrotCost; private readonly ConfigEntry<int> seedCarrotReturn; private readonly ConfigEntry<int> seedOnionCost; private readonly ConfigEntry<int> seedOnionReturn; private readonly ConfigEntry<int> seedTurnipCost; private readonly ConfigEntry<int> seedTurnipReturn; private readonly ConfigEntry<int> turnipCost; private readonly ConfigEntry<int> turnipReturn; private readonly ConfigEntry<int> magecapCost; private readonly ConfigEntry<int> magecapReturn; private readonly ConfigEntry<int> jotunPuffsCost; private readonly ConfigEntry<int> jotunPuffsReturn; private readonly ConfigEntry<int> pickableBranchCost; private readonly ConfigEntry<int> pickableBranchReturn; private readonly ConfigEntry<int> pickableBranchRespawnTime; private readonly ConfigEntry<int> pickableStoneCost; private readonly ConfigEntry<int> pickableStoneReturn; private readonly ConfigEntry<int> pickableStoneRespawnTime; private readonly ConfigEntry<int> pickableFlintCost; private readonly ConfigEntry<int> pickableFlintReturn; private readonly ConfigEntry<int> pickableFlintRespawnTime; private readonly ConfigEntry<int> mushroomCost; private readonly ConfigEntry<int> yellowMushroomCost; private readonly ConfigEntry<int> blueMushroomCost; private readonly ConfigEntry<int> smokePuffCost; private readonly ConfigEntry<int> mushroomRespawnTime; private readonly ConfigEntry<int> yellowMushroomRespawnTime; private readonly ConfigEntry<int> blueMushroomRespawnTime; private readonly ConfigEntry<int> smokePuffRespawnTime; private readonly ConfigEntry<int> mushroomReturn; private readonly ConfigEntry<int> yellowMushroomReturn; private readonly ConfigEntry<int> blueMushroomReturn; private readonly ConfigEntry<int> smokePuffReturn; private readonly ConfigEntry<int> thistleCost; private readonly ConfigEntry<int> dandelionCost; private readonly ConfigEntry<int> fiddleheadCost; private readonly ConfigEntry<int> thistleRespawnTime; private readonly ConfigEntry<int> dandelionRespawnTime; private readonly ConfigEntry<int> fiddleheadRespawnTime; private readonly ConfigEntry<int> thistleReturn; private readonly ConfigEntry<int> dandelionReturn; private readonly ConfigEntry<int> fiddleheadReturn; private readonly ConfigEntry<float> birchMinScale; private readonly ConfigEntry<float> birchMaxScale; private readonly ConfigEntry<float> oakMinScale; private readonly ConfigEntry<float> oakMaxScale; private readonly ConfigEntry<float> ancientMinScale; private readonly ConfigEntry<float> ancientMaxScale; private readonly ConfigEntry<float> birchGrowthTime; private readonly ConfigEntry<float> oakGrowthTime; private readonly ConfigEntry<float> ancientGrowthTime; private readonly ConfigEntry<float> birchGrowRadius; private readonly ConfigEntry<float> oakGrowRadius; private readonly ConfigEntry<float> ancientGrowRadius; private readonly ConfigEntry<float> beechGrowthTime; private readonly ConfigEntry<float> pineGrowthTime; private readonly ConfigEntry<float> firGrowthTime; private readonly ConfigEntry<float> beechMinScale; private readonly ConfigEntry<float> beechMaxScale; private readonly ConfigEntry<float> pineMinScale; private readonly ConfigEntry<float> pineMaxScale; private readonly ConfigEntry<float> firMinScale; private readonly ConfigEntry<float> firMaxScale; private readonly ConfigEntry<float> beechGrowRadius; private readonly ConfigEntry<float> pineGrowRadius; private readonly ConfigEntry<float> firGrowRadius; private readonly ConfigEntry<float> yggaMinScale; private readonly ConfigEntry<float> yggaMaxScale; private readonly ConfigEntry<float> yggaGrowthTime; private readonly ConfigEntry<float> yggaGrowRadius; private readonly ConfigEntry<float> autumnBirchMinScale; private readonly ConfigEntry<float> autumnBirchMaxScale; private readonly ConfigEntry<float> autumnBirchGrowthTime; private readonly ConfigEntry<float> autumnBirchGrowRadius; private readonly ConfigEntry<float> ashwoodMinScale; private readonly ConfigEntry<float> ashwoodMaxScale; private readonly ConfigEntry<float> ashwoodGrowthTime; private readonly ConfigEntry<float> ashwoodGrowRadius; private readonly ConfigEntry<bool> enableSeedOverrides; private readonly ConfigEntry<int> seedDropMin; private readonly ConfigEntry<int> seedDropMax; private readonly ConfigEntry<int> treeDropMin; private readonly ConfigEntry<int> treeDropMax; private readonly ConfigEntry<float> dropChance; private readonly ConfigEntry<bool> oneOfEach; private readonly ConfigEntry<bool> enablePickableTimers; private readonly ConfigEntry<bool> enablePlantTimers; private readonly ConfigEntry<bool> growthAsPercentage; private readonly ConfigEntry<bool> enableVineOverrides; private readonly ConfigEntry<bool> enableCustomVinePiece; private readonly ConfigEntry<AshVineStyle> ashVineStyle; private readonly ConfigEntry<VineBerryStyle> vineBerryStyle; private readonly ConfigEntry<float> vineAttachDistance; private readonly ConfigEntry<float> vineGrowRadius; private readonly ConfigEntry<float> vineGrowthTime; private readonly ConfigEntry<int> vineBerryRespawnTime; private readonly ConfigEntry<int> vineBerryReturn; private readonly ConfigEntry<Color> ashVineCustomColor; private readonly ConfigEntry<Color> leftBerryColor; private readonly ConfigEntry<Color> centerBerryColor; private readonly ConfigEntry<Color> rightBerryColor; private readonly CustomSyncedValue<List<string>> extraResources; private readonly ConfigurationManagerAttributes seedSettingAtrributes = new ConfigurationManagerAttributes(); private readonly List<ConfigurationManagerAttributes> cropSettingAttributes = new List<ConfigurationManagerAttributes> { new ConfigurationManagerAttributes(), new ConfigurationManagerAttributes { Order = 27 } }; private List<ConfigEntry<Color>> _BerryColors; internal bool EnableDebugMessages => enableDebugMessages.Value; internal bool ShowPickableSpawners => showPickableSpawners.Value; internal bool EnableMiscFlora => enableMiscFlora.Value; internal bool EnableDebris => enableDebris.Value; internal bool EnableExtraResources => enableExtraResources.Value; internal bool SnappableVines => snappableVines.Value; internal bool EnableLocalization => enableLocalization.Value; internal string Language => language.Value; internal string[] DisabledResourceNames => disabledResourceNames.Value.Split(new char[1] { ',' }); internal bool RequireCultivation => requireCultivation.Value; internal bool PlaceAnywhere => placeAnywhere.Value; internal bool EnforceBiomes => enforceBiomes.Value; internal bool EnforceBiomesVanilla => enforceBiomesVanilla.Value; internal bool PlantsRequireShielding => plantsRequireShielding.Value; internal bool CanRemoveFlora => canRemoveFlora.Value; internal bool RecoverResources => recoverResources.Value; internal bool ResourcesSpawnEmpty => resourcesSpawnEmpty.Value; internal bool EnemiesTargetPieces => enemiesTargetPieces.Value; internal int RaspberryCost => raspberryCost.Value; internal int BlueberryCost => blueberryCost.Value; internal int CloudberryCost => cloudberryCost.Value; internal int RaspberryRespawnTime => raspberryRespawnTime.Value; internal int BlueberryRespawnTime => blueberryRespawnTime.Value; internal int CloudberryRespawnTime => cloudberryRespawnTime.Value; internal int RaspberryReturn => raspberryReturn.Value; internal int BlueberryReturn => blueberryReturn.Value; internal int CloudberryReturn => cloudberryReturn.Value; internal bool EnableCropOverrides => enableCropOverrides.Value; internal bool OverrideModdedCrops => overrideModdedCrops.Value; internal float CropMinScale => cropMinScale.Value; internal float CropMaxScale => cropMaxScale.Value; internal float CropGrowTimeMin => Mathf.Max(cropGrowTimeMin.Value, 10f); internal float CropGrowTimeMax => Mathf.Max(cropGrowTimeMax.Value, 10f); internal float CropGrowRadius => cropGrowRadius.Value; internal bool CropRequireCultivation => cropRequireCultivation.Value; internal bool CropRequireSunlight => cropRequireSunlight.Value; internal bool CropRequireGrowthSpace => cropRequireGrowthSpace.Value; internal bool EnemiesTargetCrops => enemiesTargetCrops.Value; internal int BarleyCost => barleyCost.Value; internal int BarleyReturn => barleyReturn.Value; internal int CarrotCost => carrotCost.Value; internal int CarrotReturn => carrotReturn.Value; internal int FlaxCost => flaxCost.Value; internal int FlaxReturn => flaxReturn.Value; internal int OnionCost => onionCost.Value; internal int OnionReturn => onionReturn.Value; internal int SeedCarrotCost => seedCarrotCost.Value; internal int SeedCarrotReturn => seedCarrotReturn.Value; internal int SeedOnionCost => seedOnionCost.Value; internal int SeedOnionReturn => seedOnionReturn.Value; internal int SeedTurnipCost => seedTurnipCost.Value; internal int SeedTurnipReturn => seedTurnipReturn.Value; internal int TurnipCost => turnipCost.Value; internal int TurnipReturn => turnipReturn.Value; internal int MagecapCost => magecapCost.Value; internal int MagecapReturn => magecapReturn.Value; internal int JotunPuffsCost => jotunPuffsCost.Value; internal int JotunPuffsReturn => jotunPuffsReturn.Value; internal int PickableBranchCost => pickableBranchCost.Value; internal int PickableBranchReturn => pickableBranchReturn.Value; internal int PickableBranchRespawnTime => pickableBranchRespawnTime.Value; internal int PickableStoneCost => pickableStoneCost.Value; internal int PickableStoneReturn => pickableStoneReturn.Value; internal int PickableStoneRespawnTime => pickableStoneRespawnTime.Value; internal int PickableFlintCost => pickableFlintCost.Value; internal int PickableFlintReturn => pickableFlintReturn.Value; internal int PickableFlintRespawnTime => pickableFlintRespawnTime.Value; internal int MushroomCost => mushroomCost.Value; internal int YellowMushroomCost => yellowMushroomCost.Value; internal int BlueMushroomCost => blueMushroomCost.Value; internal int SmokePuffCost => smokePuffCost.Value; internal int MushroomRespawnTime => mushroomRespawnTime.Value; internal int YellowMushroomRespawnTime => yellowMushroomRespawnTime.Value; internal int BlueMushroomRespawnTime => blueMushroomRespawnTime.Value; internal int SmokePuffRespawnTime => smokePuffRespawnTime.Value; internal int MushroomReturn => mushroomReturn.Value; internal int YellowMushroomReturn => yellowMushroomReturn.Value; internal int BlueMushroomReturn => blueMushroomReturn.Value; internal int SmokePuffReturn => smokePuffReturn.Value; internal int ThistleCost => thistleCost.Value; internal int DandelionCost => dandelionCost.Value; internal int FiddleheadCost => fiddleheadCost.Value; internal int ThistleRespawnTime => thistleRespawnTime.Value; internal int DandelionRespawnTime => dandelionRespawnTime.Value; internal int FiddleheadRespawnTime => fiddleheadRespawnTime.Value; internal int ThistleReturn => thistleReturn.Value; internal int DandelionReturn => dandelionReturn.Value; internal int FiddleheadReturn => fiddleheadReturn.Value; internal float BirchMinScale => birchMinScale.Value; internal float BirchMaxScale => birchMaxScale.Value; internal float OakMinScale => oakMinScale.Value; internal float OakMaxScale => oakMaxScale.Value; internal float AncientMinScale => ancientMinScale.Value; internal float AncientMaxScale => ancientMaxScale.Value; internal float BirchGrowthTime => Mathf.Max(birchGrowthTime.Value, 10f); internal float OakGrowthTime => Mathf.Max(oakGrowthTime.Value, 10f); internal float AncientGrowthTime => Mathf.Max(ancientGrowthTime.Value, 10f); internal float BirchGrowRadius => birchGrowRadius.Value; internal float OakGrowRadius => oakGrowRadius.Value; internal float AncientGrowRadius => ancientGrowRadius.Value; internal float BeechGrowthTime => Mathf.Max(beechGrowthTime.Value, 10f); internal float PineGrowthTime => Mathf.Max(pineGrowthTime.Value, 10f); internal float FirGrowthTime => Mathf.Max(firGrowthTime.Value, 10f); internal float BeechMinScale => beechMinScale.Value; internal float BeechMaxScale => beechMaxScale.Value; internal float PineMinScale => pineMinScale.Value; internal float PineMaxScale => pineMaxScale.Value; internal float FirMinScale => firMinScale.Value; internal float FirMaxScale => firMaxScale.Value; internal float BeechGrowRadius => beechGrowRadius.Value; internal float PineGrowRadius => pineGrowRadius.Value; internal float FirGrowRadius => firGrowRadius.Value; internal float YggaMinScale => yggaMinScale.Value; internal float YggaMaxScale => yggaMaxScale.Value; internal float YggaGrowthTime => yggaGrowthTime.Value; internal float YggaGrowRadius => yggaGrowRadius.Value; internal float AutumnBirchMinScale => autumnBirchMinScale.Value; internal float AutumnBirchMaxScale => autumnBirchMaxScale.Value; internal float AutumnBirchGrowthTime => autumnBirchGrowthTime.Value; internal float AutumnBirchGrowRadius => autumnBirchGrowRadius.Value; internal float AshwoodMinScale => ashwoodMinScale.Value; internal float AshwoodMaxScale => ashwoodMaxScale.Value; internal float AshwoodGrowthTime => ashwoodGrowthTime.Value; internal float AshwoodGrowRadius => ashwoodGrowRadius.Value; internal bool EnableSeedOverrides => enableSeedOverrides.Value; internal int SeedDropMin => seedDropMin.Value; internal int SeedDropMax => seedDropMax.Value; internal int TreeDropMin => treeDropMin.Value; internal int TreeDropMax => treeDropMax.Value; internal float DropChance => dropChance.Value; internal bool OneOfEach => oneOfEach.Value; internal bool EnablePickableTimers => enablePickableTimers.Value; internal bool EnablePlantTimers => enablePlantTimers.Value; internal bool GrowthAsPercentage => growthAsPercentage.Value; internal bool EnableVineOverrides => enableVineOverrides.Value; internal bool EnableCustomVinePiece => enableCustomVinePiece.Value; internal float VinesAttachDistance => vineAttachDistance.Value; internal float VineGrowRadius => vineGrowRadius.Value; internal float VinesGrowthTime => vineGrowthTime.Value; internal int VineBerryRespawnTime => vineBerryRespawnTime.Value; internal int VineBerryReturn => vineBerryReturn.Value; internal Color VinesColor => ashVineCustomColor.Value; internal List<ConfigEntry<Color>> BerryColors { get { List<ConfigEntry<Color>> list = _BerryColors; if (list == null) { List<ConfigEntry<Color>> obj = new List<ConfigEntry<Color>>(3) { rightBerryColor, centerBerryColor, leftBerryColor }; List<ConfigEntry<Color>> list2 = obj; _BerryColors = obj; list = list2; } return list; } } internal AshVineStyle AshVineStyle => ashVineStyle.Value; internal VineBerryStyle VineBerryStyle => vineBerryStyle.Value; internal CustomSyncedValue<List<string>> SyncedExtraResources => extraResources; internal bool IsSourceOfTruth => ConfigSync.IsSourceOfTruth; private ConfigEntry<T> Config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { ConfigEntry<T> val = ConfigFile.Bind<T>(group, name, value, description); ConfigSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronizedSetting; return val; } private ConfigEntry<T> Config<T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return Config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } internal ModConfig(ConfigFile configFile, ConfigSync configSync) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown //IL_042e: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Expected O, but got Unknown //IL_0466: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Expected O, but got Unknown //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Expected O, but got Unknown //IL_04de: Unknown result type (might be due to invalid IL or missing references) //IL_04e9: Expected O, but got Unknown //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_0525: Expected O, but got Unknown //IL_0556: Unknown result type (might be due to invalid IL or missing references) //IL_0561: Expected O, but got Unknown //IL_0592: Unknown result type (might be due to invalid IL or missing references) //IL_059d: Expected O, but got Unknown //IL_05ca: Unknown result type (might be due to invalid IL or missing references) //IL_05d5: Expected O, but got Unknown //IL_0602: Unknown result type (might be due to invalid IL or missing references) //IL_060d: Expected O, but got Unknown //IL_063a: Unknown result type (might be due to invalid IL or missing references) //IL_0645: Expected O, but got Unknown //IL_0672: Unknown result type (might be due to invalid IL or missing references) //IL_067d: Expected O, but got Unknown //IL_06aa: Unknown result type (might be due to invalid IL or missing references) //IL_06b5: Expected O, but got Unknown //IL_06e2: Unknown result type (might be due to invalid IL or missing references) //IL_06ed: Expected O, but got Unknown //IL_071a: Unknown result type (might be due to invalid IL or missing references) //IL_0725: Expected O, but got Unknown //IL_0752: Unknown result type (might be due to invalid IL or missing references) //IL_075d: Expected O, but got Unknown //IL_078a: Unknown result type (might be due to invalid IL or missing references) //IL_0795: Expected O, but got Unknown //IL_07c2: Unknown result type (might be due to invalid IL or missing references) //IL_07cd: Expected O, but got Unknown //IL_07fa: Unknown result type (might be due to invalid IL or missing references) //IL_0805: Expected O, but got Unknown //IL_0832: Unknown result type (might be due to invalid IL or missing references) //IL_083d: Expected O, but got Unknown //IL_086a: Unknown result type (might be due to invalid IL or missing references) //IL_0875: Expected O, but got Unknown //IL_08a2: Unknown result type (might be due to invalid IL or missing references) //IL_08ad: Expected O, but got Unknown //IL_08da: Unknown result type (might be due to invalid IL or missing references) //IL_08e5: Expected O, but got Unknown //IL_0912: Unknown result type (might be due to invalid IL or missing references) //IL_091d: Expected O, but got Unknown //IL_094a: Unknown result type (might be due to invalid IL or missing references) //IL_0955: Expected O, but got Unknown //IL_0982: Unknown result type (might be due to invalid IL or missing references) //IL_098d: Expected O, but got Unknown //IL_09ba: Unknown result type (might be due to invalid IL or missing references) //IL_09c5: Expected O, but got Unknown //IL_09f2: Unknown result type (might be due to invalid IL or missing references) //IL_09fd: Expected O, but got Unknown //IL_0a2a: Unknown result type (might be due to invalid IL or missing references) //IL_0a35: Expected O, but got Unknown //IL_0a62: Unknown result type (might be due to invalid IL or missing references) //IL_0a6d: Expected O, but got Unknown //IL_0a9a: Unknown result type (might be due to invalid IL or missing references) //IL_0aa5: Expected O, but got Unknown //IL_0ad2: Unknown result type (might be due to invalid IL or missing references) //IL_0add: Expected O, but got Unknown //IL_133f: Unknown result type (might be due to invalid IL or missing references) //IL_134a: Expected O, but got Unknown //IL_1371: Unknown result type (might be due to invalid IL or missing references) //IL_137c: Expected O, but got Unknown //IL_13a3: Unknown result type (might be due to invalid IL or missing references) //IL_13ae: Expected O, but got Unknown //IL_13d5: Unknown result type (might be due to invalid IL or missing references) //IL_13e0: Expected O, but got Unknown //IL_1407: Unknown result type (might be due to invalid IL or missing references) //IL_1412: Expected O, but got Unknown //IL_143d: Unknown result type (might be due to invalid IL or missing references) //IL_1448: Expected O, but got Unknown //IL_146f: Unknown result type (might be due to invalid IL or missing references) //IL_147a: Expected O, but got Unknown //IL_1504: Unknown result type (might be due to invalid IL or missing references) //IL_150f: Expected O, but got Unknown //IL_1542: Unknown result type (might be due to invalid IL or missing references) //IL_154d: Expected O, but got Unknown //IL_157f: Unknown result type (might be due to invalid IL or missing references) //IL_158a: Expected O, but got Unknown //IL_15bc: Unknown result type (might be due to invalid IL or missing references) //IL_15c7: Expected O, but got Unknown //IL_168d: Unknown result type (might be due to invalid IL or missing references) //IL_16b2: Unknown result type (might be due to invalid IL or missing references) //IL_16bd: Expected O, but got Unknown //IL_16e2: Unknown result type (might be due to invalid IL or missing references) //IL_1707: Unknown result type (might be due to invalid IL or missing references) //IL_1712: Expected O, but got Unknown //IL_1737: Unknown result type (might be due to invalid IL or missing references) //IL_175c: Unknown result type (might be due to invalid IL or missing references) //IL_1767: Expected O, but got Unknown //IL_178c: Unknown result type (might be due to invalid IL or missing references) //IL_17b1: Unknown result type (might be due to invalid IL or missing references) //IL_17bc: Expected O, but got Unknown ConfigFile = configFile; ConfigSync = configSync; configFile.SaveOnConfigSet = false; serverConfigLocked = Config("General", "LockConfiguration", value: true, "If on, the configuration is locked and can be changed by server admins only."); nexusID = Config("General", "NexusID", 1042, new ConfigDescription("Nexus mod ID for updates.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = "Internal", ReadOnly = true } }), synchronizedSetting: false); enableDebugMessages = Config("General", "EnableDebugMessages", value: false, "Enable mod debug messages in console.", synchronizedSetting: false); showPickableSpawners = Config("General", "ShowPickableSpawners", value: true, "Continue to show mushroom, thistle, and dandelion spawners after being picked. (Requires world reload on client to take effect.)", synchronizedSetting: false); enableMiscFlora = Config("General", "EnableMiscFlora", value: true, "Enables small trees, bushes, shrubs, vines, and large mushrooms."); enableDebris = Config("General", "EnableDebris", value: true, "Allows for the placement of debris such as branches, flint, and stone."); enableExtraResources = Config("General", "EnableExtraResources", value: false, "When set to true, the mod will attempt to make user-defined prefabs buildable with the cultivator. Prefabs are defined in PlantEverything_ExtraResources.cfg. If file is not present, an example one will be generated for you."); snappableVines = Config("General", "SnappableVines", value: true, "Enables snap points when placing vines adjacently.", synchronizedSetting: false); enableLocalization = Config("General", "EnableLocalization", value: false, "Enable this to attempt to load localized text data for the language set in the following setting.", synchronizedSetting: false); language = Config("General", "Language", "english", "Language to be used. If EnableLocalization is enabled, game will attempt to load localized text from a file named {language}_PlantEverything.json.", synchronizedSetting: false); disabledResourceNames = Config("General", "DisabledResourceNames", "", new ConfigDescription("To disable specific resources added by this mod (and not add them to the cultivator), list their prefab names here separated by a comma. Names are case-sensitive.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = -1 } })); requireCultivation = Config("Difficulty", "RequireCultivation", value: false, "Pickable resources can only be planted on cultivated ground."); placeAnywhere = Config("Difficulty", "PlaceAnywhere", value: false, "Allow resources to be placed anywhere (not just on the ground). Does not apply to mushrooms or flowers."); enforceBiomes = Config("Difficulty", "EnforceBiomes", value: false, "Restrict modded plantables (pickables and saplings) to being placed in their respective biome."); enforceBiomesVanilla = Config("Difficulty", "EnforceBiomesVanilla", value: true, "Restrict vanilla plantables (crops and saplings) to being placed in their respective biome."); plantsRequireShielding = Config("Difficulty", "PlantsRequireShielding", value: true, "Controls whether plants need shielding to survive in hostile environments."); canRemoveFlora = Config("Difficulty", "CanRemoveFlora", value: false, "Allows the cultivator to deconstruct decorative flora placed by a player. Useful for creative game types."); recoverResources = Config("Difficulty", "RecoverResources", value: false, "Recover resources when pickables are removed with the cultivator. Applies to berries, mushrooms, and flowers."); resourcesSpawnEmpty = Config("Difficulty", "ResourcesSpawnEmpty", value: false, "Specifies whether resources should spawn empty or full. Applies to berry bushes, mushrooms, flowers, and debris."); enemiesTargetPieces = Config("Difficulty", "EnemiesTargetPieces", value: true, "When enabled, enemies may target and attack player placed resources added by the mod. If this setting is changed, pre-existing placed pieces will not be affected until the world/server is reloaded."); raspberryCost = Config("Berries", "RaspberryCost", 5, "Number of raspberries required to place a raspberry bush. Set to 0 to disable the ability to plant this resource."); blueberryCost = Config("Berries", "BlueberryCost", 5, "Number of blueberries required to place a blueberry bush. Set to 0 to disable the ability to plant this resource."); cloudberryCost = Config("Berries", "CloudberryCost", 5, "Number of cloudberries required to place a cloudberry bush. Set to 0 to disable the ability to plant this resource."); raspberryRespawnTime = Config("Berries", "RaspberryRespawnTime", 300, "Number of minutes it takes for a raspberry bush to respawn berries."); blueberryRespawnTime = Config("Berries", "BlueberryRespawnTime", 300, "Number of minutes it takes for a blueberry bush to respawn berries."); cloudberryRespawnTime = Config("Berries", "CloudberryRespawnTime", 300, "Number of minutes it takes for a cloudberry bush to respawn berries."); raspberryReturn = Config("Berries", "RaspberryReturn", 1, "Number of berries a raspberry bush will spawn."); blueberryReturn = Config("Berries", "BlueberryReturn", 1, "Number of berries a blueberry bush will spawn."); cloudberryReturn = Config("Berries", "CloudberryReturn", 1, "Number of berries a cloudberry bush will spawn."); enableCropOverrides = Config("Crops", "EnableCropOverrides", value: false, new ConfigDescription("Enables the [Crops] section of this config.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 28 } })); overrideModdedCrops = Config("Crops", "OverrideModdedCrops", value: true, new ConfigDescription("Applies all [Crops] settings to 3rd party modded crops.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[1] })); cropMinScale = Config("Crops", "CropMinScale", 0.9f, new ConfigDescription("The minimum scaling factor used to scale crops upon growth.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); cropMaxScale = Config("Crops", "CropMaxScale", 1.1f, new ConfigDescription("The maximum scaling factor used to scale crops upon growth.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); cropGrowTimeMin = Config("Crops", "CropGrowTimeMin", 4000f, new ConfigDescription("Minimum number of seconds it takes for crops to grow (will take at least 10 seconds after planting to grow).", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); cropGrowTimeMax = Config("Crops", "CropGrowTimeMax", 5000f, new ConfigDescription("Maximum number of seconds it takes for crops to grow (will take at least 10 seconds after planting to grow).", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); cropGrowRadius = Config("Crops", "CropGrowRadius", 0.5f, new ConfigDescription("Radius of free space required for crops to grow.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); cropRequireCultivation = Config("Crops", "CropsRequireCultivation", value: true, new ConfigDescription("Crops can only be planted on cultivated ground.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[1] })); cropRequireSunlight = Config("Crops", "CropsRequireSunlight", value: true, new ConfigDescription("Crops can only grow under an open sky.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[1] })); cropRequireGrowthSpace = Config("Crops", "CropsRequireGrowthSpace", value: true, new ConfigDescription("Crops require space to grow. This setting overrides the CropGrowRadius setting but without altering it, allowing grid spacing mods to continue functioning.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[1] })); enemiesTargetCrops = Config("Crops", "EnemiesTargetCrops", value: true, new ConfigDescription("Determines whether enemies will target and attack crops. If this setting is changed, pre-existing placed crops will not be affected until the world/server is reloaded.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[1] })); barleyCost = Config("Crops", "BarleyCost", 1, new ConfigDescription("Resource cost of planting barley.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); barleyReturn = Config("Crops", "BarleyReturn", 2, new ConfigDescription("Resources gained upon harvesting barley (does not apply to wild barley).", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); carrotCost = Config("Crops", "CarrotCost", 1, new ConfigDescription("Resource cost of planting carrots.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); carrotReturn = Config("Crops", "CarrotReturn", 1, new ConfigDescription("Resources gained upon harvesting carrots.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); flaxCost = Config("Crops", "FlaxCost", 1, new ConfigDescription("Resource cost of planting flax.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); flaxReturn = Config("Crops", "FlaxReturn", 2, new ConfigDescription("Resources gained upon harvesting flax (does not apply to wild flax).", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); onionCost = Config("Crops", "OnionCost", 1, new ConfigDescription("Resource cost of planting onions.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); onionReturn = Config("Crops", "OnionReturn", 1, new ConfigDescription("Resources gained upon harvesting onions.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); seedCarrotCost = Config("Crops", "SeedCarrotCost", 1, new ConfigDescription("Resource cost of planting seed carrots.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); seedCarrotReturn = Config("Crops", "SeedCarrotReturn", 3, new ConfigDescription("Resources gained upon harvesting seed carrots.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); seedOnionCost = Config("Crops", "SeedOnionCost", 1, new ConfigDescription("Resource cost of planting seed onions.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); seedOnionReturn = Config("Crops", "SeedOnionReturn", 3, new ConfigDescription("Resources gained upon harvesting seed onions.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); seedTurnipCost = Config("Crops", "SeedTurnipCost", 1, new ConfigDescription("Resource cost of planting seed turnips.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); seedTurnipReturn = Config("Crops", "SeedTurnipReturn", 3, new ConfigDescription("Resources gained upon harvesting seed turnips.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); turnipCost = Config("Crops", "TurnipCost", 1, new ConfigDescription("Resource cost of planting turnips.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); turnipReturn = Config("Crops", "TurnipReturn", 1, new ConfigDescription("Resources gained upon harvesting turnips.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); magecapCost = Config("Crops", "MagecapCost", 1, new ConfigDescription("Resource cost of planting magecap.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); magecapReturn = Config("Crops", "MagecapReturn", 3, new ConfigDescription("Resources gained upon harvesting magecap.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); jotunPuffsCost = Config("Crops", "JotunPuffsCost", 1, new ConfigDescription("Resource cost of planting Jotun puffs.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); jotunPuffsReturn = Config("Crops", "JotunPuffsReturn", 3, new ConfigDescription("Resources gained upon harvesting Jotun puffs.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] })); pickableBranchCost = Config("Debris", "PickableBranchCost", 5, "Amount of wood required to place branch debris. Set to 0 to disable the ability to plant this resource."); pickableBranchReturn = Config("Debris", "PickableBranchReturn", 1, "Amount of wood that branch debris drops when picked."); pickableBranchRespawnTime = Config("Debris", "PickableBranchRespawnTime", 240, "Number of minutes it takes for a pickable branch to respawn."); pickableStoneCost = Config("Debris", "PickableStoneCost", 1, "Amount of stone required to place stone debris. Set to 0 to disable the ability to plant this resource."); pickableStoneReturn = Config("Debris", "PickableStoneReturn", 1, "Amount of stones that stone debris drops when picked."); pickableStoneRespawnTime = Config("Debris", "PickableStoneRespawnTime", 0, "Number of minutes it takes for a pickable Stone to respawn."); pickableFlintCost = Config("Debris", "PickableFlintCost", 5, "Amount of flint required to place flint debris. Set to 0 to disable the ability to plant this resource."); pickableFlintReturn = Config("Debris", "PickableFlintReturn", 1, "Amount of flint that flint debris drops when picked."); pickableFlintRespawnTime = Config("Debris", "PickableFlintRespawnTime", 240, "Number of minutes it takes for pickable flint to respawn."); mushroomCost = Config("Mushrooms", "MushroomCost", 5, "Number of mushrooms required to place a pickable mushroom spawner. Set to 0 to disable the ability to plant this resource."); yellowMushroomCost = Config("Mushrooms", "YellowMushroomCost", 5, "Number of yellow mushrooms required to place a pickable yellow mushroom spawner. Set to 0 to disable the ability to plant this resource."); blueMushroomCost = Config("Mushrooms", "BlueMushroomCost", 5, "Number of blue mushrooms required to place a pickable blue mushroom spawner. Set to 0 to disable the ability to plant this resource."); smokePuffCost = Config("Mushrooms", "SmokepuffCost", 5, "Number of smoke puffs required to place a pickable smoke puff spawner. Set to 0 to disable the ability to plant this resource."); mushroomRespawnTime = Config("Mushrooms", "MushroomRespawnTime", 240, "Number of minutes it takes for mushrooms to respawn."); yellowMushroomRespawnTime = Config("Mushrooms", "YellowMushroomRespawnTime", 240, "Number of minutes it takes for yellow mushrooms to respawn."); blueMushroomRespawnTime = Config("Mushrooms", "BlueMushroomRespawnTime", 240, "Number of minutes it takes for blue mushrooms to respawn."); smokePuffRespawnTime = Config("Mushrooms", "SmokepuffRespawnTime", 240, "Number of minutes it takes for smoke puffs to respawn."); mushroomReturn = Config("Mushrooms", "MushroomReturn", 1, "Number of mushrooms a pickable mushroom spawner will spawn."); yellowMushroomReturn = Config("Mushrooms", "YellowMushroomReturn", 1, "Number of yellow mushrooms a pickable yellow mushroom spawner will spawn."); blueMushroomReturn = Config("Mushrooms", "BlueMushroomReturn", 1, "Number of blue mushrooms a pickable blue mushroom spawner will spawn."); smokePuffReturn = Config("Mushrooms", "SmokepuffReturn", 1, "Number of smoke puffs a pickable smoke puff spawner will spawn."); thistleCost = Config("Flowers", "ThistleCost", 5, "Number of thistle required to place a pickable thistle spawner. Set to 0 to disable the ability to plant this resource."); dandelionCost = Config("Flowers", "DandelionCost", 5, "Number of dandelion required to place a pickable dandelion spawner. Set to 0 to disable the ability to plant this resource."); fiddleheadCost = Config("Flowers", "FiddleheadCost", 15, "Number of fiddlehead required to place a pickable fiddlehead spawner. Set to 0 to disable the ability to plant this resource."); thistleRespawnTime = Config("Flowers", "ThistleRespawnTime", 240, "Number of minutes it takes for thistle to respawn."); dandelionRespawnTime = Config("Flowers", "DandelionRespawnTime", 240, "Number of minutes it takes for dandelion to respawn."); fiddleheadRespawnTime = Config("Flowers", "FiddleheadRespawnTime", 300, "Number of minutes it takes for fiddlehead to respawn."); thistleReturn = Config("Flowers", "ThistleReturn", 1, "Number of thistle a pickable thistle spawner will spawn."); dandelionReturn = Config("Flowers", "DandelionReturn", 1, "Number of dandelion a pickable dandelion spawner will spawn."); fiddleheadReturn = Config("Flowers", "FiddleheadReturn", 3, "Number of fiddlehead a pickable fiddlehead spawner will spawn."); birchMinScale = Config("Saplings", "BirchMinScale", 0.5f, "The minimum scaling factor used to scale a birch tree upon growth."); birchMaxScale = Config("Saplings", "BirchMaxScale", 1f, "The maximum scaling factor used to scale a birch tree upon growth."); oakMinScale = Config("Saplings", "OakMinScale", 0.7f, "The minimum scaling factor used to scale an oak tree upon growth."); oakMaxScale = Config("Saplings", "OakMaxScale", 0.9f, "The maximum scaling factor used to scale an oak tree upon growth."); ancientMinScale = Config("Saplings", "AncientMinScale", 0.5f, "The minimum scaling factor used to scale an ancient tree upon growth."); ancientMaxScale = Config("Saplings", "AncientMaxScale", 2f, "The maximum scaling factor used to scale an ancient tree upon growth."); birchGrowthTime = Config("Saplings", "BirchGrowthTime", 3000f, "Number of seconds it takes for a birch tree to grow from a birch sapling (will take at least 10 seconds after planting to grow)."); oakGrowthTime = Config("Saplings", "OakGrowthTime", 3000f, "Number of seconds it takes for an oak tree to grow from an oak sapling (will take at least 10 seconds after planting to grow)."); ancientGrowthTime = Config("Saplings", "AncientGrowthTime", 3000f, "Number of seconds it takes for an ancient tree to grow from an ancient sapling (will take at least 10 seconds after planting to grow)."); birchGrowRadius = Config("Saplings", "BirchGrowRadius", 2f, "Radius of free space required for a birch sapling to grow."); oakGrowRadius = Config("Saplings", "OakGrowRadius", 3f, "Radius of free space required for an oak sapling to grow."); ancientGrowRadius = Config("Saplings", "AncientGrowRadius", 2f, "Radius of free space required for an ancient sapling to grow."); beechGrowthTime = Config("Saplings", "BeechGrowthTime", 3000f, "Number of seconds it takes for a beech tree to grow from a beech sapling (will take at least 10 seconds after planting to grow)."); pineGrowthTime = Config("Saplings", "PineGrowthTime", 3000f, "Number of seconds it takes for a pine tree to grow from a pine sapling (will take at least 10 seconds after planting to grow)."); firGrowthTime = Config("Saplings", "FirGrowthTime", 3000f, "Number of seconds it takes for a fir tree to grow from a fir sapling (will take at least 10 seconds after planting to grow)."); beechMinScale = Config("Saplings", "BeechMinScale", 0.8f, "The minimum scaling factor used to scale a beech tree upon growth."); beechMaxScale = Config("Saplings", "BeechMaxScale", 1.5f, "The maximum scaling factor used to scale a beech tree upon growth."); pineMinScale = Config("Saplings", "PineMinScale", 1.5f, "The minimum scaling factor used to scale a pine tree upon growth."); pineMaxScale = Config("Saplings", "PineMaxScale", 2.5f, "The maximum scaling factor used to scale a pine tree upon growth."); firMinScale = Config("Saplings", "FirMinScale", 1f, "The minimum scaling factor used to scale a fir tree upon growth."); firMaxScale = Config("Saplings", "FirMaxScale", 2.5f, "The maximum scaling factor used to scale a fir tree upon growth."); beechGrowRadius = Config("Saplings", "BeechGrowRadius", 2f, "Radius of free space required for a beech sapling to grow."); pineGrowRadius = Config("Saplings", "PineGrowRadius", 2f, "Radius of free space required for a pine sapling to grow."); firGrowRadius = Config("Saplings", "FirGrowRadius", 2f, "Radius of free space required for a fir sapling to grow."); yggaMinScale = Config("Saplings", "YggaMinScale", 0.5f, "The minimum scaling factor used to scale a ygga tree upon growth."); yggaMaxScale = Config("Saplings", "YggaMaxScale", 2f, "The minimum scaling factor used to scale a ygga tree upon growth."); yggaGrowthTime = Config("Saplings", "YggaGrowthTime", 3000f, "Number of seconds it takes for a ygga tree to grow from a ygga sapling (will take at least 10 seconds after planting to grow)."); yggaGrowRadius = Config("Saplings", "YggaGrowRadius", 2f, "Radius of free space required for a ygga sapling to grow."); autumnBirchMinScale = Config("Saplings", "AutumnBirchMinScale", 0.5f, "The minimum scaling factor used to scale an autumn birch tree upon growth."); autumnBirchMaxScale = Config("Saplings", "AutumnBirchMaxScale", 1f, "The minimum scaling factor used to scale an autumn birch tree upon growth."); autumnBirchGrowthTime = Config("Saplings", "AutumnBirchGrowthTime", 3000f, "Number of seconds it takes for an autumn birch tree to grow from an autumn birch sapling (will take at least 10 seconds after planting to grow)."); autumnBirchGrowRadius = Config("Saplings", "AutumnBirchGrowRadius", 2f, "Radius of free space required for an autumn birch sapling to grow."); ashwoodMinScale = Config("Saplings", "AshwoodMinScale", 0.5f, "The minimum scaling factor used to scale an ashwood tree upon growth."); ashwoodMaxScale = Config("Saplings", "AshwoodMaxScale", 2f, "The minimum scaling factor used to scale an ashwood tree upon growth."); ashwoodGrowthTime = Config("Saplings", "AshwoodGrowthTime", 3000f, "Num
Plugins/CreatureLevelControl.dll
Decompiled 2 years 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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("")] [assembly: AssemblyTitle("CreatureLevelControl")] [assembly: AssemblyDescription("https://valheim.thunderstore.io/package/Smoothbrain/CreatureLevelAndLootControl")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: ComVisible(false)] [assembly: AssemblyProduct("CreatureLevelControl")] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Guid("6363d416-d2b3-437d-8f72-ed0069245f86")] [assembly: AssemblyConfiguration("")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: <7013c0bb-d076-4a4c-bf25-c72e6d37edc8>RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [<08d3f5d2-4c29-46e1-8090-17b3656410f6>Embedded] [CompilerGenerated] internal sealed class <08d3f5d2-4c29-46e1-8090-17b3656410f6>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [<08d3f5d2-4c29-46e1-8090-17b3656410f6>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [<08d3f5d2-4c29-46e1-8090-17b3656410f6>Embedded] [CompilerGenerated] internal sealed class <11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContextAttribute : Attribute { public readonly byte Flag; public <11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContextAttribute(byte P_0) { Flag = P_0; } } [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [<08d3f5d2-4c29-46e1-8090-17b3656410f6>Embedded] [CompilerGenerated] internal sealed class <7013c0bb-d076-4a4c-bf25-c72e6d37edc8>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <7013c0bb-d076-4a4c-bf25-c72e6d37edc8>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CreatureLevelControl { public enum CreatureExtraEffect { None, Aggressive, Quick, Regenerating, Curious, Splitting, Armored } public enum CreatureInfusion { None, Lightning, Fire, Frost, Poison, Chaos, Spirit } public enum BossAffix { None, Reflective, Shielded, Mending, Summoner, Elementalist, Enraged, Twin } [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] [PublicAPI] [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(1)] public static class API { public static bool IsEnabled() { return true; } public static bool IsInfusionEnabled() { return CreatureLevelControl.creatureInfusionEffects.GetToggle(); } public static bool IsExtraEffectEnabled() { return CreatureLevelControl.creatureSpecialEffects.GetToggle(); } public static bool IsAffixEnabled() { return CreatureLevelControl.bossSpecialEffects.GetToggle(); } public static int GetWorldLevel() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_006b: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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) if (!Object.op_Implicit((Object)(object)ZoneSystem.instance) || !Object.op_Implicit((Object)(object)Game.instance)) { return 0; } int result = CreatureLevelControl.worldLevels.Count; if (CreatureLevelControl.difficultySecondFactor.Value == CreatureLevelControl.DifficultySecondFactor.Distance) { Vector3 val = default(Vector3); ZoneSystem.instance.GetLocationIcon(Game.instance.m_StartLocation, ref val); Player localPlayer = Player.m_localPlayer; Vector3 val2 = (Vector3)((localPlayer != null) ? ((Component)localPlayer).transform.localPosition : default(Vector3)) - val; float num = Mathf.Sqrt(Mathf.Pow(val2.x, 2f) + Mathf.Pow(val2.z, 2f)); foreach (ConfigEntry<int> key in CreatureLevelControl.spawnDistance.Keys) { if (num < (float)key.Value) { result = CreatureLevelControl.spawnDistance[key]; break; } } } else if (CreatureLevelControl.difficultySecondFactor.Value != CreatureLevelControl.DifficultySecondFactor.Age_of_world) { result = ((CreatureLevelControl.difficultySecondFactor.Value != CreatureLevelControl.DifficultySecondFactor.BossesKilled) ? 3 : new string[6] { "eikthyr", "gdking", "bonemass", "dragon", "goblinking", "queen" }.Count([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (string boss) => ZoneSystem.instance.GetGlobalKey("defeated_" + boss))); } else { int day = EnvMan.instance.GetDay(ZNet.instance.GetTimeSeconds()); foreach (ConfigEntry<int> key2 in CreatureLevelControl.worldLevels.Keys) { if (day < key2.Value) { result = CreatureLevelControl.worldLevels[key2]; break; } } } return result; } internal static float[] zeroProbabilities(float[] p, int shift = 0) { float num = 100f; for (int i = 0; i < p.Length; i++) { num -= p[i]; if (num < 0f) { p[i] += num; num = 0f; } } float[] array = new float[shift + 1].Concat(p).ToArray(); array[shift] = num; return array; } public static float[] LevelProbabilities([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] Character character, int worldLevel, bool includeZoneBonusLevel) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) int num; if (!includeZoneBonusLevel) { num = 0; } else { object obj; if (character == null) { obj = null; } else { ZNetView component = ((Component)character).GetComponent<ZNetView>(); obj = ((component != null) ? component.GetZDO() : null); } num = ((obj == null) ? CreatureSector.sectorBonusLevel(((Component)Player.m_localPlayer).GetComponent<ZNetView>().GetZDO().GetSector()) : CreatureSector.sectorBonusLevel(character)); } int num2 = num; if ((Object)(object)character != (Object)null) { float[] array = Utils.ReadWithWorldLevelFromConfig(character, [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] (CreatureConfig c) => c.worldLevelToStars); if (array != null) { return zeroProbabilities(array, (!character.IsBoss()) ? num2 : 0); } } if (character != null && character.IsBoss() && !CreatureLevelControl.bossLevelUseCreatureLevel.GetToggle()) { return zeroProbabilities(Utils.ParseStringProbabilities(CreatureLevelControl.customBossLevelChances.Value)); } if (CreatureLevelControl.difficulty.Value == CreatureLevelControl.Difficulty.Custom) { return zeroProbabilities(Utils.ParseStringProbabilities(CreatureLevelControl.customLevelChances[worldLevel].Value), num2); } if (!CreatureLevelControl.levelConfig.TryGetValue(CreatureLevelControl.difficulty.Value, out var value)) { value = CreatureLevelControl.levelConfig[CreatureLevelControl.Difficulty.Medium]; } float[] source = zeroProbabilities(value[worldLevel], num2); int value2 = (int)CreatureLevelControl.minimumLevel.Value; int num3 = Math.Max(value2, (int)CreatureLevelControl.maximumLevel.Value); float num4 = source.Take(value2).Sum(); float num5 = source.Skip(1 + num3).Sum(); source = new float[value2].Concat(source.Skip(value2).Take(1 + num3 - value2)).ToArray(); source[value2] += num4; if (num5 > 0f) { source = source.Concat(new float[Mathf.Max(0, 1 + num3 - source.Length)]).ToArray(); source[num3] += num5; } return source; } public static int LevelRand(Character character) { return Utils.LevelFromProbabilities(LevelProbabilities(character, GetWorldLevel(), includeZoneBonusLevel: true)); } public static bool HasAffixBoss(Character character) { return HasExtraEffectCreature(character); } public static BossAffix GetAffixBoss(Character character) { ZNetView component = ((Component)character).GetComponent<ZNetView>(); if (!CreatureLevelControl.bossSpecialEffects.GetToggle() || ((component != null) ? component.GetZDO() : null) == null) { return BossAffix.None; } return (BossAffix)component.GetZDO().GetInt("CL&LC effect", 0); } public static void SetAffixBoss(Character character, BossAffix affix) { //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) string[] source = new string[7] { "Eikthyr", "gd_king", "Bonemass", "Dragon", "GoblinKing", "SeekerQueen", "Fader" }; if (affix == BossAffix.Summoner && !source.Contains(((Object)character).name.Replace("(Clone)", ""))) { affix = BossAffix.None; } if (GetAffixBoss(character) == BossAffix.Twin) { if (affix != BossAffix.Twin) { Character twinBoss = GetTwinBoss(character); GameObject val = ((twinBoss != null) ? ((Component)twinBoss).gameObject : null); if (val != null) { ZNetScene.instance.Destroy(val); } } float num = Utils.ReadValueFromEnumWithWorldLevelAndStarsFromConfig(character, BossAffix.Twin, [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1, 2 })] (CreatureConfig c) => c.worldLevelToBossAffixFactor) ?? (CreatureLevelControl.bossAffixPowerTwin.Value / 100f); character.m_health /= num; character.SetupMaxHealth(); } else if (affix == BossAffix.Twin) { if (CreatureLevelControl.bossSpecialEffects.GetToggle()) { float num2 = Utils.ReadValueFromEnumWithWorldLevelAndStarsFromConfig(character, BossAffix.Twin, [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1, 2 })] (CreatureConfig c) => c.worldLevelToBossAffixFactor) ?? (CreatureLevelControl.bossAffixPowerTwin.Value / 100f); character.m_health *= num2; character.SetupMaxHealth(); setAffixBossZDO(character, affix); ZPackage val2 = new ZPackage(); character.m_nview.GetZDO().Serialize(val2); val2.SetPos(0); ZDO val3 = new ZDO(); val3.Init(); val3.m_uid = Utils.GenerateNewZDOID(); val3.Deserialize(val2); val3.SetRotation(Quaternion.Euler(0f, Random.Range(0f, 360f), 0f)); val3.SetPosition(((Component)character).transform.localPosition + Random.insideUnitSphere * 0.5f); val3.SetOwnerInternal(ZDOMan.GetSessionID()); ZDOMan.instance.m_objectsByID.Add(val3.m_uid, val3); Character component = ZNetScene.instance.CreateObject(val3).GetComponent<Character>(); Vector3 insideUnitSphere = Random.insideUnitSphere; if (insideUnitSphere.y < 0f) { insideUnitSphere.y = 0f - insideUnitSphere.y; } ((Component)component).GetComponent<Rigidbody>().AddForce(insideUnitSphere * 5f, (ForceMode)2); CreatureLevelControl.SetTwinBoss(character, component); } else { affix = BossAffix.None; } } setAffixBossZDO(character, affix); OriginalCharacterData component2 = ((Component)character).GetComponent<OriginalCharacterData>(); if (component2 != null) { component2.Awake(); } else { ((Component)character).gameObject.AddComponent<OriginalCharacterData>(); } CreatureLevelControl.ShowStar.NeedsUpdate.Remove(character); } private static void setAffixBossZDO(Character character, BossAffix affix) { ((Component)character).GetComponent<ZNetView>().GetZDO().Set("CL&LC effect", (int)affix); } public static bool HasExtraEffectCreature(Character character) { return ((Component)character).GetComponent<ZNetView>().GetZDO().GetInt("CL&LC effect", -1) != -1; } public static CreatureExtraEffect GetExtraEffectCreature(Character character) { ZNetView component = ((Component)character).GetComponent<ZNetView>(); if (!CreatureLevelControl.creatureSpecialEffects.GetToggle() || ((component != null) ? component.GetZDO() : null) == null || character.GetLevel() <= 1) { return CreatureExtraEffect.None; } return (CreatureExtraEffect)component.GetZDO().GetInt("CL&LC effect", 0); } public static void SetExtraEffectCreature(Character character) { float rand; HashSet<CreatureExtraEffect> processedProbabilities; CreatureExtraEffect? creatureExtraEffect = Utils.RandomWithProbabilityFromConfig(character, [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 1, 2 })] (CreatureConfig c) => c.worldLevelToCreatureEffect, out rand, out processedProbabilities); if (!creatureExtraEffect.HasValue) { creatureExtraEffect = CreatureExtraEffect.None; foreach (CreatureExtraEffect key in CreatureLevelControl.customCreatureAffixChances.Keys) { if (!processedProbabilities.Contains(key)) { rand -= CreatureLevelControl.customCreatureAffixChances[key].Value; if (rand < 0f) { creatureExtraEffect = key; break; } } } } SetExtraEffectCreature(character, creatureExtraEffect.Value); } public static void SetExtraEffectCreature(Character character, CreatureExtraEffect effect) { ((Component)character).GetComponent<ZNetView>().GetZDO().Set("CL&LC effect", (int)effect); CreatureLevelControl.SetPersistedCharacterAttributes(character); CreatureLevelControl.ShowStar.NeedsUpdate.Remove(character); } public static bool HasInfusionCreature(Character character) { return ((Component)character).GetComponent<ZNetView>().GetZDO().GetInt("CL&LC infusion", -1) != -1; } public static CreatureInfusion GetInfusionCreature(Character character) { ZNetView component = ((Component)character).GetComponent<ZNetView>(); if (!CreatureLevelControl.creatureInfusionEffects.GetToggle() || ((component != null) ? component.GetZDO() : null) == null) { return CreatureInfusion.None; } return (CreatureInfusion)component.GetZDO().GetInt("CL&LC infusion", 0); } public static void SetInfusionCreature(Character character) { float rand; HashSet<CreatureInfusion> processedProbabilities; CreatureInfusion? creatureInfusion = Utils.RandomWithProbabilityFromConfig(character, [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 1, 2 })] (CreatureConfig c) => c.worldLevelToInfusion, out rand, out processedProbabilities); CreatureInfusion infusion; if (creatureInfusion.HasValue) { infusion = creatureInfusion.GetValueOrDefault(); } else { infusion = CreatureInfusion.None; if (!CreatureLevelControl.infusionProbabilityModifiersByLevel.TryGetValue(character.GetLevel(), out var value)) { value = 1f; } if (Random.Range(0f, 1f) <= value) { foreach (CreatureInfusion key in CreatureLevelControl.customCreatureInfusionChances.Keys) { if (!processedProbabilities.Contains(key)) { rand -= CreatureLevelControl.customCreatureInfusionChances[key].Value; if (rand < 0f) { infusion = key; break; } } } } } SetInfusionCreature(character, infusion); } public static void SetInfusionCreature(Character character, CreatureInfusion infusion) { ((Component)character).GetComponent<ZNetView>().GetZDO().Set("CL&LC infusion", (int)infusion); OriginalCharacterData component = ((Component)character).GetComponent<OriginalCharacterData>(); if (component != null) { component.immutableExtra = true; } CreatureLevelControl.AttachInfusionFlames(character); CreatureLevelControl.ShowStar.NeedsUpdate.Remove(character); } [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] public static Character GetTwinBoss(Character boss) { //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_0020: Unknown result type (might be due to invalid IL or missing references) ZDOID zDOID = ((Component)boss).GetComponent<ZNetView>().GetZDO().GetZDOID("CL&LC twin boss"); if (ZDOMan.instance.m_objectsByID.TryGetValue(zDOID, out var value) && ZNetScene.s_instance.m_instances.TryGetValue(value, out var value2)) { return ((Component)value2).GetComponent<Character>(); } return null; } public static bool DropItemOnDeath(ItemData item) { bool? flag = Utils.ReadWithWorldLevelFromConfig(item, [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] (ItemConfig c) => c.worldLevelToItemLoss); if (!flag.HasValue) { if (!item.m_shared.m_questItem) { return !item.m_equipped; } return false; } return flag.GetValueOrDefault(); } } [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(2)] public class ConfigurationManagerAttributes { public bool? ShowRangeAsPercent; [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1 })] public Action<ConfigEntryBase> CustomDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1, 1 })] public Func<object, string> ObjToStr; [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1, 1 })] public Func<string, object> StrToObj; } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(1)] [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] public abstract class ConfigFile { public interface Loader { [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] ConfigFile ConfigFile { [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(2)] get; [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(2)] set; } string FilePattern { get; } string EditButtonName { get; } CustomSyncedValue<List<string>> FileData { get; } bool Enabled { get; } ConfigFile InstantiateConfig(); void ProcessConfig(); } [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] protected class Section : IDisposable { [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] private readonly Section lastSection; [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] private readonly Dictionary<string, object> dict; public readonly string dictKey; private readonly HashSet<string> knownKeys = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase); private readonly ConfigFile configFile; public string Path => ((lastSection == null || lastSection.dictKey == "") ? "" : (lastSection.Path + ".")) + dictKey; public Section([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] Dictionary<string, object> dict, string key, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] Section lastSection, ConfigFile file) { this.dict = dict; dictKey = key; this.lastSection = lastSection; configFile = file; } [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] public object Get(string key) { knownKeys.Add(key); if (dict.TryGetValue(key, out var value) && value == null) { configFile.configErrors.Add(Path + "." + key + " cannot be empty"); } return value; } public IEnumerable<string> KeysWithPrefix(string prefix) { return dict.Keys.Where([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (string k) => k.StartsWith(prefix)); } public void Dispose() { IEnumerable<string> enumerable = dict.Keys.Where([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (string key) => !knownKeys.Contains(key)).ToArray(); if (enumerable.Any()) { configFile.configWarnings.Add(Path + " contains unknown keys " + string.Join(", ", enumerable)); } } } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] protected delegate bool ParserDelegate<[<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] ref T target, Section sect, string key); [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(2)] [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] private struct ParseResult<T> { [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(1)] public T value; public string error; } public static readonly Loader[] loaders = new Loader[2] { new CreatureConfig.Loader(), new ItemConfig.Loader() }; public readonly List<string> configErrors = new List<string>(); public readonly List<string> configWarnings = new List<string>(); protected readonly Dictionary<string, List<string>> groups = new Dictionary<string, List<string>>(); public void DumpWarnings(string prefix) { if (configWarnings.Count > 0) { Debug.LogWarning((object)(prefix + ((configErrors.Count > 0) ? "" : " The config file was loaded, but may not yield expected results due to warnings:") + "\n" + string.Join("\n", configWarnings))); configWarnings.Clear(); } } protected void AssignConfig<[<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] T>(ref T newConfig, T inConfig) where T : class { if (newConfig == null) { newConfig = inConfig; } } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] protected void AssignConfig<T>(ref T? newConfig, T? inConfig) where T : struct { T? val = newConfig; if (!val.HasValue) { newConfig = inConfig; } } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(2)] protected void AssignEnumConfig<T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1, 1, 2 })] ref Dictionary<int, Dictionary<T, float[]>> newConfig, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1, 1, 2 })] Dictionary<int, Dictionary<T, float[]>> inConfig) { if (inConfig == null) { return; } if (newConfig == null) { newConfig = inConfig.ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<int, Dictionary<T, float[]>> kv) => kv.Key, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<int, Dictionary<T, float[]>> kv) => kv.Value.ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<T, float[]> k) => k.Key, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<T, float[]> k) => k.Value)); } foreach (KeyValuePair<int, Dictionary<T, float[]>> item in inConfig) { if (!newConfig.ContainsKey(item.Key)) { newConfig[item.Key] = item.Value; continue; } foreach (KeyValuePair<T, float[]> item2 in item.Value) { if (!newConfig[item.Key].ContainsKey(item2.Key)) { newConfig[item.Key][item2.Key] = item2.Value; } } } } protected void resolveGroupsForName(List<string> groupNames, string name) { foreach (KeyValuePair<string, List<string>> group in groups) { if (!groupNames.Contains(group.Key) && group.Value.Contains(name)) { groupNames.Add(group.Key); resolveGroupsForName(groupNames, group.Key); } } } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(2)] protected void fillWorldLevels<T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1 })] Dictionary<int, T> config) { if (config == null) { return; } T value = default(T); int num = -1; for (int i = 0; i <= CreatureLevelControl.defaultWorldLevelDays.Length; i++) { if (config.TryGetValue(i, out var value2)) { value = value2; if (num == -1) { num = i; } } else if (num != -1) { config[i] = value; } } for (int j = 0; j < num; j++) { config[j] = config[num]; } } [PublicAPI] [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] protected static Dictionary<string, object> castDictToStringDict([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] Dictionary<object, object> dict) { return new Dictionary<string, object>(dict.ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<object, object> kv) => kv.Key.ToString(), [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<object, object> kv) => kv.Value), StringComparer.CurrentCultureIgnoreCase); } [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] protected Section section(Section parent, string key) { object obj = parent.Get(key); if (obj is Dictionary<object, object> dict) { return new Section(castDictToStringDict(dict), key, parent, this); } if (obj != null) { configWarnings.Add($"Expected a section containing further configuration values, got {obj.GetType()} for {parent.Path}.{key}"); } return null; } public void Parse(object configObj) { if (configObj is Dictionary<object, object> dict) { Dictionary<string, object> dictionary = castDictToStringDict(dict); foreach (KeyValuePair<string, object> item2 in dictionary) { if (item2.Key == "groups") { if (item2.Value is Dictionary<object, object> dictionary2) { foreach (KeyValuePair<object, object> item3 in dictionary2) { string text = item3.Key.ToString(); List<string> source; if (item3.Value is string item) { source = new List<string> { item }; } else { if (!(item3.Value is List<object> source2)) { configErrors.Add("groups." + text + " contains an invalid value (" + (item3.Value?.GetType().Name ?? "null") + ")"); continue; } source = source2.Where([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (object s) => s != null).Cast<string>().ToList(); } groups[text.ToLower()] = source.Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (string s) => s.ToLower()).ToList(); } } else { configErrors.Add("groups must contain a mapping from group to a list of group or creature names"); } } else { Section section = this.section(new Section(dictionary, "", null, this), item2.Key); if (section != null) { ParsePrimarySection(section); section.Dispose(); continue; } configErrors.Add("All top-level keys must be a mapping. Got unexpected " + (item2.Value?.GetType().ToString() ?? "null") + " for key '" + item2.Key + "'."); } } } Verify(); } protected virtual void Verify() { } protected abstract void ParsePrimarySection(Section primarySection); [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] private bool parseScalar<T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(1)] string input, out T output) where T : struct { if (typeof(int) == typeof(T)) { if (int.TryParse(input, out var result)) { output = (T)(object)result; return true; } } else if (typeof(float) == typeof(T)) { if (float.TryParse(input, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { output = (T)(object)result2; return true; } } else if (typeof(bool) == typeof(T) || typeof(T) == typeof(ItemConfig.Teleportable)) { string[] source = new string[12] { "0", "false", "off", "no", "nope", "nah", "-", "hell no", "pls dont", "lol no", "certainly not", "absolutely not" }; string[] source2 = new string[14] { "1", "true", "on", "yes", "yep", "yeah", "+", "hell yeah", "ok", "okay", "k", "yaaas", "certainly", "absolutely" }; if (source.Contains(input.ToLower())) { output = ((typeof(ItemConfig.Teleportable) == typeof(T)) ? ((T)(object)default(ItemConfig.Teleportable)) : ((T)(object)false)); return true; } if (source2.Contains(input.ToLower())) { output = ((typeof(ItemConfig.Teleportable) == typeof(T)) ? ((T)(object)new ItemConfig.Teleportable { amount = int.MaxValue }) : ((T)(object)true)); return true; } } output = default(T); return false; } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] protected bool ParseScalarFromObject<T>(ref T target, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(1)] Section sect, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(1)] string key) where T : struct { T? target2 = null; if (ParseScalarFromObject(ref target2, sect, key)) { target = target2.Value; return true; } return false; } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] protected bool ParseScalarFromObject<T>(ref T? target, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(1)] Section sect, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(1)] string key) where T : struct { object obj = sect.Get(key); if (obj != null) { if (obj is string input && parseScalar<T>(input, out var output)) { target = output; return true; } configErrors.Add(sect.Path + "." + key + " is not a " + typeof(T).Name + " describing a " + key + " multiplier"); } return false; } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] private bool parseStructFromDict<T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] Dictionary<object, object> input, out T output, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(1)] string path) where T : struct { output = default(T); if (!typeof(T).IsPrimitive && !typeof(T).IsEnum) { HashSet<string> hashSet = new HashSet<string>(); FieldInfo[] fields = typeof(T).GetFields(); foreach (FieldInfo fieldInfo in fields) { if (!input.TryGetValue(fieldInfo.Name, out var value)) { continue; } hashSet.Add(fieldInfo.Name); object[] array; if (fieldInfo.FieldType.IsPrimitive || fieldInfo.FieldType.IsEnum) { array = new object[2] { value, null }; if (!(bool)typeof(ConfigFile).GetMethod("parseScalar", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(fieldInfo.FieldType).Invoke(this, array)) { configErrors.Add(path + "." + fieldInfo.Name + " is not " + fieldInfo.FieldType.Name); continue; } } else { array = new object[3] { value, null, path + "." + fieldInfo.FieldType.Name }; typeof(ConfigFile).GetMethod("parseStructFromDict", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(fieldInfo.FieldType).Invoke(this, array); } fieldInfo.SetValue(output, array[1]); } foreach (object key in input.Keys) { if (!hashSet.Contains(key)) { configErrors.Add(string.Format("{0} contains invalid key '{1}'. Allowed keys are {2}.", path, key, string.Join(", ", from f in typeof(T).GetFields() select f.Name))); } } return true; } return false; } [PublicAPI] [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(2)] protected float[] ParseProbabilityMap([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(1)] string path, object value) { if (value is List<object> list) { float[] array = new float[list.Count]; for (int i = 0; i < list.Count; i++) { if (list[i] is string s && float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { array[i] = result; } else { configErrors.Add($"{path}[{i}] is not a float denoting a probability"); } } return array; } return null; } protected bool ParseWorldlevelToSingleScalar<[<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 0 })] ref Dictionary<int, T?> target, Section sect, string key) where T : struct { string name = typeof(T).Name; object obj = sect.Get(key); if (obj != null) { T output; if (obj.ToString().ToLower() == "default") { target = Enumerable.Repeat<T?>(null, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T? v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); } else if (obj is string input && parseScalar<T>(input, out output)) { target = Enumerable.Repeat((T?)output, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T? v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); } else if (obj is Dictionary<object, object> dictionary) { target = new Dictionary<int, T?>(); bool flag = true; foreach (KeyValuePair<object, object> item in dictionary) { if (int.TryParse(item.Key.ToString(), out var result)) { if (item.Value?.ToString().ToLower() == "default") { target[result] = null; } else if (item.Value is string input2 && parseScalar<T>(input2, out output)) { target[result] = output; } else if (item.Value is Dictionary<object, object> input3 && parseStructFromDict<T>(input3, out output, $"{sect.Path}.{key}.{result}")) { target[result] = output; } else { configErrors.Add($"{sect.Path}.{key}.{result} is not 'default' nor {name}"); } } else { if (!flag && !typeof(T).IsPrimitive && !typeof(T).IsEnum && parseStructFromDict<T>(dictionary, out output, sect.Path + "." + key)) { target = Enumerable.Repeat((T?)output, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T? v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); break; } configErrors.Add($"{sect.Path}.{key} contains a non-integer key {item.Key}"); } flag = false; } } else { configErrors.Add(sect.Path + "." + key + " is not 'default', " + name + " nor Map"); } } return target != null; } protected bool ParseWorldlevelToFloatMap([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] ref Dictionary<int, float[]> target, Section sect, string key) { object obj = sect.Get(key); if (obj != null) { int result; float result2; if (obj.ToString().ToLower() == "default") { target = Enumerable.Repeat<float[]>(null, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); } else if (key == "stars" && obj is string s && int.TryParse(s, out result)) { float[] element = ((!(sect.dictKey != "sector")) ? ((result < 0) ? Array.Empty<float>() : new float[1] { -result }) : ((result <= 0) ? Array.Empty<float>() : Enumerable.Repeat(0f, result - 1).Concat(new float[1] { 100f }).ToArray())); target = Enumerable.Repeat(element, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); } else if (key != "stars" && obj is string s2 && float.TryParse(s2, NumberStyles.Float, CultureInfo.InvariantCulture, out result2)) { target = Enumerable.Repeat(new float[1] { result2 }, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); } else { float[] array = ParseProbabilityMap(sect.Path + "." + key, obj); if (array != null) { target = Enumerable.Repeat(array, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); } else if (obj is Dictionary<object, object> dictionary) { target = new Dictionary<int, float[]>(); foreach (KeyValuePair<object, object> item in dictionary) { if (int.TryParse(item.Key.ToString(), out var result3)) { if (item.Value?.ToString().ToLower() == "default") { target[result3] = null; continue; } if (key == "stars" && item.Value is string s3 && int.TryParse(s3, out result)) { if (sect.dictKey != "sector") { target[result3] = ((result <= 0) ? Array.Empty<float>() : Enumerable.Repeat(0f, result - 1).Concat(new float[1] { 100f }).ToArray()); } else { target[result3] = ((result < 0) ? Array.Empty<float>() : new float[1] { -result }); } continue; } if (key != "stars" && item.Value is string s4 && float.TryParse(s4, NumberStyles.Float, CultureInfo.InvariantCulture, out var result4)) { target[result3] = new float[1] { result4 }; continue; } float[] array2 = ParseProbabilityMap($"{sect.Path}.{key}.{result3}", item.Value); if (array2 != null) { target[result3] = array2; continue; } configErrors.Add(string.Format("{0}.{1}.{2} is not 'default', {3} nor List", sect.Path, key, result3, (key == "stars") ? "integer" : "float")); } else { configErrors.Add($"{sect.Path}.{key} contains a non-integer key {item.Key}"); } } } else { configErrors.Add(sect.Path + "." + key + " is not 'default', " + ((key == "stars") ? "integer" : "float") + " nor List nor Map"); } } } return target != null; } protected bool ParseEnumConfig<[<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1, 0, 2 })] ref Dictionary<int, Dictionary<T, float[]>> target, Section sect, string key) where T : struct, IConvertible { List<T> allEnumValues = ((T[])Enum.GetValues(typeof(T))).Where([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T t) => t.ToInt32(CultureInfo.InvariantCulture) != 0).ToList(); object obj = sect.Get(key); if (obj != null) { if (obj.ToString().ToLower() == "default") { target = Enumerable.Repeat(((IEnumerable<T>)allEnumValues).ToDictionary((Func<T, T>)([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T k) => k), (Func<T, float[]>)([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T _) => null)), CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); } else if (obj is string text) { if (float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { target = Enumerable.Repeat(defaultEntryFromProbability(result), CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); } else if (typeof(T) != typeof(CreatureLevelControl.ModifyDamage)) { ParseResult<T> parseResult = ParseEnum(text); if (parseResult.error == null) { target = Enumerable.Repeat(new Dictionary<T, float[]> { { parseResult.value, new float[1] { 100f } } }, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); } else { configErrors.Add(sect.Path + "." + key + " contains invalid value " + text + ", expecting default, float, " + parseResult.error + " or dictionary"); } } } else { if (typeof(T) == typeof(CreatureLevelControl.ModifyDamage)) { float[] array = ParseProbabilityMap(sect.Path + "." + key, obj); if (array != null) { target = Enumerable.Repeat(new Dictionary<T, float[]> { { (T)(object)CreatureLevelControl.ModifyDamage.All, array } }, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.i, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] k => k.v); goto IL_0653; } } if (obj is Dictionary<object, object> dictionary) { target = new Dictionary<int, Dictionary<T, float[]>>(); if (dictionary.Count > 0) { if (int.TryParse(dictionary.Keys.First().ToString(), out var _)) { foreach (KeyValuePair<object, object> item in dictionary) { if (int.TryParse(item.Key.ToString(), out var result3)) { float result4; if (item.Value?.ToString().ToLower() == "default") { target[result3] = ((IEnumerable<T>)allEnumValues).ToDictionary((Func<T, T>)([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T k) => k), (Func<T, float[]>)([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T _) => null)); } else if (item.Value is string s && float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out result4)) { target[result3] = defaultEntryFromProbability(result4); } else if (item.Value is Dictionary<object, object> affixes2) { target[result3] = ParseAffixProbabilities($"{sect.Path}.{key}[{result3}]", affixes2); } else { configErrors.Add($"{sect.Path}.{key}[{result3}] is not a mapping from affix names to probabilities"); } } else { configErrors.Add(sect.Path + "." + key + " contains mixed world levels and affix names"); } } } else { Dictionary<T, float[]> value = ParseAffixProbabilities(sect.Path + "." + key, dictionary); for (int j = 0; j <= CreatureLevelControl.defaultWorldLevelDays.Length; j++) { target[j] = value; } } } } else { configErrors.Add(sect.Path + "." + key + " is not integer" + ((typeof(T) == typeof(CreatureLevelControl.ModifyDamage)) ? ", List" : "") + ", 'default' nor Map"); } } } goto IL_0653; IL_0653: return target != null; [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 0, 2 })] Dictionary<T, float[]> ParseAffixProbabilities([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(1)] string path, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] Dictionary<object, object> affixes) { Dictionary<T, float[]> affixProbabilities = new Dictionary<T, float[]>(); bool hasOther = false; float[] otherValue = null; foreach (KeyValuePair<object, object> affix in affixes) { bool isOther = affix.Key.ToString().ToLower() == "other"; ParseResult<T> result5 = ParseEnum(affix.Key.ToString()); if (isOther || result5.error == null) { float result6; if (affix.Value?.ToString().ToLower() == "default") { assign(null); } else if (affix.Value is string s2 && float.TryParse(s2, NumberStyles.Float, CultureInfo.InvariantCulture, out result6)) { assign(new float[1] { result6 }); } else { float[] array2 = ParseProbabilityMap($"{path}.{affix.Key}", affix.Value); if (array2 != null) { assign(array2); } else { configErrors.Add(string.Format("{0}.{1} (value '{2}') is not a float or list of floats denoting probabilities", path, affix.Key, (affix.Value is string) ? affix.Value : (affix.Value?.GetType().Name ?? "null"))); } } } else { configErrors.Add($"{path} contains unexpected affix key {affix.Key}, expecting either other, {result5.error}"); } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] void assign([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] float[] probabilityArray) { if (isOther) { hasOther = true; otherValue = probabilityArray; } else { affixProbabilities[result5.value] = probabilityArray; } } } if (hasOther) { int undefinedValueCount = allEnumValues.Count - affixProbabilities.Count; if (otherValue != null && undefinedValueCount > 0) { otherValue = otherValue.Select((float p) => p / (float)undefinedValueCount).ToArray(); } foreach (T item2 in allEnumValues) { if (!affixProbabilities.ContainsKey(item2)) { affixProbabilities[item2] = otherValue; } } } return affixProbabilities; } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] ParseResult<T> ParseEnum([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(1)] string name) { ParseResult<T> result8; if (!Enum.TryParse<T>(name, ignoreCase: true, out var result7)) { result8 = default(ParseResult<T>); result8.error = string.Join(", ", allEnumValues.Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T t) => t.ToString())); return result8; } result8 = default(ParseResult<T>); result8.value = result7; return result8; } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 0, 2 })] Dictionary<T, float[]> defaultEntryFromProbability(float probability) { if (!(typeof(T) == typeof(CreatureLevelControl.ModifyDamage))) { return allEnumValues.ToDictionary([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T k) => k, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T _) => new float[1] { probability }); } return new Dictionary<T, float[]> { { (T)(object)CreatureLevelControl.ModifyDamage.All, new float[1] { probability } } }; } } } [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(1)] public class CreatureConfig { [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] [Flags] public enum CreatureMode { Default = 0, Tamed = 1, Day = 2, Night = 4, Dungeon = 8, Override = 0x10 } [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] public struct CreatureFilter : IComparable { public CreatureMode Mode; [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1 })] public Dictionary<string, bool> GlobalKeys; private string globalKeys() { return "Globalkeys " + string.Join(", ", GlobalKeys.Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<string, bool> kv) => (kv.Value ? "" : "!") + kv.Key)); } public override string ToString() { if (Mode == CreatureMode.Default) { return globalKeys(); } if (GlobalKeys != null) { return $"{Mode}, {globalKeys()}"; } return Mode.ToString(); } public int CompareTo(object obj) { if (obj is CreatureFilter creatureFilter) { int num = 0; if ((Mode & CreatureMode.Override) == 0 == ((creatureFilter.Mode & CreatureMode.Override) == 0)) { if (GlobalKeys == null != (creatureFilter.GlobalKeys == null)) { if (GlobalKeys != null) { return -1; } return 1; } if (GlobalKeys != null && GlobalKeys.Count != creatureFilter.GlobalKeys.Count) { if (GlobalKeys.Count <= creatureFilter.GlobalKeys.Count) { return 1; } return -1; } } CreatureMode[] modePriorities = CreatureConfig.modePriorities; foreach (CreatureMode creatureMode in modePriorities) { if ((Mode & creatureMode) == 0 != ((creatureFilter.Mode & creatureMode) == 0)) { if ((Mode & creatureMode) != 0) { return -1; } return 1; } if (num == 0 && (Mode & creatureMode) != (creatureFilter.Mode & creatureMode)) { num = ((Mode >= creatureFilter.Mode) ? 1 : (-1)); } } if (num == 0 && GlobalKeys != null && creatureFilter.GlobalKeys != null) { List<KeyValuePair<string, bool>> list = GlobalKeys.OrderBy([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<string, bool> kv) => kv.Key).ToList(); List<KeyValuePair<string, bool>> list2 = creatureFilter.GlobalKeys.OrderBy([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<string, bool> kv) => kv.Key).ToList(); for (int j = 0; j < list.Count; j++) { int num2 = string.Compare(list[j].Key, list2[j].Key, StringComparison.Ordinal); if (num2 != 0) { return num2; } if (list[j].Value != list2[j].Value) { if (!list[j].Value) { return 1; } return -1; } } } return num; } return 1; } } [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] public class ConfigFile : global::CreatureLevelControl.ConfigFile { [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] private delegate void Assigner<[<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] T>(ref T current, T input); private readonly Dictionary<string, CreatureConfig> configs = new Dictionary<string, CreatureConfig>(); private static List<string> prefabLocalizations(Character prefab) { return new List<string> { ((Object)prefab).name.ToLower(), prefab.m_name.ToLower(), Localization.instance.Localize(prefab.m_name).ToLower(), CreatureLevelControl.englishLocalization.Localize(prefab.m_name).ToLower() }; } private static List<string> biomeLocalizations(Biome biome) { return new string[3] { ((object)(Biome)(ref biome)).ToString().ToLower(), Localization.instance.Localize("$biome_" + ((object)(Biome)(ref biome)).ToString().ToLower()).ToLower(), CreatureLevelControl.englishLocalization.Localize("$biome_" + ((object)(Biome)(ref biome)).ToString().ToLower()).ToLower() }.Distinct().ToList(); } public Dictionary<string, CreatureConfig> Process() { //IL_00cf: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, CreatureConfig> dictionary = new Dictionary<string, CreatureConfig>(); Biome[] array = new Biome[9]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Biome[] biomeOrder = (Biome[])(object)array; biomeOrder = biomeOrder.Concat(knownBiomes.Where((Biome b) => !biomeOrder.Contains(b))).ToArray(); Dictionary<Biome, List<GameObject>> dictionary2 = new Dictionary<Biome, List<GameObject>>(); foreach (IGrouping<string, SpawnData> item in ZNetScene.instance.GetPrefab("_ZoneCtrl").GetComponent<SpawnSystem>().m_spawnLists.SelectMany([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (SpawnSystemList s) => from p in s.m_spawners where p.m_requiredGlobalKey == "" && Object.op_Implicit((Object)(object)p.m_prefab.gameObject.GetComponent<Character>()) group p by ((Object)p.m_prefab).name)) { Biome val = item.Aggregate((Biome)0, [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (Biome a, SpawnData p) => (Biome)(a | p.m_biome)); Biome[] array2 = biomeOrder; foreach (Biome val2 in array2) { if (((Enum)val).HasFlag((Enum)(object)val2)) { if (!dictionary2.TryGetValue(val2, out var value)) { List<GameObject> list2 = (dictionary2[val2] = new List<GameObject>()); value = list2; } value.Add(item.First().m_prefab); break; } } } foreach (KeyValuePair<Biome, List<GameObject>> item2 in dictionary2) { List<string> value2 = item2.Value.SelectMany([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (GameObject prefab) => prefabLocalizations(prefab.GetComponent<Character>())).ToList(); foreach (string item3 in from biomeName in biomeLocalizations(item2.Key) where !groups.ContainsKey(biomeName) select biomeName) { groups[item3] = value2; } } foreach (Character item4 in from p in ZNetScene.instance.m_prefabs select p.GetComponent<Character>() into c where Object.op_Implicit((Object)(object)c) && !c.IsPlayer() select c) { List<string> list3 = prefabLocalizations(item4); string[] array3 = list3.ToArray(); foreach (string name in array3) { resolveGroupsForName(list3, name); } list3.Add(item4.IsBoss() ? "boss" : "creature"); list3.Add("all"); foreach (string item5 in list3) { if (configs.TryGetValue(item5, out var value3)) { if (!dictionary.TryGetValue(item4.m_name, out var value4)) { CreatureConfig creatureConfig2 = (dictionary[item4.m_name] = new CreatureConfig()); value4 = creatureConfig2; } AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.worldLevelToStars, value3.worldLevelToStars); AssignCreatureModeConfigStruct<float>(value4.sizeScalingFactor, value3.sizeScalingFactor); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.baseHealth, value3.baseHealth); AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.healthGainPerStar, value3.healthGainPerStar); AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>(base.AssignConfig, value4.baseDamage, value3.baseDamage); AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.damageGainPerStar, value3.damageGainPerStar); AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.attackSpeedGainPerStar, value3.attackSpeedGainPerStar); AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.movementSpeedGainPerStar, value3.movementSpeedGainPerStar); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.baseMovementSpeed, value3.baseMovementSpeed); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.baseAttackSpeed, value3.baseAttackSpeed); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.spawnAmount, value3.spawnAmount); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.sectorCount, value3.sectorCount); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.sectorStars, value3.sectorStars); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.worldLevelToLootAmount, value3.worldLevelToLootAmount); AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.worldLevelToLootPerStar, value3.worldLevelToLootPerStar); AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>(base.AssignEnumConfig, value4.worldLevelToCreatureEffect, value3.worldLevelToCreatureEffect); AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>(base.AssignEnumConfig, value4.worldLevelToCreatureEffectFactor, value3.worldLevelToCreatureEffectFactor); AssignEnumConfig(ref value4.worldLevelToBoss, value3.worldLevelToBoss); AssignEnumConfig(ref value4.worldLevelToBossAffixFactor, value3.worldLevelToBossAffixFactor); AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureInfusion, float[]>>>(base.AssignEnumConfig, value4.worldLevelToInfusion, value3.worldLevelToInfusion); AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>(base.AssignEnumConfig, value4.worldLevelToDamageTakenModifier, value3.worldLevelToDamageTakenModifier); } } if (dictionary.TryGetValue(item4.m_name, out var value5)) { fillModeWorldLevels<float[]>(value5.worldLevelToStars); fillModeWorldLevels<Dictionary<CreatureExtraEffect, float[]>>(value5.worldLevelToCreatureEffect); fillModeWorldLevels<Dictionary<CreatureExtraEffect, float[]>>(value5.worldLevelToCreatureEffectFactor); fillWorldLevels(value5.worldLevelToBoss); fillWorldLevels(value5.worldLevelToBossAffixFactor); fillModeWorldLevels<Dictionary<CreatureInfusion, float[]>>(value5.worldLevelToInfusion); fillModeWorldLevels<Dictionary<CreatureLevelControl.ModifyDamage, float[]>>(value5.worldLevelToDamageTakenModifier); fillModeWorldLevels<float[]>(value5.baseHealth); fillModeWorldLevels<float?>(value5.healthGainPerStar); fillModeWorldLevels<Dictionary<CreatureLevelControl.ModifyDamage, float[]>>(value5.baseDamage); fillModeWorldLevels<float?>(value5.damageGainPerStar); fillModeWorldLevels<float[]>(value5.baseMovementSpeed); fillModeWorldLevels<float?>(value5.movementSpeedGainPerStar); fillModeWorldLevels<float[]>(value5.baseAttackSpeed); fillModeWorldLevels<float?>(value5.attackSpeedGainPerStar); fillModeWorldLevels<float[]>(value5.spawnAmount); fillModeWorldLevels<float[]>(value5.sectorCount); fillModeWorldLevels<float[]>(value5.sectorStars); fillModeWorldLevels<float[]>(value5.worldLevelToLootAmount); fillModeWorldLevels<float?>(value5.worldLevelToLootPerStar); } } return dictionary; static void AssignCreatureModeConfig<T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 0 })] Assigner<T> assigner, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> newConfig, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> inConfig) where T : class { foreach (CreatureFilter item6 in newConfig.Keys.Concat(inConfig.Keys).ToList()) { T value9; if (!newConfig.TryGetValue(item6, out var value7)) { if (inConfig.TryGetValue(item6, out var value8)) { newConfig[item6] = value8; } } else if (inConfig.TryGetValue(item6, out value9)) { assigner(ref value7, value9); newConfig[item6] = value7; } } } static void AssignCreatureModeConfigStruct<T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> newConfig, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> inConfig) where T : struct { foreach (CreatureFilter item7 in newConfig.Keys.Concat(inConfig.Keys).ToList()) { if (!newConfig.ContainsKey(item7) && inConfig.TryGetValue(item7, out var value6)) { newConfig[item7] = value6; } } } void fillModeWorldLevels<T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 0 })] SortedDictionary<CreatureFilter, Dictionary<int, T>> config) { config.Values.ToList().ForEach(base.fillWorldLevels); } } private SortedDictionary<CreatureFilter, Section> getSections(Section parentSection) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) SortedDictionary<CreatureFilter, Section> sections = new SortedDictionary<CreatureFilter, Section> { { default(CreatureFilter), parentSection } }; foreach (CreatureMode item in ((CreatureMode[])Enum.GetValues(typeof(CreatureMode))).Where((CreatureMode v) => v != CreatureMode.Default)) { creatureModeSection(item, new string[1] { item.ToString().ToLower() }); } Biome[] knownBiomes = CreatureConfig.knownBiomes; foreach (Biome biome in knownBiomes) { creatureModeSection(biomeToCreatureMode(biome), biomeLocalizations(biome)); } readGlobalkeys("key_", present: true); readGlobalkeys("nokey_", present: false); return sections; void creatureModeSection(CreatureMode mode, IEnumerable<string> localizations) { Section section3 = localizations.Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (string localizedKey) => section(parentSection, localizedKey)).FirstOrDefault([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (Section section) => section != null); if (section3 != null) { foreach (KeyValuePair<CreatureFilter, Section> section4 in getSections(section3)) { CreatureFilter key2 = section4.Key; key2.Mode |= mode; sections[key2] = section4.Value; } } } void readGlobalkeys(string prefix, bool present) { foreach (string item2 in parentSection.KeysWithPrefix(prefix)) { Section section2 = section(parentSection, item2); if (section2 != null) { foreach (KeyValuePair<CreatureFilter, Section> section5 in getSections(section2)) { CreatureFilter key = section5.Key; key.GlobalKeys = ((key.GlobalKeys != null) ? new Dictionary<string, bool>(key.GlobalKeys) : new Dictionary<string, bool>()); key.GlobalKeys[item2.Substring(prefix.Length)] = present; sections[key] = section5.Value; } } } } } protected override void ParsePrimarySection(Section creatureSection) { string key = creatureSection.dictKey.ToLower(); if (!configs.TryGetValue(key, out var value)) { value = (configs[key] = new CreatureConfig()); } SortedDictionary<CreatureFilter, Section> sections = getSections(creatureSection); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.worldLevelToStars, sections, "stars"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.worldLevelToLootAmount, sections, "loot"); AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.worldLevelToLootPerStar, sections, "loot per star"); AssignCreatureMode(base.ParseScalarFromObject, value.sizeScalingFactor, sections, "size"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.baseHealth, sections, "health"); AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.healthGainPerStar, sections, "health per star"); AssignCreatureMode(base.ParseEnumConfig, value.baseDamage, sections, "damage"); AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.damageGainPerStar, sections, "damage per star"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.baseAttackSpeed, sections, "attack speed"); AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.attackSpeedGainPerStar, sections, "attack speed per star"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.baseMovementSpeed, sections, "movement speed"); AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.movementSpeedGainPerStar, sections, "movement speed per star"); AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToDamageTakenModifier, sections, "damage taken"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.spawnAmount, sections, "amount"); AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToCreatureEffect, sections, "effect"); AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToCreatureEffectFactor, sections, "effect power"); ParseEnumConfig(ref value.worldLevelToBoss, creatureSection, "affix"); ParseEnumConfig(ref value.worldLevelToBossAffixFactor, creatureSection, "affix power"); AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToInfusion, sections, "infusion"); using Section section = base.section(creatureSection, "sector"); if (section != null) { SortedDictionary<CreatureFilter, Section> sections2 = getSections(section); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.sectorCount, sections2, "count"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.sectorStars, sections2, "stars"); } sections.Remove(default(CreatureFilter)); foreach (Section value2 in sections.Values) { value2.Dispose(); } } private static void AssignCreatureMode<[<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] T>(ParserDelegate<T> parser, SortedDictionary<CreatureFilter, T> target, SortedDictionary<CreatureFilter, Section> sections, string key) { foreach (KeyValuePair<CreatureFilter, Section> section in sections) { target.TryGetValue(default(CreatureFilter), out var value); if (parser(ref value, section.Value, key)) { target[section.Key] = value; } } } protected override void Verify() { foreach (KeyValuePair<string, CreatureConfig> config in configs) { KeyValuePair<string, CreatureConfig> configKv = config; foreach (KeyValuePair<CreatureFilter, Dictionary<int, float[]>> worldLevelToStar in configKv.Value.worldLevelToStars) { float[] array = null; foreach (KeyValuePair<int, float[]> item in worldLevelToStar.Value) { float[] value = item.Value; if (value != null && value.Sum() > 100.0001f && (array == null || !array.SequenceEqual(item.Value))) { array = item.Value; configWarnings.Add(string.Format("{0}{1} has a sum of probabilities greater than 100% for its 'stars' setting at world level {2}. Note that the sum of probabilites for individual star levels MUST be equal or lower than 100%, otherwise probabilities exceeding 100% will be ignored.\nWith the current configuration this group would have the following base probabilities: {3}.", configKv.Key, worldLevelToStar.Key.Equals(default(CreatureFilter)) ? "" : $" in {worldLevelToStar.Key} mode", item.Key, string.Join(", ", API.zeroProbabilities(item.Value).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (float p, int i) => $"{i} stars: {p}%")))); } } } checkEffectProbabilities<CreatureExtraEffect>(configKv.Value.worldLevelToCreatureEffect, CreatureLevelControl.customCreatureAffixChances, "creature special effect"); checkEffectProbabilities<CreatureInfusion>(configKv.Value.worldLevelToInfusion, CreatureLevelControl.customCreatureInfusionChances, "creature infusion"); SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<BossAffix, float[]>>> sortedDictionary = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<BossAffix, float[]>>>(); if (configKv.Value.worldLevelToBoss != null) { sortedDictionary[default(CreatureFilter)] = configKv.Value.worldLevelToBoss; } checkEffectProbabilities<BossAffix>(sortedDictionary, CreatureLevelControl.customBossAffixChances, "boss affix"); void checkEffectProbabilities<T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 1, 0, 2 })] SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<T, float[]>>> dict, [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 0, 1 })] Dictionary<T, ConfigEntry<float>> defaultsDict, string nameString) where T : struct, IConvertible { foreach (KeyValuePair<CreatureFilter, Dictionary<int, Dictionary<T, float[]>>> item2 in dict) { Dictionary<T, float> dictionary = null; foreach (KeyValuePair<int, Dictionary<T, float[]>> item3 in item2.Value) { int num = item3.Value.Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<T, float[]> v) => (v.Value ?? new float[1]).Length).DefaultIfEmpty(1).Max(); for (int j = 0; j < num; j++) { bool flag = false; Dictionary<T, float> dictionary2 = new Dictionary<T, float>(); Dictionary<T, float> dictionary3 = new Dictionary<T, float>(); foreach (T item4 in ((T[])Enum.GetValues(typeof(T))).Where([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (T e) => e.ToInt32(CultureInfo.InvariantCulture) != 0)) { float num3; if (item3.Value.TryGetValue(item4, out var value2) && value2 != null && value2.Length != 0) { num3 = (dictionary3[item4] = value2[(j < value2.Length) ? j : (value2.Length - 1)]); } else { num3 = defaultsDict[item4].Value; if (num3 > 0f) { flag = true; } } dictionary2[item4] = num3; } if (dictionary2.Values.Sum() > 101.1f && Mathf.Abs(dictionary3.Values.Sum() - 100f) > 1.1f && (dictionary == null || !dictionary.SequenceEqual(dictionary2))) { bool flag2 = dictionary3.Values.Sum() < 100f; dictionary = dictionary2; configWarnings.Add(string.Format("{0}{1} has a sum of {2} chances greater than 100% for {3} stars at world level {4}{5}. Some effects may not happen at all with the current configuration. Specified chances are: {6}.", configKv.Key, item2.Key.Equals(default(CreatureFilter)) ? "" : $" in configuration {item2.Key}", nameString, j, item3.Key, (flag && flag2) ? " (including default probabilities from config)" : "", string.Join(", ", (flag2 ? dictionary2 : dictionary3).Select([<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] (KeyValuePair<T, float> kv) => $"{kv.Key}: {kv.Value}%")))); } } } } } } } } [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] public class Loader : global::CreatureLevelControl.ConfigFile.Loader { [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(2)] public global::CreatureLevelControl.ConfigFile ConfigFile { [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(2)] get { return CreatureLevelControl.creatureConfigFile; } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(2)] set { CreatureLevelControl.creatureConfigFile = (ConfigFile)value; } } public string FilePattern => "CreatureConfig*.yml"; public string EditButtonName => LocalizationWrapper.getTranslation("Edit Creature YAML config"); public CustomSyncedValue<List<string>> FileData => CreatureLevelControl.creatureConfigFileData; public bool Enabled => CreatureLevelControl.creatureConfigFileActive.GetToggle(); public global::CreatureLevelControl.ConfigFile InstantiateConfig() { return new ConfigFile(); } public void ProcessConfig() { CreatureLevelControl.PrefabConfig = CreatureLevelControl.creatureConfigFile.Process(); } } private const int BiomeOffset = 5; [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> worldLevelToStars = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>> worldLevelToCreatureEffect = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>> worldLevelToCreatureEffectFactor = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureInfusion, float[]>>> worldLevelToInfusion = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureInfusion, float[]>>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1, 2 })] public Dictionary<int, Dictionary<BossAffix, float[]>> worldLevelToBoss; [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 2, 1, 2 })] public Dictionary<int, Dictionary<BossAffix, float[]>> worldLevelToBossAffixFactor; public readonly SortedDictionary<CreatureFilter, float> sizeScalingFactor = new SortedDictionary<CreatureFilter, float>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> baseHealth = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> healthGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>> baseDamage = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>(); public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> damageGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> baseMovementSpeed = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> movementSpeedGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> baseAttackSpeed = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> attackSpeedGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> spawnAmount = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> sectorCount = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> sectorStars = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>> worldLevelToDamageTakenModifier = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>(); [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> worldLevelToLootAmount = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> worldLevelToLootPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>(); private static Biome[] knownBiomes => ((Biome[])Enum.GetValues(typeof(Biome))).Where((Biome b) => (int)b > 0).ToArray(); private static CreatureMode[] modePriorities { get { CreatureMode[] obj = new CreatureMode[5] { CreatureMode.Override, CreatureMode.Tamed, CreatureMode.Dungeon, CreatureMode.Default, CreatureMode.Day | CreatureMode.Night }; obj[3] = knownBiomes.Aggregate(CreatureMode.Default, (CreatureMode a, Biome m) => a | biomeToCreatureMode(m)); return obj; } } public static CreatureMode biomeToCreatureMode(Biome biome) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Expected I4, but got Unknown return (CreatureMode)(biome << 5); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("org.bepinex.plugins.creaturelevelcontrol", "Creature Level & Loot Control", "4.6.1")] [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(1)] [BepInIncompatibility("org.bepinex.plugins.valheim_plus")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class CreatureLevelControl : BaseUnityPlugin { [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] public enum Difficulty { [LocalizationWrapper.Localized(Difficulty.Custom)] Custom, [LocalizationWrapper.Localized(Difficulty.Very_easy)] Very_easy, [LocalizationWrapper.Localized(Difficulty.Easy)] Easy, [LocalizationWrapper.Localized(Difficulty.Medium)] Medium, [LocalizationWrapper.Localized(Difficulty.Hard)] Hard, [LocalizationWrapper.Localized(Difficulty.Very_hard)] Very_hard, [LocalizationWrapper.Localized(Difficulty.Insane)] Insane } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] public enum CreatureSectorAnnouncementScope { [LocalizationWrapper.Localized(CreatureSectorAnnouncementScope.Local)] Local, [LocalizationWrapper.Localized(CreatureSectorAnnouncementScope.Global)] Global, [LocalizationWrapper.Localized(CreatureSectorAnnouncementScope.Off)] Off } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] public enum LootSystem { [LocalizationWrapper.Localized(LootSystem.Vanilla)] Vanilla, [LocalizationWrapper.Localized(LootSystem.Linear)] Linear, [LocalizationWrapper.Localized(LootSystem.CalculateChance)] CalculateChance, [LocalizationWrapper.Localized(LootSystem.CalculateAmount)] CalculateAmount } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] private enum VisualLevelIndicator { [LocalizationWrapper.Localized(VisualLevelIndicator.Off)] Off, [LocalizationWrapper.Localized(VisualLevelIndicator.On)] On, [LocalizationWrapper.Localized(VisualLevelIndicator.BossesOff)] BossesOff, [LocalizationWrapper.Localized(VisualLevelIndicator.CreaturesOff)] CreaturesOff } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] private enum AllowedConsoleCommands { [LocalizationWrapper.Localized(AllowedConsoleCommands.CreatureCommands)] CreatureCommands, [LocalizationWrapper.Localized(AllowedConsoleCommands.InformationCommands)] InformationCommands, [LocalizationWrapper.Localized(AllowedConsoleCommands.None)] None } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] private enum VisualExtraEffectIndicator { [LocalizationWrapper.Localized(VisualExtraEffectIndicator.Color)] Color, [LocalizationWrapper.Localized(VisualExtraEffectIndicator.Text)] Text, [LocalizationWrapper.Localized(VisualExtraEffectIndicator.Both)] Both } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] public enum DifficultySecondFactor { [LocalizationWrapper.Localized(DifficultySecondFactor.None)] None, [LocalizationWrapper.Localized(DifficultySecondFactor.Age_of_world)] Age_of_world, [LocalizationWrapper.Localized(DifficultySecondFactor.Distance)] Distance, [LocalizationWrapper.Localized(DifficultySecondFactor.BossesKilled)] BossesKilled } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] public enum SpawnLevel { [LocalizationWrapper.Localized(SpawnLevel.None)] None, [LocalizationWrapper.Localized(SpawnLevel.One)] One, [LocalizationWrapper.Localized(SpawnLevel.Two)] Two, [LocalizationWrapper.Localized(SpawnLevel.Three)] Three, [LocalizationWrapper.Localized(SpawnLevel.Four)] Four, [LocalizationWrapper.Localized(SpawnLevel.Five)] Five } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] public enum CreatureSectorWorldLevel { [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Disabled)] Disabled = -1, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.None)] None, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.One)] One, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Two)] Two, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Three)] Three, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Four)] Four, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Five)] Five, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Six)] Six, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Seven)] Seven } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] public enum ModifyDamage { All, Fire, Frost, Poison, Lightning, Spirit, Elemental, Blunt, Slash, Pierce, Chop, Physical, Knives, Bows, Crossbows, ElementalMagic, BloodMagic, Swords, Spears, Pickaxes, Axes, Clubs, Polearms, Weapons, Unarmed } [HarmonyPatch(typeof(Game), "GetPlayerDifficulty")] [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] private class PatchPlayerCount { [UsedImplicitly] private static void Postfix(ref int __result) { __result = Mathf.Min(maximumMultiplayerPlayerCount.Value, Mathf.Max(minimumMultiplayerPlayerCount.Value, additionalMultiplayerPlayerCount.Value + __result)); } } [HarmonyPatch(typeof(Terminal), "TryRunCommand")] [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] private class PatchTerminal { [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(1)] [UsedImplicitly] private static bool Prefix(Terminal __instance, string text) { //IL_04a1: Unknown result type (might be due to invalid IL or missing references) //IL_04a8: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) if (!text.ToLower().StartsWith("cllc")) { return true; } bool flag = true; string[] array = text.ToLower().Split(new char[1] { ' ' }); bool flag2 = !configSync.IsLocked; bool flag3 = false; if (array.Length > 1 && array[1] == "killhighstars") { flag = false; if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands) { if (array.Length <= 2 || !int.TryParse(array[2], out var result)) { result = 6; } Character[] array2 = Object.FindObjectsOfType<Character>(); foreach (Character val in array2) { if (val.IsPlayer() || val.GetLevel() - 1 < result) { continue; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if (component != null) { ZDO zDO = component.GetZDO(); if (zDO != null) { zDO.SetOwner(ZDOMan.instance.m_sessionID); } } Object.Destroy((Object)(object)((Component)val).GetComponent<CharacterDrop>()); ZNetScene.instance.Destroy(((Component)val).gameObject); } __instance.AddString("Removed all nearby creatures with at least " + result + " stars"); } else { flag3 = true; } } else if (array.Length > 1 && array[1] == "killall") { flag = false; if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands) { Character[] array2 = Object.FindObjectsOfType<Character>(); foreach (Character val2 in array2) { if (val2.IsPlayer()) { continue; } ZNetView component2 = ((Component)val2).GetComponent<ZNetView>(); if (component2 != null) { ZDO zDO2 = component2.GetZDO(); if (zDO2 != null) { zDO2.SetOwner(ZDOMan.instance.m_sessionID); } } Object.Destroy((Object)(object)((Component)val2).GetComponent<CharacterDrop>()); ZNetScene.instance.Destroy(((Component)val2).gameObject); } __instance.AddString("Removed all nearby creatures"); } else { flag3 = true; } } else if (array.Length > 1 && array[1] == "worldlevel") { flag = false; if (flag2 || allowedConsoleCommands.Value != AllowedConsoleCommands.None) { __instance.AddString("Current world level: " + API.GetWorldLevel()); } else { flag3 = true; } } else if (array.Length > 1 && array[1] == "sectorkills") { flag = false; if (flag2 || allowedConsoleCommands.Value != AllowedConsoleCommands.None) { __instance.AddString("Kills in the current sector: " + (CreatureSector.currentSector(((Component)Player.m_localPlayer).GetComponent<ZNetView>())?.sectorKills ?? 0f)); } else { flag3 = true; } } else if (array.Length > 1 && array[1] == "resetsector") { flag = false; if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands) { CreatureSector.resetSectorKills(((Component)Player.m_localPlayer).GetComponent<ZNetView>()); __instance.AddString("Reset all nearby creature sectors"); } else { flag3 = true; } } else if (array.Length > 1 && array[1] == "starchance") { flag = false; if (flag2 || allowedConsoleCommands.Value != AllowedConsoleCommands.None) { object obj; if (array.Length <= 2) { obj = null; } else { GameObject prefab = ZNetScene.instance.GetPrefab(text.Split(new char[1] { ' ' })[2]); obj = ((prefab != null) ? prefab.GetComponent<Character>() : null); } Character val3 = (Character)obj; int num = 0; __instance.AddString("Current star chances" + ((val3 == null) ? "" : (" for " + Localization.instance.Localize(val3.m_name))) + ":"); float[] array3 = API.LevelProbabilities(val3, API.GetWorldLevel(), includeZoneBonusLevel: true); foreach (float num2 in array3) { __instance.AddString(num++ + " star: " + num2.ToString(CultureInfo.InvariantCulture) + "%"); } } else { flag3 = true; } } else if (array.Length > 2 && array[1] == "spawn") { flag = false; if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands) { string text2 = text.Split(new char[1] { ' ' })[2]; GameObject prefab2 = ZNetScene.instance.GetPrefab(text2); if ((Object)(object)prefab2 == (Object)null || !Object.op_Implicit((Object)(object)prefab2.GetComponent<Character>())) { __instance.AddString(text2 + " is not a creature"); return false; } ((Character)Player.m_localPlayer).Message((MessageType)1, "Spawning object " + ((Object)prefab2).name, 0, (Sprite)null); Transform transform = ((Component)Player.m_localPlayer).transform; Character character = Object.Instantiate<GameObject>(prefab2, transform.position + transform.forward * 2f + Vector3.up, Quaternion.identity).GetComponent<Character>(); foreach (string item in array.Skip(3)) { string effectName = item; if (int.TryParse(effectName, out var result2)) { character.SetLevel(result2); continue; } bool matched = false; if (character.IsBoss()) { loop<BossAffix>(delegate(BossAffix affix) { API.SetAffixBoss(character, affix); }); } else { loop<CreatureInfusion>(delegate(CreatureInfusion infusion) { API.SetInfusionCreature(character, infusion); }); loop<CreatureExtraEffect>(delegate(CreatureExtraEffect effect) { API.SetExtraEffectCreature(character, effect); }); } if (!matched) { __instance.AddString("Unknown effect " + effectName); } void loop<T>([<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 0 })] Action<T> apply) { T[] array4 = (T[])Enum.GetValues(typeof(T)); for (int j = 0; j < array4.Length; j++) { T obj2 = array4[j]; if (string.Equals(obj2.ToString(), effectName, StringComparison.CurrentCultureIgnoreCase)) { apply(obj2); matched = true; } } } } } else { flag3 = true; } } if (flag) { __instance.AddString("CLLC console commands - use 'cllc' followed by one of the following options"); __instance.AddString("killhighstars [stars] - removes all nearby creatures with at least stars. Default stars is 6."); __instance.AddString("killall - removes all nearby creatures"); __instance.AddString("worldlevel - displays the current world level"); __instance.AddString("sectorkills - displays the creatures killed in the current sector"); __instance.AddString("resetsector - resets all nearby creature sectors"); __instance.AddString("starchance [creature] - displays the current star chances. Optionally for a specific creature."); __instance.AddString("spawn [creature] [level] [affix] [extraeffect] [infusion] - spawns a creature with the provided properties."); } if (flag3) { __instance.AddString("You are not allowed to use this command on this server."); } return false; } } [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] [HarmonyPatch(typeof(Game), "GetDifficultyDamageScalePlayer")] private class PatchDamageFactor { [UsedImplicitly] private static void Postfix(ref float __result) { __result = (float)((double)(__result - 1f) / 0.04 * (double)multiplayerDMGfactor.Value / 100.0) + 1f; } } [HarmonyPatch(typeof(Game), "GetDifficultyDamageScaleEnemy")] [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] private class PatchHealthFactor { [UsedImplicitly] private static void Postfix(ref float __result) { __result = 1f / ((float)((double)(1f / __result - 1f) / 0.4 * (double)multiplayerHPfactor.Value / 100.0) + 1f); } } [HarmonyPatch(typeof(Attack), "GetLevelDamageFactor")] [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(0)] private class PatchDamageStarFactor { [<11b8c2c6-0cdc-4550-a04f-4f3e72b87539>NullableContext(1)] [UsedImplicitly] private static void Postfix(Attack __instance, ref float __result) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!((Character)(Humanoid)AccessTools.DeclaredField(typeof(Attack), "m_character").GetValue(__instance)).IsPlayer()) { __result = 1f; } } } [HarmonyPatch(typeof(Character), "SetupMaxHealth")] [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] private class PatchHealthStarFactor { private static readonly MethodInfo HealthFactorApplier = AccessTools.DeclaredMethod(typeof(PatchHealthStarFactor), "applyHealthFactor", (Type[])null, (Type[])null); private static float applyHealthFactor(float level, Character character) { int usedStars; float num = Utils.ReadWithWorldLevelAndStarsFromConfig(character, [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] (CreatureConfig c) => c.baseHealth, out usedStars) ?? (creatureBaseHealth.Value / 100f); float num2 = Utils.ReadWithWorldLevelFromConfig(character, (CreatureConfig c) => c.healthGainPerStar) ?? ((character.IsBoss() ? bossHealthGainPerStar : creatureHealthGainPerStar).Value / 100f); return num + (level - 1f - (float)usedStars) * num2; } [UsedImplicitly] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { foreach (CodeInstruction instruction in instructions) { yield return instruction; if (instruction.opcode == OpCodes.Conv_R4) { yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)HealthFactorApplier); } } } } [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] [<7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(0)] private class PatchDropChances { private static readonly MethodInfo AmountCalculator = AccessTools.DeclaredMethod(typeof(PatchDropChances), "CalculateAmount", (Type[])null, (Type[])null); private static readonly MethodInfo CheckDropMultiplier = AccessTools.DeclaredMethod(typeof(PatchDropChances), "DropMultiplierCheck", (Type[])null, (Type[])null); private static readonly MethodInfo CheckChanceMultiply = AccessTools.DeclaredMethod(typeof(PatchDropChances), "ShallMultiplyAmountWithDropchance", (Type[])null, (Type[])null); private static readonly MethodInfo ChangeRandomChance = AccessTools.DeclaredMethod(typeof(PatchDropChances), "ManipulateRandomChance", (Type[])null, (Type[])null); private static int CalculateAmount(CharacterDrop instance, int calculatedAmount, Drop drop) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 Character val = (Character)AccessTools.DeclaredField(typeof(CharacterDrop), "m_character").GetValue(instance); if (lootSystem.Value != 0 && Object.op_Implicit((Object)(object)val)) { ItemDrop component = drop.m_prefab.GetComponent<ItemDrop>(); if (component == null || (int)component.m_itemData.m_shared.m_itemType != 13) { float? num = Utils.ReadWithWorldLevelAndStarsFromConfig(val, [return: <7ac6eab4-7b94-4bf7-9ee0-ac655546aa83>Nullable(new byte[] { 1, 1, 2 })] (CreatureConfig c) => c.worldLevelToLootAmount); float num2; if (num.HasValue) { num2 = num.GetValueOrDefault(); } else { float value; float defaultValue; if (val.IsBoss()) { defaultValue = (float)additionalLootChancePerLevelBoss.Value / 100f; value = bossLootMultiplier.Value; } else { defaultValue = (float)additionalLootChancePerLevelCreature.Value / 100f; value = creatureLootMultiplier.Value; } defaultValue = Utils.ReadWithWorldLevelFromConfig(val, (CreatureConfig c) => c.worldLevelToLootPerStar).GetValueOrDefault(defaultValue); num2 = (1f + defaultValue * (float)(val.GetLevel() - 1)) * value; } return (int)(num2 + Random.Range(0f, 1f)); } } return calculatedAmount; } private static bool DropMultiplierCheck(Drop drop, CharacterDrop instance) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_006e: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)drop.m_prefab.GetComponent<Character>())) { return false; } Character val = (Character)AccessTools.DeclaredField(typeof(Character
Plugins/FarmGrid.dll
Decompiled 2 years agousing System; 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.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using FarmGrid.Patches; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7", FrameworkDisplayName = ".NET Framework 4.7")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 FarmGrid { [BepInPlugin("BepIn.Sarcen.FarmGrid", "FarmGrid", "0.5.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class FarmGrid : BaseUnityPlugin { internal const string Author = "Sarcen"; internal const string Name = "FarmGrid"; internal const string Version = "0.5.0"; internal const string BepInGUID = "BepIn.Sarcen.FarmGrid"; internal const string HarmonyGUID = "Harmony.Sarcen.FarmGrid"; internal static Harmony harmony; private ConfigEntry<float> plantSpacing; private ConfigEntry<int> farmGridSections; private ConfigEntry<float> farmGridYOffset; private ConfigEntry<Color> farmGridColor; private ConfigEntry<string> plantObjectMasks; private ConfigEntry<string> customPlants; private ConfigEntry<int> farmGridFixedRotation; private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) harmony = new Harmony("Harmony.Sarcen.FarmGrid"); harmony.PatchAll(); farmGridFixedRotation = ((BaseUnityPlugin)this).Config.Bind<int>("FarmGrid", "farmGridFixedRotation", FarmGrid_Patch.farmGridFixedRotation, "Fixed rotation in degrees, 0 is no fixed rotation (if you want 0 to be the fixed rotation enter 360)"); plantSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("FarmGrid", "plantSpacing", FarmGrid_Patch.plantSpacing, "Amount of space between plants. This is extra spacing on top of the growthsize needed to grow."); farmGridSections = ((BaseUnityPlugin)this).Config.Bind<int>("FarmGrid", "farmGridSections", FarmGrid_Patch.farmGridSections, "Amount of grid sections (on either side of the main axis.)"); farmGridYOffset = ((BaseUnityPlugin)this).Config.Bind<float>("FarmGrid", "farmGridYOffset", FarmGrid_Patch.farmGridYOffset, "Grid offset from the ground."); farmGridColor = ((BaseUnityPlugin)this).Config.Bind<Color>("FarmGrid", "farmGridColor", FarmGrid_Patch.farmGridColor, "Color of the grid."); plantObjectMasks = ((BaseUnityPlugin)this).Config.Bind<string>("FarmGrid", "plantObjectMasks", GeneralExtensions.Join<string>((IEnumerable<string>)FarmGrid_Patch.plantObjectMasks, (Func<string, string>)null, ", "), "Masks used by overlapping detection, if you add custom plants that are not in the normal category you may want to add more flags here.\nif you don't know what you are doing, don't touch this.\n\nUse this for Planting Plus:plantObjectMasks = piece,piece_nonsolid,item"); customPlants = ((BaseUnityPlugin)this).Config.Bind<string>("FarmGrid", "customPlants", "", "Plants that are not actually plants (objects without a plant component), their name and size.\n\nUse this for Planting Plus:\ncustomPlants = RaspberryBush(Clone): 0.5, RaspberryBush: 0.5, BlueberryBush(Clone): 0.5, BlueberryBush: 0.5, Pickable_Mushroom_yellow(Clone): 0.5, Pickable_Mushroom_yellow: 0.5, Pickable_Mushroom_blue(Clone): 0.5, Pickable_Mushroom_blue: 0.5, CloudberryBush: 0.5, CloudberryBush(Clone): 0.5, Pickable_Thistle(Clone): 0.5, Pickable_Thistle: 0.5, Pickable_Dandelion(Clone): 0.5, Pickable_Dandelion: 0.5"); farmGridFixedRotation.SettingChanged += FarmGridFixedRotation_SettingChanged; plantSpacing.SettingChanged += PlantSpacing_SettingChanged; farmGridSections.SettingChanged += FarmGridSections_SettingChanged; farmGridYOffset.SettingChanged += FarmGridYOffset_SettingChanged; farmGridColor.SettingChanged += FarmGridColor_SettingChanged; plantObjectMasks.SettingChanged += PlantObjectMasks_SettingChanged; customPlants.SettingChanged += CustomPlants_SettingChanged; SettingsChanged(); } private void FarmGridFixedRotation_SettingChanged(object sender, EventArgs e) { FarmGrid_Patch.farmGridFixedRotation = farmGridFixedRotation.Value; FarmGrid_Patch.DestroyFarmGrid(); } private void SettingsChanged() { FarmGridFixedRotation_SettingChanged(null, null); PlantSpacing_SettingChanged(null, null); FarmGridSections_SettingChanged(null, null); FarmGridYOffset_SettingChanged(null, null); FarmGridColor_SettingChanged(null, null); PlantObjectMasks_SettingChanged(null, null); CustomPlants_SettingChanged(null, null); } private void CustomPlants_SettingChanged(object sender, EventArgs e) { FarmGrid_Patch.customPlants.Clear(); string[] array = customPlants.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Split(new string[1] { ":" }, StringSplitOptions.RemoveEmptyEntries); if (array3.Length == 2 && float.TryParse(array3[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { FarmGrid_Patch.customPlants.Add(array3[0].Trim(), result); } } FarmGrid_Patch.DestroyFarmGrid(); } private void PlantObjectMasks_SettingChanged(object sender, EventArgs e) { string[] array = plantObjectMasks.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); List<string> list = new List<string>(); string[] array2 = array; foreach (string text in array2) { list.Add(text.Trim()); } FarmGrid_Patch.plantObjectMasks = list; FarmGrid_Patch.DestroyFarmGrid(); } private void FarmGridColor_SettingChanged(object sender, EventArgs e) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) FarmGrid_Patch.farmGridColor = farmGridColor.Value; FarmGrid_Patch.DestroyFarmGrid(); } private void FarmGridYOffset_SettingChanged(object sender, EventArgs e) { FarmGrid_Patch.farmGridYOffset = farmGridYOffset.Value; FarmGrid_Patch.DestroyFarmGrid(); } private void FarmGridSections_SettingChanged(object sender, EventArgs e) { FarmGrid_Patch.farmGridSections = farmGridSections.Value; FarmGrid_Patch.DestroyFarmGrid(); } private void PlantSpacing_SettingChanged(object sender, EventArgs e) { FarmGrid_Patch.plantSpacing = plantSpacing.Value; FarmGrid_Patch.DestroyFarmGrid(); } } } namespace FarmGrid.Patches { public static class Vector3Ext { public static Vector3 xz(this Vector3 v) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) return new Vector3(v.x, 0f, v.z); } } [HarmonyPatch] internal class FarmGrid_Patch { private class PlantObject { public Vector3 position; public float growthSize; public PlantObject(Vector3 position, float growthSize) { //IL_0009: 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) this.position = position; this.growthSize = growthSize; } } public static float plantSpacing = 0.01f; public static int farmGridSections = 2; public static float farmGridYOffset = 0.2f; public static Color farmGridColor = new Color(0.8f, 0.8f, 0.8f, 0.2f); public static Dictionary<string, float> customPlants = new Dictionary<string, float>(); public static List<string> plantObjectMasks = new List<string> { "piece", "piece_nonsolid" }; private static Vector3 plantSnapPoint; private static GameObject[] farmGrid = null; private static bool farmGridVisible = false; private static Vector3 plantGhostPosition; private static Vector3 otherPlantCollider; private static List<PlantObject> otherPlantList; private static int plantObjectMask; private static Material lineMaterial; internal static int farmGridFixedRotation; [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> UpdatePlacementGhost(IEnumerable<CodeInstruction> instructions) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); int num = 0; bool flag = false; for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Brtrue) { num = i; } if (CodeInstructionExtensions.Calls(list[i], AccessTools.Method(typeof(Player), "FindClosestSnapPoints", (Type[])null, (Type[])null))) { list.InsertRange(num + 1, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(FarmGrid_Patch), "GetFarmSnapPoints", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Brtrue, list[num].operand) }); flag = true; break; } } if (!flag) { ZLog.LogWarning((object)"FarmGrid: Failed to patch UpdatePlacementGhost"); } return list; } [HarmonyPatch(typeof(Player), "PlacePiece")] [HarmonyPrefix] private static bool PlacePiece(ref Player __instance, ref bool __result, Piece piece) { //IL_0017: 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_003b: Unknown result type (might be due to invalid IL or missing references) if (GetPlantObject(__instance.m_placementGhost.GetComponent<Collider>(), out var plantObject) && HasOverlappingPlants(plantObject.position, plantObject.growthSize)) { __result = false; return false; } otherPlantCollider = Vector3.zero; return true; } [HarmonyPatch(typeof(Humanoid), "SetupVisEquipment")] [HarmonyPostfix] private static void SetupVisEquipment(ref Humanoid __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || ((Humanoid)Player.m_localPlayer).m_rightItem == null || ((Humanoid)Player.m_localPlayer).m_rightItem.m_shared == null || ((Humanoid)Player.m_localPlayer).m_rightItem.m_shared.m_name != "$item_cultivator")) { HideFarmGrid(); } } private static void DrawFarmGrid(Vector3 pos, Vector3 gridDir, float gridSize) { //IL_0026: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) if (farmGrid == null || (Object)(object)farmGrid[0] == (Object)null) { InitFarmGrid(); } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(gridDir.z, gridDir.y, 0f - gridDir.x); for (int i = -farmGridSections; i <= farmGridSections; i++) { Vector3 val2 = pos + gridDir * (float)i * gridSize; GameObject val3 = farmGrid[i + farmGridSections]; val3.transform.position = val2; LineRenderer component = val3.GetComponent<LineRenderer>(); component.widthMultiplier = 0.015f; ((Renderer)component).enabled = true; for (int j = -farmGridSections; j <= farmGridSections; j++) { Vector3 val4 = val2 + val * (float)j * gridSize; float groundHeight = GetGroundHeight(val4); val4.y = groundHeight + farmGridYOffset; component.SetPosition(j + farmGridSections, val4); } } for (int k = -farmGridSections; k <= farmGridSections; k++) { Vector3 val5 = pos + val * (float)k * gridSize; GameObject val6 = farmGrid[k + farmGridSections + (farmGridSections * 2 + 1)]; val6.transform.position = val5; LineRenderer component2 = val6.GetComponent<LineRenderer>(); component2.widthMultiplier = 0.015f; ((Renderer)component2).enabled = true; for (int l = -farmGridSections; l <= farmGridSections; l++) { Vector3 val7 = val5 + gridDir * (float)l * gridSize; float groundHeight2 = GetGroundHeight(val7); val7.y = groundHeight2 + farmGridYOffset; component2.SetPosition(l + farmGridSections, val7); } } farmGridVisible = true; } private static float GetGroundHeight(Vector3 linePos) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_003b: 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) //IL_006c: Unknown result type (might be due to invalid IL or missing references) float num = ZoneSystem.instance.GetGroundHeight(linePos); RaycastHit[] array = Physics.RaycastAll(linePos + Vector3.up, Vector3.down, 2f, Piece.s_pieceRayMask); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val = array2[i]; if (!Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Plant>()) && ((RaycastHit)(ref val)).point.y > num) { num = ((RaycastHit)(ref val)).point.y; } } return num; } public static void DestroyFarmGrid() { if (farmGrid == null) { return; } for (int i = 0; i < farmGrid.Length; i++) { if (Object.op_Implicit((Object)(object)farmGrid[i])) { Object.Destroy((Object)(object)farmGrid[i]); } } farmGrid = null; } private static void InitFarmGrid() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0074: 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) if (!Object.op_Implicit((Object)(object)lineMaterial)) { lineMaterial = Resources.FindObjectsOfTypeAll<Material>().First((Material k) => ((Object)k).name == "Default-Line"); } farmGrid = (GameObject[])(object)new GameObject[(farmGridSections * 2 + 1) * 2]; for (int i = 0; i < farmGrid.Length; i++) { GameObject val = new GameObject(); LineRenderer val2 = val.AddComponent<LineRenderer>(); ((Renderer)val2).material = lineMaterial; val2.startColor = farmGridColor; val2.endColor = farmGridColor; val2.positionCount = farmGridSections * 2 + 1; farmGrid[i] = val; } } private static void HideFarmGrid() { if (farmGridVisible && farmGrid != null && (Object)(object)farmGrid[0] != (Object)null) { for (int i = 0; i < farmGrid.Length; i++) { LineRenderer component = farmGrid[i].GetComponent<LineRenderer>(); ((Renderer)component).enabled = false; } farmGridVisible = false; } } private static PlantObject GetGhostPlant() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; Collider component = localPlayer.m_placementGhost.GetComponent<Collider>(); if ((Object)(object)component != (Object)null && GetPlantObject(component, out var plantObject)) { return plantObject; } if ((Object)(object)component == (Object)null) { Piece componentInParent = localPlayer.m_placementGhost.GetComponentInParent<Piece>(); if ((Object)(object)componentInParent != (Object)null && customPlants.TryGetValue(((Object)componentInParent).name, out var value)) { return new PlantObject(((Component)componentInParent).transform.position, value); } } return null; } private static bool GetFarmSnapPoints() { //IL_0050: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00bb: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_042b: Unknown result type (might be due to invalid IL or missing references) //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_0420: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) GameObject val = Player.m_localPlayer?.m_placementGhost; if ((Object)(object)val == (Object)null) { return false; } PlantObject plantGhost = GetGhostPlant(); if (plantGhost != null) { if (plantGhostPosition == val.transform.position) { if (plantSnapPoint != Vector3.zero) { val.transform.position = plantSnapPoint; } return true; } plantSnapPoint = Vector3.zero; plantGhostPosition = plantGhost.position; List<PlantObject> otherPlants = GetOtherPlants(plantGhost.position, plantGhost.growthSize * 3.5f); otherPlants.OrderBy(delegate(PlantObject k) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_0016: Unknown result type (might be due to invalid IL or missing references) Vector3 val6 = k.position - plantGhost.position; return ((Vector3)(ref val6)).sqrMagnitude; }); PlantObject firstPlant = ((otherPlants.Count > 0) ? otherPlants[0] : null); if (otherPlants.Count >= 1) { if (!((Vector3)(ref otherPlantCollider)).Equals(otherPlants[0].position)) { otherPlantCollider = otherPlants[0].position; otherPlantList = GetOtherPlants(otherPlants[0].position, plantGhost.growthSize * 4.5f); otherPlantList = otherPlantList.OrderBy(delegate(PlantObject k) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_0016: Unknown result type (might be due to invalid IL or missing references) Vector3 val5 = k.position - firstPlant.position; return ((Vector3)(ref val5)).sqrMagnitude; }).ToList(); } otherPlants = otherPlantList; } if (otherPlants.Count == 1) { Vector3 val2 = plantGhost.position.xz() - otherPlants[0].position.xz(); ((Vector3)(ref val2)).Normalize(); float num = Mathf.Max(plantGhost.growthSize, otherPlants[0].growthSize) * 2f; float num2 = num + plantSpacing; plantSnapPoint = otherPlants[0].position + val2 * num2; float groundHeight = GetGroundHeight(plantSnapPoint); plantSnapPoint.y = groundHeight; val.transform.position = plantSnapPoint; DrawFarmGrid(plantSnapPoint, val2, num2); return true; } if (otherPlants.Count > 1) { Vector3 gridDir = GetGridDir(otherPlants, plantGhost); Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(gridDir.z, gridDir.y, 0f - gridDir.x); float num3 = Mathf.Max(Mathf.Max(otherPlants[1].growthSize, otherPlants[0].growthSize), plantGhost.growthSize) * 2f; float num4 = num3 + plantSpacing; List<Vector3> list = new List<Vector3>(); for (int i = -2; i <= 2; i++) { for (int j = -2; j <= 2; j++) { if (i != 0 || j != 0) { Vector3 item = firstPlant.position + gridDir * (float)i * num4 + val3 * (float)j * num4; list.Add(item); } } } list = list.OrderBy(delegate(Vector3 k) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //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) Vector3 val4 = k - plantGhost.position; return ((Vector3)(ref val4)).sqrMagnitude; }).ToList(); plantSnapPoint = Vector3.zero; for (int l = 0; l < list.Count; l++) { if (!HasOverlappingPlants(list[l], plantGhost.growthSize)) { plantSnapPoint = list[l]; break; } } if (plantSnapPoint == Vector3.zero) { plantSnapPoint = list[0]; } float groundHeight2 = GetGroundHeight(plantSnapPoint); plantSnapPoint.y = groundHeight2; val.transform.position = plantSnapPoint; DrawFarmGrid(plantSnapPoint, gridDir, num4); return true; } HideFarmGrid(); return true; } HideFarmGrid(); return false; } private static Vector3 GetGridDir(List<PlantObject> plantList, PlantObject plantGhost) { //IL_004c: 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_0179: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) Vector3 result = default(Vector3); if (farmGridFixedRotation != 0) { result.y = 0f; result.x = Mathf.Sin((float)farmGridFixedRotation * ((float)Math.PI / 180f)); result.z = Mathf.Cos((float)farmGridFixedRotation * ((float)Math.PI / 180f)); return ((Vector3)(ref result)).normalized; } for (int i = 0; i < plantList.Count - 1; i++) { for (int j = 1 + i; j < plantList.Count; j++) { result = plantList[i].position.xz() - plantList[j].position.xz(); float num = Mathf.Max(Mathf.Max(plantList[i].growthSize, plantList[j].growthSize), plantGhost.growthSize) * 2f + plantSpacing; float magnitude = ((Vector3)(ref result)).magnitude; float num2 = Mathf.Floor(magnitude / (num - 0.01f)); if (Mathf.Abs(magnitude - num2 * num) <= num2 * 0.01f) { ((Vector3)(ref result)).Normalize(); return result; } } } result = plantList[0].position.xz() - plantList[1].position.xz(); ((Vector3)(ref result)).Normalize(); return result; } private static List<PlantObject> GetOtherPlants(Vector3 pos, float collisionRadius) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) List<PlantObject> list = new List<PlantObject>(); if (plantObjectMask == 0) { plantObjectMask = LayerMask.GetMask(plantObjectMasks.ToArray()); } int num = Physics.OverlapSphereNonAlloc(pos, collisionRadius, Piece.s_pieceColliders, plantObjectMask); for (int i = 0; i < num; i++) { if (GetPlantObject(Piece.s_pieceColliders[i], out var plantObject)) { list.Add(plantObject); } } return list; } private static bool HasOverlappingPlants(Vector3 pos, float collisionRadius) { //IL_0023: 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_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) if (plantObjectMask == 0) { plantObjectMask = LayerMask.GetMask(plantObjectMasks.ToArray()); } int num = Physics.OverlapSphereNonAlloc(pos, collisionRadius, Piece.s_pieceColliders, plantObjectMask); for (int i = 0; i < num; i++) { if (GetPlantObject(Piece.s_pieceColliders[i], out var plantObject)) { Vector3 val = pos - plantObject.position; if (((Vector3)(ref val)).magnitude <= collisionRadius + plantObject.growthSize) { return true; } } } return false; } private static bool GetPlantObject(Collider collider, out PlantObject plantObject) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)collider == (Object)null) { plantObject = null; return false; } Plant componentInParent = ((Component)collider).GetComponentInParent<Plant>(); if ((Object)(object)componentInParent != (Object)null) { if (!customPlants.TryGetValue(((Object)componentInParent).name, out var value)) { value = componentInParent.m_growRadius; } plantObject = new PlantObject(((Component)collider).transform.position, value); return true; } Piece componentInParent2 = ((Component)collider).GetComponentInParent<Piece>(); if ((Object)(object)componentInParent2 != (Object)null && customPlants.TryGetValue(((Object)componentInParent2).name, out var value2)) { if (value2 == 0f) { value2 = collider.contactOffset; } plantObject = new PlantObject(((Component)collider).transform.position, value2); return true; } plantObject = null; return false; } } }
Plugins/FirstPersonMode.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using FirstPersonMode.Util; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("FirstPersonMode")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Azumatt")] [assembly: AssemblyProduct("FirstPersonMode")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("E0E2F92E-557C-4A05-9D89-AA92A0BD75C4")] [assembly: AssemblyFileVersion("1.3.3")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.3.0")] [module: UnverifiableCode] 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; } } } namespace FirstPersonMode { [HarmonyPatch(typeof(InstanceRenderer), "OnEnable")] internal static class InstanceRendererOnEnablePatch { private static readonly int CamCull = Shader.PropertyToID("_CamCull"); private static void Prefix(InstanceRenderer __instance) { Transform parent = ((Component)__instance).gameObject.transform.parent; if (((parent != null) ? ((Object)parent).name : null) == "grassroot") { __instance.m_material.SetFloat(CamCull, 0f); } } } [HarmonyPatch(typeof(Pickable), "Awake")] internal static class PickableAwakePatch { private static void Postfix(Pickable __instance) { Renderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Renderer>(); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] materials = componentsInChildren[i].materials; for (int j = 0; j < materials.Length; j++) { materials[j].SetFloat("_CamCull", 0f); } } } } [HarmonyPatch(typeof(Character), "SetVisible")] public static class CharacterSetVisiblePatch { private static bool Prefix(ref Character __instance, bool visible) { //IL_0066: 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) if (FirstPersonModePlugin.FirstPersonEnabled.Value != FirstPersonModePlugin.Toggle.On) { return true; } if ((Object)(object)__instance.m_lodGroup == (Object)null || __instance.m_lodVisible == visible || (__instance.IsPlayer() && !visible)) { return false; } __instance.m_lodVisible = visible; __instance.m_lodGroup.localReferencePoint = (Vector3)(__instance.m_lodVisible ? __instance.m_originalLocalRef : new Vector3(999999f, 999999f, 999999f)); return false; } } [HarmonyPatch(typeof(GameCamera), "Awake")] public static class GameCameraAwakePatch { private static void Postfix(ref GameCamera __instance) { if (FirstPersonModePlugin.FirstPersonEnabled.Value == FirstPersonModePlugin.Toggle.On) { FirstPersonModePlugin.CachedCameraValues.ZoomSens = __instance.m_zoomSens; FirstPersonModePlugin.CachedCameraValues.MinDistance = __instance.m_minDistance; FirstPersonModePlugin.CachedCameraValues.MaxDistance = __instance.m_maxDistance; FirstPersonModePlugin.CachedCameraValues.FOV = __instance.m_fov; } } } [HarmonyPatch(typeof(VisEquipment), "SetHelmetEquipped")] public static class UpdateVisEquipment_SetHelmetequiped2Nothing { private static bool _helmetVisRemovedPrefabrestored; private static bool _helmetVisRemoved; private static void Prefix(VisEquipment __instance, bool ___m_isPlayer, int hash, int hairHash, ref int ___m_currentHelmetItemHash, ref GameObject ___m_helmetItemInstance, ref bool ___m_helmetHideHair, ref Transform ___m_helmet) { if (FirstPersonModePlugin.NoHeadMode.Value == FirstPersonModePlugin.Toggle.On || (Object)(object)__instance == (Object)null || !Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponent<Player>()) || (Object)(object)((Component)__instance).gameObject.GetComponent<Player>() != (Object)(object)Player.m_localPlayer) { return; } if (___m_currentHelmetItemHash != hash) { _helmetVisRemoved = false; } if ((Object)(object)ObjectDB.instance == (Object)null) { return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hash); if (!Object.op_Implicit((Object)(object)itemPrefab)) { return; } if (FirstPersonModePlugin.DynamicPerson.IsFirstPerson && !_helmetVisRemoved) { int childCount = itemPrefab.transform.childCount; for (int i = 0; i < childCount; i++) { Transform child = itemPrefab.transform.GetChild(i); string name = ((Object)((Component)child).gameObject).name; if ((name == "attach" || name == "attach_skin") ? true : false) { Renderer[] componentsInChildren = ((Component)child).gameObject.GetComponentsInChildren<Renderer>(); for (int j = 0; j < componentsInChildren.Length; j++) { componentsInChildren[j].shadowCastingMode = (ShadowCastingMode)3; } } } ___m_currentHelmetItemHash = -1; _helmetVisRemoved = true; _helmetVisRemovedPrefabrestored = false; } else if (!FirstPersonModePlugin.DynamicPerson.IsFirstPerson && _helmetVisRemoved) { _helmetVisRemoved = false; ___m_currentHelmetItemHash = -1; } } private static void Postfix(VisEquipment __instance, bool ___m_isPlayer, int hash, int hairHash, ref int ___m_currentHelmetItemHash, ref GameObject ___m_helmetItemInstance, ref bool ___m_helmetHideHair, ref Transform ___m_helmet) { if (FirstPersonModePlugin.NoHeadMode.Value == FirstPersonModePlugin.Toggle.On || !Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponent<Player>()) || _helmetVisRemovedPrefabrestored || (Object)(object)((Component)__instance).gameObject.GetComponent<Player>() != (Object)(object)Player.m_localPlayer) { return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hash); if (!Object.op_Implicit((Object)(object)itemPrefab)) { return; } int childCount = itemPrefab.transform.childCount; for (int i = 0; i < childCount; i++) { Transform child = itemPrefab.transform.GetChild(i); string name = ((Object)((Component)child).gameObject).name; if ((name == "attach" || name == "attach_skin") ? true : false) { Renderer[] componentsInChildren = ((Component)child).gameObject.GetComponentsInChildren<Renderer>(); for (int j = 0; j < componentsInChildren.Length; j++) { componentsInChildren[j].shadowCastingMode = (ShadowCastingMode)1; } } } _helmetVisRemovedPrefabrestored = true; } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] public static class GameCameraUpdatePatch { private static void Postfix(ref GameCamera __instance, float dt) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) if (FirstPersonModePlugin.FirstPersonEnabled.Value != FirstPersonModePlugin.Toggle.On || (FirstPersonModePlugin.CHEInBuildMode != null && FirstPersonModePlugin.CHEIsLoaded && (bool)FirstPersonModePlugin.CHEInBuildMode.Invoke(null, null))) { return; } if (__instance.m_freeFly) { __instance.UpdateFreeFly(dt); __instance.UpdateCameraShake(dt); return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } bool flag = FirstPersonModePlugin.DynamicPerson.IsFirstPerson; bool flag2 = FirstPersonModePlugin.ToggleFirstPersonHotkey.Value.IsKeyDown(); if ((__instance.m_distance <= 1f && !flag && !flag2) || FirstPersonModePlugin.FirstPersonEnforced.Value == FirstPersonModePlugin.Toggle.On) { flag = true; FirstPersonModePlugin.DynamicPerson.IsFirstPerson = true; Functions.SetupFP(ref __instance, ref localPlayer); } else if ((double)__instance.m_minDistance > 0.0 && flag && !flag2) { flag = false; FirstPersonModePlugin.DynamicPerson.IsFirstPerson = false; __instance.m_3rdOffset = FirstPersonModePlugin.DynamicPerson.NoFp3RdOffset; __instance.m_fpsOffset = FirstPersonModePlugin.DynamicPerson.NoFpFPSOffset; __instance.m_minDistance = FirstPersonModePlugin.CachedCameraValues.MinDistance; __instance.m_maxDistance = FirstPersonModePlugin.CachedCameraValues.MaxDistance; __instance.m_zoomSens = FirstPersonModePlugin.CachedCameraValues.ZoomSens; __instance.m_fov = FirstPersonModePlugin.CachedCameraValues.FOV; ((Character)localPlayer).m_head.localScale = Vector3.one; ((Character)localPlayer).m_eye.localScale = Vector3.one; } if (flag2 && FirstPersonModePlugin.FirstPersonEnforced.Value != FirstPersonModePlugin.Toggle.On) { if (FirstPersonModePlugin.DynamicPerson.IsFirstPerson = !flag) { Functions.SetupFP(ref __instance, ref localPlayer); } else { __instance.m_distance = 1.5f; __instance.m_3rdOffset = FirstPersonModePlugin.DynamicPerson.NoFp3RdOffset; __instance.m_fpsOffset = FirstPersonModePlugin.DynamicPerson.NoFpFPSOffset; __instance.m_minDistance = FirstPersonModePlugin.CachedCameraValues.MinDistance; __instance.m_maxDistance = FirstPersonModePlugin.CachedCameraValues.MaxDistance; __instance.m_zoomSens = FirstPersonModePlugin.CachedCameraValues.ZoomSens; __instance.m_fov = 65f; ((Character)localPlayer).m_head.localScale = Vector3.one; ((Character)localPlayer).m_eye.localScale = Vector3.one; } } __instance.m_camera.fieldOfView = __instance.m_fov; __instance.m_skyCamera.fieldOfView = __instance.m_fov; if (!Functions.ShouldIgnoreAdjustments(localPlayer)) { if (FirstPersonModePlugin.DynamicPerson.IsFirstPerson) { Functions.HandleFirstPersonMode(ref __instance); } else { Functions.HandleNotFirstPersonMode(ref __instance, localPlayer); } } if (((Character)localPlayer).IsDead() && Object.op_Implicit((Object)(object)localPlayer.GetRagdoll())) { ((Component)__instance).transform.LookAt(localPlayer.GetRagdoll().GetAverageBodyPosition()); } else { Functions.SetCameraTransform(ref __instance, localPlayer, dt); } __instance.UpdateCameraShake(dt); } } [HarmonyPatch(typeof(DamageText), "Awake")] internal static class DamageTextAwakePatch { private static void Prefix(DamageText __instance) { __instance.m_maxTextDistance = 100f; __instance.m_smallFontDistance = 35f; } } [HarmonyPatch(typeof(Hud), "UpdateShipHud")] internal static class UpdateHud_fixshiphud { private static void Postfix(Hud __instance, Player player) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (FirstPersonModePlugin.FirstPersonEnabled.Value != FirstPersonModePlugin.Toggle.On) { return; } Camera mainCamera = Utils.GetMainCamera(); if ((Object)(object)mainCamera == (Object)null) { return; } if (FirstPersonModePlugin.DynamicPerson.IsFirstPerson) { __instance.m_shipControlsRoot.transform.position = new Vector3((float)mainCamera.pixelWidth * 0.5f, (float)mainCamera.pixelHeight * 0.2f, 0f); return; } Ship controlledShip = player.GetControlledShip(); if ((Object)(object)controlledShip != (Object)null) { __instance.m_shipControlsRoot.transform.position = mainCamera.WorldToScreenPoint(controlledShip.m_controlGuiPos.position); } } } [BepInPlugin("Azumatt.FirstPersonMode", "FirstPersonMode", "1.3.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class FirstPersonModePlugin : BaseUnityPlugin { public enum Toggle { On = 1, Off = 0 } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct DynamicPerson { public static bool IsFirstPerson = false; public static Vector3 NoFp3RdOffset = Vector3.zero; public static Vector3 NoFpFPSOffset = Vector3.zero; public static float MaxDeviation = 40f; public static Quaternion PlayerRotation = Quaternion.identity; public static Rigidbody PlayerRigidbody = null; public static Vector3 LastTargetPosition = Vector3.zero; } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct CachedCameraValues { public static float ZoomSens = 10f; public static float MinDistance = 1f; public static float MaxDistance = 8f; public static float FOV = 8f; public static float NearClipPlaneMax = 0.02f; public static float NearClipPlaneMin = 0.01f; } private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] public string Category; [UsedImplicitly] public Action<ConfigEntryBase> CustomDrawer; } internal const string ModName = "FirstPersonMode"; internal const string ModVersion = "1.3.3"; internal const string Author = "Azumatt"; private const string ModGUID = "Azumatt.FirstPersonMode"; private static string ConfigFileName = "Azumatt.FirstPersonMode.cfg"; private static string ConfigFileFullPath; internal static string ConnectionError; private readonly Harmony _harmony = new Harmony("Azumatt.FirstPersonMode"); private static readonly ConfigSync ConfigSync; public static bool CHEIsLoaded; private Assembly _cheAssembly; public static MethodInfo? CHEInBuildMode; public static readonly ManualLogSource FirstPersonModeLogger; private static ConfigEntry<Toggle> _serverConfigLocked; internal static ConfigEntry<Toggle> FirstPersonEnabled; internal static ConfigEntry<Toggle> FirstPersonEnforced; internal static ConfigEntry<Toggle> NoHeadMode; internal static ConfigEntry<float> DefaultFOV; internal static ConfigEntry<KeyboardShortcut> ToggleFirstPersonHotkey; internal static ConfigEntry<KeyboardShortcut> RaiseFOVHotkey; internal static ConfigEntry<KeyboardShortcut> LowerFOVHotkey; internal static ConfigEntry<float> NearClipPlaneMinConfig; internal static ConfigEntry<float> NearClipPlaneMaxConfig; internal static ConfigEntry<Vector3> OffsetWhenAiming; public void Awake() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) if (Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.valheim_plus")) { FirstPersonModeLogger.LogWarning((object)"Valheim Plus detected, disabling FirstPersonMode to prevent camera stuttering. Please use the First Person mode in Valheim Plus or disable it to use this mod."); return; } _serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, new ConfigDescription("If on, the configuration is locked and can be changed by server admins only. All Synced With Server configurations will be enforced to the clients.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 8 } })); ConfigSync.AddLockingConfigEntry<Toggle>(_serverConfigLocked); FirstPersonEnabled = config("1 - Toggles", "Enable First Person", Toggle.On, "If on, First Person is enabled."); FirstPersonEnforced = config("1 - Toggles", "Enforce First Person", Toggle.Off, "If on, First Person is enforced to always be on. Respects the Enable First Person configuration and both must be on for First Person to be enforced."); NoHeadMode = config("1 - Toggles", "Hide Head", Toggle.Off, "If on, the camera will not use the culling mode and will instead shrink the head to hide it. This method is a bit better overall as your armor isn't see through, but looks a little weird. Headless people always do.", synchronizedSetting: false); DefaultFOV = config("2 - Camera", "Default FOV", 65f, "Default FOV for First Person.", synchronizedSetting: false); NearClipPlaneMinConfig = config("2 - Camera", "NearClipPlaneMin", 0.17f, "Adjusts the nearest distance at which objects are rendered in first person view. Increase to reduce body visibility; too high might clip nearby objects.", synchronizedSetting: false); NearClipPlaneMaxConfig = config("2 - Camera", "NearClipPlaneMax", 0.17f, "Adjusts the nearest distance at which objects are rendered in first person view. Increase to reduce body visibility; too high might clip nearby objects.", synchronizedSetting: false); OffsetWhenAiming = config<Vector3>("2 - Camera", "OffsetWhenAiming", new Vector3(0.35f, 0.15f, 0.071f), "Adjusts the x offset when aiming with a bow. Higher number = more to the right, lower is more to the left.", synchronizedSetting: false); ToggleFirstPersonHotkey = config<KeyboardShortcut>("3 - Keyboard Shortcuts", "Toggle First Person Shortcut", new KeyboardShortcut((KeyCode)104, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Keyboard Shortcut needed to toggle First Person. If FirstPersonMode is enforced, you cannot toggle.", synchronizedSetting: false); RaiseFOVHotkey = config<KeyboardShortcut>("3 - Keyboard Shortcuts", "Raise FOV Shortcut", new KeyboardShortcut((KeyCode)280, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Keyboard Shortcut needed to raise FOV.", synchronizedSetting: false); LowerFOVHotkey = config<KeyboardShortcut>("3 - Keyboard Shortcuts", "Lower FOV Shortcut", new KeyboardShortcut((KeyCode)281, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Keyboard Shortcut needed to lower FOV.", synchronizedSetting: false); CHEIsLoaded = Chainloader.PluginInfos.ContainsKey("Azumatt.BuildCameraCHE"); if (CHEIsLoaded) { _cheAssembly = ((object)Chainloader.PluginInfos["Azumatt.BuildCameraCHE"].Instance).GetType().Assembly; CHEInBuildMode = _cheAssembly.GetType("Valheim_Build_Camera.Utils")?.GetMethod("InBuildMode", BindingFlags.Static | BindingFlags.Public); } Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); SetupWatcher(); } private void Start() { AutoDoc(); } private void AutoDoc() { } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { FirstPersonModeLogger.LogDebug((object)"ReadConfigValues called"); ((BaseUnityPlugin)this).Config.Reload(); } catch { FirstPersonModeLogger.LogError((object)("There was an issue loading your " + ConfigFileName)); FirstPersonModeLogger.LogError((object)"Please check your config entries for spelling and format!"); } } private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); ConfigSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting; return val2; } private ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } static FirstPersonModePlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; ConnectionError = ""; ConfigSync = new ConfigSync("Azumatt.FirstPersonMode") { DisplayName = "FirstPersonMode", CurrentVersion = "1.3.3", MinimumRequiredVersion = "1.3.3" }; FirstPersonModeLogger = Logger.CreateLogSource("FirstPersonMode"); _serverConfigLocked = null; FirstPersonEnabled = null; FirstPersonEnforced = null; NoHeadMode = null; DefaultFOV = null; ToggleFirstPersonHotkey = null; RaiseFOVHotkey = null; LowerFOVHotkey = null; NearClipPlaneMinConfig = null; NearClipPlaneMaxConfig = null; OffsetWhenAiming = null; } } } namespace FirstPersonMode.Util { public static class KeyboardExtensions { public static bool IsKeyDown(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } return false; } public static bool IsKeyHeld(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } return false; } } public static class Functions { internal static bool ShouldIgnoreAdjustments(Player localPlayer) { Chat instance = Chat.instance; if ((instance == null || !instance.HasFocus()) && !Console.IsVisible() && !InventoryGui.IsVisible() && !StoreGui.IsVisible() && !Menu.IsVisible() && !Minimap.IsOpen() && !((Character)localPlayer).InCutscene()) { return ((Character)localPlayer).InPlaceMode(); } return true; } internal static void SetupFP(ref GameCamera __instance, ref Player localPlayer) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) FirstPersonModePlugin.CachedCameraValues.MaxDistance = __instance.m_maxDistance; FirstPersonModePlugin.CachedCameraValues.FOV = __instance.m_fov; FirstPersonModePlugin.DynamicPerson.NoFp3RdOffset = __instance.m_3rdOffset; FirstPersonModePlugin.DynamicPerson.NoFpFPSOffset = __instance.m_fpsOffset; __instance.m_3rdOffset = Vector3.zero; __instance.m_fpsOffset = Vector3.zero; __instance.m_minDistance = 0f; __instance.m_maxDistance = 0f; __instance.m_zoomSens = 0f; __instance.m_nearClipPlaneMax = FirstPersonModePlugin.NearClipPlaneMaxConfig.Value; __instance.m_nearClipPlaneMin = FirstPersonModePlugin.NearClipPlaneMinConfig.Value; __instance.m_fov = FirstPersonModePlugin.DefaultFOV.Value; if (FirstPersonModePlugin.NoHeadMode.Value == FirstPersonModePlugin.Toggle.On) { ((Character)localPlayer).m_head.localScale = Vector3.zero; ((Character)localPlayer).m_eye.localScale = Vector3.zero; __instance.m_nearClipPlaneMax = FirstPersonModePlugin.CachedCameraValues.NearClipPlaneMax; __instance.m_nearClipPlaneMin = FirstPersonModePlugin.CachedCameraValues.NearClipPlaneMin; } } internal static void HandleFirstPersonMode(ref GameCamera __instance) { //IL_0005: 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) if (FirstPersonModePlugin.RaiseFOVHotkey.Value.IsKeyDown()) { GameCamera obj = __instance; obj.m_fov += 1f; ((Terminal)Console.instance).AddString($"Changed fov to: {__instance.m_fov}"); } else if (FirstPersonModePlugin.LowerFOVHotkey.Value.IsKeyDown()) { GameCamera obj2 = __instance; obj2.m_fov -= 1f; ((Terminal)Console.instance).AddString($"Changed fov to: {__instance.m_fov}"); } } internal static void HandleNotFirstPersonMode(ref GameCamera __instance, Player localPlayer) { _ = __instance.m_minDistance; float num = ZInput.GetMouseScrollWheel(); if (Player.m_debugMode) { num = ScrollReturn(__instance, num); } GameCamera obj = __instance; obj.m_distance -= num * __instance.m_zoomSens; float num2 = (((Object)(object)localPlayer.GetControlledShip() != (Object)null) ? __instance.m_maxDistanceBoat : __instance.m_maxDistance); __instance.m_distance = Mathf.Clamp(__instance.m_distance, 0f, num2); } internal static float ScrollReturn(GameCamera cam, float scroll) { //IL_0027: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if (ZInput.GetKey((KeyCode)304, true) && ZInput.GetKey((KeyCode)99, true) && !Console.IsVisible()) { Vector2 mouseDelta = ZInput.GetMouseDelta(); EnvMan.instance.m_debugTimeOfDay = true; EnvMan.instance.m_debugTime = (float)(((double)EnvMan.instance.m_debugTime + (double)mouseDelta.y * 0.004999999888241291) % 1.0); if ((double)EnvMan.instance.m_debugTime < 0.0) { EnvMan instance = EnvMan.instance; instance.m_debugTime += 1f; } cam.m_fov += mouseDelta.x * 1f; cam.m_fov = Mathf.Clamp(cam.m_fov, 0.5f, 165f); cam.m_camera.fieldOfView = cam.m_fov; cam.m_skyCamera.fieldOfView = cam.m_fov; if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Character)Player.m_localPlayer).IsDebugFlying()) { if ((double)scroll > 0.0) { Character.m_debugFlySpeed = (int)Mathf.Clamp((float)Character.m_debugFlySpeed * 1.1f, (float)(Character.m_debugFlySpeed + 1), 300f); } else if ((double)scroll < 0.0 && Character.m_debugFlySpeed > 1) { Character.m_debugFlySpeed = (int)Mathf.Min((float)Character.m_debugFlySpeed * 0.9f, (float)(Character.m_debugFlySpeed - 1)); } } scroll = 0f; } return scroll; } internal static void SetCameraTransform(ref GameCamera __instance, Player localPlayer, float dt) { //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //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_001c: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0067: 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_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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012d: 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) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) if (FirstPersonModePlugin.DynamicPerson.IsFirstPerson) { Vector3 val = ((Character)localPlayer).GetHeadPoint(); Vector3 val2 = ((Component)((Character)localPlayer).m_eye).transform.rotation * new Vector3(0f, 0.15f, 0.071f); if (((Character)localPlayer).IsDrawingBow()) { val2 = ((Component)((Character)localPlayer).m_eye).transform.rotation * new Vector3(FirstPersonModePlugin.OffsetWhenAiming.Value.x, FirstPersonModePlugin.OffsetWhenAiming.Value.y, FirstPersonModePlugin.OffsetWhenAiming.Value.z); } if (Object.op_Implicit((Object)(object)Utils.FindChild(((Component)localPlayer).transform, "Azu_transform", (IterativeSearchType)0))) { val = Utils.FindChild(Utils.FindChild(((Component)localPlayer).transform, "Azu_transform", (IterativeSearchType)0), "Head", (IterativeSearchType)0).position; val2 = ((Component)((Character)localPlayer).m_eye).transform.rotation * new Vector3(0f, 0.15f, 0.142f); __instance.m_nearClipPlaneMax = 0.47f; } __instance.m_nearClipPlaneMax = FirstPersonModePlugin.NearClipPlaneMaxConfig.Value; Vector3 position = ((Component)__instance).transform.position; ((Component)__instance).transform.position = Vector3.Lerp(position, val + val2, 2f); if (((Character)localPlayer).TakeInput() && Input.GetAxis("Mouse ScrollWheel") < 0f && !((Character)localPlayer).InPlaceMode()) { GameCamera obj = __instance; obj.m_minDistance += 2f; } if (ZInput.GetButton("JoyAltKeys") && !Hud.InRadial() && __instance.m_camZoomToggle && ZInput.GetButton("JoyCamZoom")) { GameCamera obj2 = __instance; obj2.m_minDistance += 2f; } if (!((Character)localPlayer).InDodge() && !localPlayer.m_attached) { Quaternion rotation = ((Character)localPlayer).m_eye.rotation; float y = ((Quaternion)(ref rotation)).eulerAngles.y; rotation = ((Character)localPlayer).m_body.rotation; float value = 0f - CalculateDeviationAngle(y, ((Quaternion)(ref rotation)).eulerAngles.y); if (Math.Abs(value) > FirstPersonModePlugin.DynamicPerson.MaxDeviation) { rotation = ((Character)localPlayer).m_body.rotation; float num = ((Quaternion)(ref rotation)).eulerAngles.y * 1f; num += (Math.Abs(value) - FirstPersonModePlugin.DynamicPerson.MaxDeviation) * (float)Math.Sign(value); Quaternion rotation2 = ((Character)localPlayer).m_body.rotation; FirstPersonModePlugin.DynamicPerson.PlayerRotation = Quaternion.Euler(((Quaternion)(ref rotation2)).eulerAngles.x, num, ((Quaternion)(ref rotation2)).eulerAngles.z); FirstPersonModePlugin.DynamicPerson.PlayerRigidbody = ((Character)localPlayer).m_body; FirstPersonModePlugin.DynamicPerson.PlayerRigidbody.rotation = FirstPersonModePlugin.DynamicPerson.PlayerRotation; } } } else { Vector3 position2 = default(Vector3); Quaternion rotation3 = default(Quaternion); __instance.GetCameraPosition(dt, ref position2, ref rotation3); ((Component)__instance).transform.position = position2; ((Component)__instance).transform.rotation = rotation3; } } public static float CalculateDeviationAngle(float angle1, float angle2) { float num = (angle2 - angle1 + 540f) % 360f - 180f; if (!(num >= -180f)) { return num + 360f; } return num; } } } namespace System.Runtime.CompilerServices { [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 ServerSync { [PublicAPI] internal abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] internal class SyncedConfigEntry<T> : OwnConfigEntryBase { public readonly ConfigEntry<T> SourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public SyncedConfigEntry(ConfigEntry<T> sourceConfig) { SourceConfig = sourceConfig; } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } internal abstract class CustomSyncedValueBase { public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List<ZNetPeer> peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } static IEnumerator WatchAdminListChanges() { MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List<string> CurrentList = new List<string>(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List<string>(adminList.GetList()); List<ZNetPeer> adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p) { string hostName = p.m_rpc.GetSocket().GetHostName(); return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName })); }).ToList(); List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>(); public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return Original.GotNewData(); } public void Close() { Original.Close(); } public string GetEndPointString() { return Original.GetEndPointString(); } public void GetAndResetStats(out int totalSent, out int totalRecv) { Original.GetAndResetStats(ref totalSent, ref totalRecv); } public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec) { Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec); } public ISocket Accept() { return Original.Accept(); } public int GetHostPort() { return Original.GetHostPort(); } public bool Flush() { return Original.Flush(); } public string GetHostName() { return Original.GetHostName(); } public void VersionMatch() { if (finished) { Original.VersionMatch(); } else { versionMatchQueued = Package.Count; } } public void Send(ZPackage pkg) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (__instance.IsServer()) { BufferingSocket value = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, value); object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (val != null && (int)ZNet.m_onlineBackend > 0) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, value); } if (__state == null) { __state = new Dictionary<Assembly, BufferingSocket>(); } __state[Assembly.GetExecutingAssembly()] = value; } } [HarmonyPostfix] private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { ZRpc rpc2 = rpc; ZNet __instance2 = __instance; Dictionary<Assembly, BufferingSocket> __state2 = __state; ZNetPeer peer; if (__instance2.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance2).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc2.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()]; bufferingSocket2.finished = true; for (int i = 0; i < bufferingSocket2.Package.Count; i++) { if (i == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } bufferingSocket2.Original.Send(bufferingSocket2.Package[i]); } if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } } IEnumerator sendAsync() { foreach (ConfigSync configSync in configSyncs) { List<PackageEntry> entries = new List<PackageEntry>(); if (configSync.CurrentVersion != null) { entries.Add(new PackageEntry { section = "Internal", key = "serverversion", type = typeof(string), value = configSync.CurrentVersion }); } MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); entries.Add(new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2] { adminList, rpc2.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false); yield return ((MonoBehaviour)__instance2).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package)); } SendBufferedData(); } } } private class PackageEntry { public string section = null; public string key = null; public Type type = null; public object? value; } [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] private static class PreventSavingServerInfo { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, ref string __result) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase)) { return true; } __result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType); return false; } } [HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")] private static class PreventConfigRereadChangingValues { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, string value) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null) { return true; } try { ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType); } catch (Exception ex) { Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } return false; } } private class InvalidDeserializationTypeException : Exception { public string expected = null; public string received = null; public string field = ""; } public static bool ProcessingServerUpdate; public readonly string Name; public string? DisplayName; public string? CurrentVersion; public string? MinimumRequiredVersion; public bool ModRequired = false; private bool? forceConfigLocking; private bool isSourceOfTruth = true; private static readonly HashSet<ConfigSync> configSyncs; private readonly HashSet<OwnConfigEntryBase> allConfigs = new HashSet<OwnConfigEntryBase>(); private HashSet<CustomSyncedValueBase> allCustomValues = new HashSet<CustomSyncedValueBase>(); private static bool isServer; private static bool lockExempt; private OwnConfigEntryBase? lockedConfig = null; private const byte PARTIAL_CONFIGS = 1; private const byte FRAGMENTED_CONFIG = 2; private const byte COMPRESSED_CONFIG = 4; private readonly Dictionary<string, SortedDictionary<int, byte[]>> configValueCache = new Dictionary<string, SortedDictionary<int, byte[]>>(); private readonly List<KeyValuePair<long, string>> cacheExpirations = new List<KeyValuePair<long, string>>(); private static long packageCounter; public bool IsLocked { get { bool? flag = forceConfigLocking; bool num; if (!flag.HasValue) { if (lockedConfig == null) { goto IL_0052; } num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0; } else { num = flag.GetValueOrDefault(); } if (!num) { goto IL_0052; } int result = ((!lockExempt) ? 1 : 0); goto IL_0053; IL_0053: return (byte)result != 0; IL_0052: result = 0; goto IL_0053; } set { forceConfigLocking = value; } } public bool IsAdmin => lockExempt || isSourceOfTruth; public bool IsSourceOfTruth { get { return isSourceOfTruth; } private set { if (value != isSourceOfTruth) { isSourceOfTruth = value; this.SourceOfTruthChanged?.Invoke(value); } } } public bool InitialSyncDone { get; private set; } = false; public event Action<bool>? SourceOfTruthChanged; private event Action? lockedConfigChanged; static ConfigSync() { ProcessingServerUpdate = false; configSyncs = new HashSet<ConfigSync>(); lockExempt = false; packageCounter = 0L; RuntimeHelpers.RunClassConstructor(typeof(VersionCheck).TypeHandle); } public ConfigSync(string name) { Name = name; configSyncs.Add(this); new VersionCheck(this); } public SyncedConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry) { ConfigEntry<T> configEntry2 = configEntry; OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry2); SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>; if (syncedEntry == null) { syncedEntry = new SyncedConfigEntry<T>(configEntry2); AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry2).Description, new object[1] { new ConfigurationManagerAttributes() }.Concat(((ConfigEntryBase)configEntry2).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray()); configEntry2.SettingChanged += delegate { if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig) { Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry2); } }; allConfigs.Add(syncedEntry); } return syncedEntry; } public SyncedConfigEntry<T> AddLockingConfigEntry<T>(ConfigEntry<T> lockingConfig) where T : IConvertible { if (lockedConfig != null) { throw new Exception("Cannot initialize locking ConfigEntry twice"); } lockedConfig = AddConfigEntry<T>(lockingConfig); lockingConfig.SettingChanged += delegate { this.lockedConfigChanged?.Invoke(); }; return (SyncedConfigEntry<T>)lockedConfig; } internal void AddCustomValue(CustomSyncedValueBase customValue) { CustomSyncedValueBase customValue2 = customValue; if (allCustomValues.Select((CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue2.Identifier)) { throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)"); } allCustomValues.Add(customValue2); allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority)); customValue2.ValueChanged += delegate { if (!ProcessingServerUpdate) { Broadcast(ZRoutedRpc.Everybody, customValue2); } }; } private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package) { lockedConfigChanged += serverLockedSettingChanged; IsSourceOfTruth = false; if (HandleConfigSyncRPC(0L, package, clientUpdate: false)) { InitialSyncDone = true; } } private void RPC_FromOtherClientConfigSync(long sender, ZPackage package) { HandleConfigSyncRPC(sender, package, clientUpdate: true); } private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown try { if (isServer && IsLocked) { ZRpc? currentRpc = SnatchCurrentlyHandlingRPC.currentRpc; object obj; if (currentRpc == null) { obj = null; } else { ISocket socket = currentRpc.GetSocket(); obj = ((socket != null) ? socket.GetHostName() : null); } string text = (string)obj; if (text != null) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text })))) { return false; } } } cacheExpirations.RemoveAll(delegate(KeyValuePair<long, string> kv) { if (kv.Key < DateTimeOffset.Now.Ticks) { configValueCache.Remove(kv.Value); return true; } return false; }); byte b = package.ReadByte(); if ((b & 2u) != 0) { long num = package.ReadLong(); string text2 = sender.ToString() + num; if (!configValueCache.TryGetValue(text2, out SortedDictionary<int, byte[]> value)) { value = new SortedDictionary<int, byte[]>(); configValueCache[text2] = value; cacheExpirations.Add(new KeyValuePair<long, string>(DateTimeOffset.Now.AddSeconds(60.0).Ticks, text2)); } int key = package.ReadInt(); int num2 = package.ReadInt(); value.Add(key, package.ReadByteArray()); if (value.Count < num2) { return false; } configValueCache.Remove(text2); package = new ZPackage(value.Values.SelectMany((byte[] a) => a).ToArray()); b = package.ReadByte(); } ProcessingServerUpdate = true; if ((b & 4u) != 0) { byte[] buffer = package.ReadByteArray(); MemoryStream stream = new MemoryStream(buffer); MemoryStream memoryStream = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress)) { deflateStream.CopyTo(memoryStream); } package = new ZPackage(memoryStream.ToArray()); b = package.ReadByte(); } if ((b & 1) == 0) { resetConfigsFromServer(); } ParsedConfigs parsedConfigs = ReadConfigsFromPackage(package); ConfigFile val2 = null; bool saveOnConfigSet = false; foreach (KeyValuePair<OwnConfigEntryBase, object> configValue in parsedConfigs.configValues) { if (!isServer && configValue.Key.LocalBaseValue == null) { configValue.Key.LocalBaseValue = configValue.Key.BaseConfig.BoxedValue; } if (val2 == null) { val2 = configValue.Key.BaseConfig.ConfigFile; saveOnConfigSet = val2.SaveOnConfigSet; val2.SaveOnConfigSet = false; } configValue.Key.BaseConfig.BoxedValue = configValue.Value; } if (val2 != null) { val2.SaveOnConfigSet = saveOnConfigSet; } foreach (KeyValuePair<CustomSyncedValueBase, object> customValue in parsedConfigs.customValues) { if (!isServer) { CustomSyncedValueBase key2 = customValue.Key; if (key2.LocalBaseValue == null) { key2.LocalBaseValue = customValue.Key.BoxedValue; } } customValue.Key.BoxedValue = customValue.Value; } Debug.Log((object)string.Format("Received {0} configs and {1} custom values from {2} for mod {3}", parsedConfigs.configValues.Count, parsedConfigs.customValues.Count, (isServer || clientUpdate) ? $"client {sender}" : "the server", DisplayName ?? Name)); if (!isServer) { serverLockedSettingChanged(); } return true; } finally { ProcessingServerUpdate = false; } } private ParsedConfigs ReadConfigsFromPackage(ZPackage package) { ParsedConfigs parsedConfigs = new ParsedConfigs(); Dictionary<string, OwnConfigEntryBase> dictionary = allConfigs.Where((OwnConfigEntryBase c) => c.SynchronizedConfig).ToDictionary((OwnConfigEntryBase c) => c.BaseConfig.Definition.Section + "_" + c.BaseConfig.Definition.Key, (OwnConfigEntryBase c) => c); Dictionary<string, CustomSyncedValueBase> dictionary2 = allCustomValues.ToDictionary((CustomSyncedValueBase c) => c.Identifier, (CustomSyncedValueBase c) => c); int num = package.ReadInt(); for (int i = 0; i < num; i++) { string text = package.ReadString(); string text2 = package.ReadString(); string text3 = package.ReadString(); Type type = Type.GetType(text3); if (text3 == "" || type != null) { object obj; try { obj = ((text3 == "") ? null : ReadValueWithTypeFromZPackage(package, type)); } catch (InvalidDeserializationTypeException ex) { Debug.LogWarning((object)("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + ex.expected)); continue; } OwnConfigEntryBase value2; if (text == "Internal") { CustomSyncedValueBase value; if (text2 == "serverversion") { if (obj?.ToString() != CurrentVersion) { Debug.LogWarning((object)("Received server version is not equal: server version = " + (obj?.ToString() ?? "null") + "; local version = " + (CurrentVersion ?? "unknown"))); } } else if (text2 == "lockexempt") { if (obj is bool flag) { lockExempt = flag; } } else if (dictionary2.TryGetValue(text2, out value)) { if ((text3 == "" && (!value.Type.IsValueType || Nullable.GetUnderlyingType(value.Type) != null)) || GetZPackageTypeString(value.Type) == text3) { parsedConfigs.customValues[value] = obj; continue; } Debug.LogWarning((object)("Got unexpected type " + text3 + " for internal value " + text2 + " for mod " + (DisplayName ?? Name) + ", expecting " + value.Type.AssemblyQualifiedName)); } } else if (dictionary.TryGetValue(text + "_" + text2, out value2)) { Type type2 = configType(value2.BaseConfig); if ((text3 == "" && (!type2.IsValueType || Nullable.GetUnderlyingType(type2) != null)) || GetZPackageTypeString(type2) == text3) { parsedConfigs.configValues[value2] = obj; continue; } Debug.LogWarning((object)("Got unexpected type " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + type2.AssemblyQualifiedName)); } else { Debug.LogWarning((object)("Received unknown config entry " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ". This may happen if client and server versions of the mod do not match.")); } continue; } Debug.LogWarning((object)("Got invalid type " + text3 + ", abort reading of received configs")); return new ParsedConfigs(); } return parsedConfigs; } private static bool isWritableConfig(OwnConfigEntryBase config) { OwnConfigEntryBase config2 = config; ConfigSync configSync = configSyncs.FirstOrDefault((ConfigSync cs) => cs.allConfigs.Contains(config2)); if (configSync == null) { return true; } return configSync.IsSourceOfTruth || !config2.SynchronizedConfig || config2.LocalBaseValue == null || (!configSync.IsLocked && (config2 != configSync.lockedConfig || lockExempt)); } private void serverLockedSettingChanged() { foreach (OwnConfigEntryBase allConfig in allConfigs) { configAttribute<ConfigurationManagerAttributes>(allConfig.BaseConfig).ReadOnly = !isWritableConfig(allConfig); } } private void resetConfigsFromServer() { ConfigFile val = null; bool saveOnConfigSet = false; foreach (OwnConfigEntryBase item in allConfigs.Where((OwnConfigEntryBase config) => config.LocalBaseValue != null)) { if (val == null) { val = item.BaseConfig.ConfigFile; saveOnConfigSet = val.SaveOnConfigSet; val.SaveOnConfigSet = false; } item.BaseConfig.BoxedValue = item.LocalBaseValue; item.LocalBaseValue = null; } if (val != null) { val.SaveOnConfigSet = saveOnConfigSet; } foreach (CustomSyncedValueBase item2 in allCustomValues.Where((CustomSyncedValueBase config) => config.LocalBaseValue != null)) { item2.BoxedValue = item2.LocalBaseValue; item2.LocalBaseValue = null; } lockedConfigChanged -= serverLockedSettingChanged; serverLockedSettingChanged(); } private IEnumerator<bool> distributeConfigToPeers(ZNetPeer peer, ZPackage package) { ZNetPeer peer2 = peer; ZRoutedRpc rpc = ZRoutedRpc.instance; if (rpc == null) { yield break; } byte[] data = package.GetArray(); if (data != null && data.LongLength > 250000) { int fragments = (int)(1 + (data.LongLength - 1) / 250000); long packageIdentifier = ++packageCounter; int fragment = 0; while (fragment < fragments) { foreach (bool item in waitForQueue()) { yield return item; } if (peer2.m_socket.IsConnected()) { ZPackage fragmentedPackage = new ZPackage(); fragmentedPackage.Write((byte)2); fragmentedPackage.Write(packageIdentifier); fragmentedPackage.Write(fragment); fragmentedPackage.Write(fragments); fragmentedPackage.Write(data.Skip(250000 * fragment).Take(250000).ToArray()); SendPackage(fragmentedPackage); if (fragment != fragments - 1) { yield return true; } int num = fragment + 1; fragment = num; continue; } break; } yield break; } foreach (bool item2 in waitForQueue()) { yield return item2; } SendPackage(package); void SendPackage(ZPackage pkg) { string text = Name + " ConfigSync"; if (isServer) { peer2.m_rpc.Invoke(text, new object[1] { pkg }); } else { rpc.InvokeRoutedRPC(peer2.m_server ? 0 : peer2.m_uid, text, new object[1] { pkg }); } } IEnumerable<bool> waitForQueue() { float timeout = Time.time + 30f; while (peer2.m_socket.GetSendQueueSize() > 20000) { if (Time.time > timeout) { Debug.Log((object)$"Disconnecting {peer2.m_uid} after 30 seconds config sending timeout"); peer2.m_rpc.Invoke("Error", new object[1] { (object)(ConnectionStatus)5 }); ZNet.instance.Disconnect(peer2); break; } yield return false; } } } private IEnumerator sendZPackage(long target, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return Enumerable.Empty<object>().GetEnumerator(); } List<ZNetPeer> list = (List<ZNetPeer>)AccessTools.DeclaredField(typeof(ZRoutedRpc), "m_peers").GetValue(ZRoutedRpc.instance); if (target != ZRoutedRpc.Everybody) { list = list.Where((ZNetPeer p) => p.m_uid == target).ToList(); } return sendZPackage(list, package); } private IEnumerator sendZPackage(List<ZNetPeer> peers, ZPackage package) { ZPackage package2 = package; if (!Object.op_Implicit((Object)(object)ZNet.instance)) { yield break; } byte[] rawData = package2.GetArray(); if (rawData != null && rawData.LongLength > 10000) { ZPackage compressedPackage = new ZPackage(); compressedPackage.Write((byte)4); MemoryStream output = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(output, CompressionLevel.Optimal)) { deflateStream.Write(rawData, 0, rawData.Length); } compressedPackage.Write(output.ToArray()); package2 = compressedPackage; } List<IEnumerator<bool>> writers = (from peer in peers where peer.IsReady() select peer into p select distributeConfigToPeers(p, package2)).ToList(); writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext()); while (writers.Count > 0) { yield return null; writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext()); } } private void Broadcast(long target, params ConfigEntryBase[] configs) { if (!IsLocked || isServer) { ZPackage package = ConfigsToPackage(configs); ZNet instance = ZNet.instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package)); } } } private void Broadcast(long target, params CustomSyncedValueBase[] customValues) { if (!IsLocked || isServer) { ZPackage package = ConfigsToPackage(null, customValues); ZNet instance = ZNet.instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package)); } } } private static OwnConfigEntryBase? configData(ConfigEntryBase config) { return config.Description.Tags?.OfType<OwnConfigEntryBase>().SingleOrDefault(); } public static SyncedConfigEntry<T>? ConfigData<T>(ConfigEntry<T> config) { return ((ConfigEntryBase)config).Description.Tags?.OfType<SyncedConfigEntry<T>>().SingleOrDefault(); } private static T configAttribute<T>(ConfigEntryBase config) { return config.Description.Tags.OfType<T>().First(); } private static Type configType(ConfigEntryBase config) { return configType(config.SettingType); } private static Type configType(Type type) { return type.IsEnum ? Enum.GetUnderlyingType(type) : type; } private static ZPackage ConfigsToPackage(IEnumerable<ConfigEntryBase>? configs = null, IEnumerable<CustomSyncedValueBase>? customValues = null, IEnumerable<PackageEntry>? packageEntries = null, bool partial = true) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown List<ConfigEntryBase> list = configs?.Where((ConfigEntryBase config) => configData(config).SynchronizedConfig).ToList() ?? new List<ConfigEntryBase>(); List<CustomSyncedValueBase> list2 = customValues?.ToList() ?? new List<CustomSyncedValueBase>(); ZPackage val = new ZPackage(); val.Write((byte)(partial ? 1 : 0)); val.Write(list.Count + list2.Count + (packageEntries?.Count() ?? 0)); foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>()) { AddEntryToPackage(val, item); } foreach (CustomSyncedValueBase item2 in list2) { AddEntryToPackage(val, new PackageEntry { section = "Internal", key = item2.Identifier, type = item2.Type, value = item2.BoxedValue }); } foreach (ConfigEntryBase item3 in list) { AddEntryToPackage(val, new PackageEntry { section = item3.Definition.Section, key = item3.Definition.Key, type = configType(item3), value = item3.BoxedValue }); } return val; } private static void AddEntryToPackage(ZPackage package, PackageEntry entry) { package.Write(entry.section); package.Write(entry.key); package.Write((entry.value == null) ? "" : GetZPackageTypeString(entry.type)); AddValueToZPackage(package, entry.value); } private static string GetZPackageTypeString(Type type) { return type.AssemblyQualifiedName; } private static void AddValueToZPackage(ZPackage package, object? value) { Type type = value?.GetType(); if (value is Enum) { value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture); } else { if (value is ICollection collection) { package.Write(collection.Count); { foreach (object item in collection) { AddValueToZPackage(package, item); } return; } } if ((object)type != null && type.IsValueType && !type.IsPrimitive) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); package.Write(fields.Length); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { package.Write(GetZPackageTypeString(fieldInfo.FieldType)); AddValueToZPackage(package, fieldInfo.GetValue(value)); } return; } } ZRpc.Serialize(new object[1] { value }, ref package); } private static object ReadValueWithTypeFromZPackage(ZPackage package, Type type) { if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); int num = package.ReadInt(); if (num != fields.Length) { throw new InvalidDeserializationTypeException { received = $"(field count: {num})", expected = $"(field count: {fields.Length})" }; } object uninitializedObject = FormatterServices.GetUninitializedObject(type); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { string text = package.ReadString(); if (text != GetZPackageTypeString(fieldInfo.FieldType)) { throw new InvalidDeserializationTypeException { received = text, expected = GetZPackageTypeString(fieldInfo.FieldType), field = fieldInfo.Name }; } fieldInfo.SetValue(uninitializedObject, ReadValueWithTypeFromZPackage(package, fieldInfo.FieldType)); } return uninitializedObject; } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >)) { int num2 = package.ReadInt(); IDictionary dictionary = (IDictionary)Activator.CreateInstance(type); Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments); FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic); for (int j = 0; j < num2; j++) { object obj = ReadValueWithTypeFromZPackage(package, type2); dictionary.Add(field.GetValue(obj), field2.GetValue(obj)); } return dictionary; } if (type != typeof(List<string>) && type.IsGenericType) { Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]); if ((object)type3 != null && type3.IsAssignableFrom(type)) { int num3 = package.ReadInt(); object obj2 = Activator.CreateInstance(type); MethodInfo method = type3.GetMethod("Add"); for (int k = 0; k < num3; k++) { method.Invoke(obj2, new object[1] { ReadValueWithTypeFromZPackage(package, type.GenericTypeArguments[0]) }); } return obj2; } } ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo)); AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type); List<object> source = new List<object>(); ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source); return source.First(); } } [PublicAPI] [HarmonyPatch] internal class VersionCheck { private static readonly HashSet<VersionCheck> versionChecks; private static readonly Dictionary<string, string> notProcessedNames; public string Name; private string? displayName; private string? currentVersion; private string? minimumRequiredVersion; public bool ModRequired = true; private string? ReceivedCurrentVersion; private string? ReceivedMinimumRequiredVersion; private readonly List<ZRpc> ValidatedClients = new List<ZRpc>(); private ConfigSync? ConfigSync; public string DisplayName { get { return displayName ?? Name; } set { displayName = value; } } public string CurrentVersion { get { return currentVersion ?? "0.0.0"; } set { currentVersion = value; } } public string MinimumRequiredVersion { get { return minimumRequiredVersion ?? (ModRequired ? CurrentVersion : "0.0.0"); } set { minimumRequiredVersion = value; } } private static void PatchServerSync() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown Patches patchInfo = PatchProcessor.GetPatchInfo((MethodBase)AccessTools.DeclaredMethod(typeof(ZNet), "Awake", (Type[])null, (Type[])null)); if (patchInfo != null && patchInfo.Postfixes.Count((Patch p) => p.PatchMethod.DeclaringType == typeof(ConfigSync.RegisterRPCPatch)) > 0) { return; } Harmony val = new Harmony("org.bepinex.helpers.ServerSync"); foreach (Type item in from t in typeof(ConfigSync).GetNestedTypes(BindingFlags.NonPublic).Concat(new Type[1] { typeof(VersionCheck) }) where t.IsClass select t) { val.PatchAll(item); } } static VersionCheck() { versionChecks = new HashSet<VersionCheck>(); notProcessedNames = new Dictionary<string, string>(); typeof(ThreadingHelper).GetMethod("StartSyncInvoke").Invoke(ThreadingHelper.Instance, new object[1] { new Action(PatchServerSync) }); } public VersionCheck(string name) { Name = name; ModRequired = true; versionChecks.Add(this); } public VersionCheck(ConfigSync configSync) { ConfigSync = configSync; Name = ConfigSync.Name; versionChecks.Add(this); } public void Initialize() { ReceivedCurrentVersion = null; ReceivedMinimumRequiredVersion = null; if (ConfigSync != null) { Name = ConfigSync.Name; DisplayName = ConfigSync.DisplayName; CurrentVersion = ConfigSync.CurrentVersion; MinimumRequiredVersion = ConfigSync.MinimumRequiredVersion; ModRequired = ConfigSync.ModRequired; } } private bool IsVersionOk() { if (ReceivedMinimumRequiredVersion == null || ReceivedCurrentVersion == null) { return !ModRequired; } bool flag = new Version(CurrentVersion) >= new Version(ReceivedMinimumRequiredVersion); bool flag2 = new Version(ReceivedCurrentVersion) >= new Version(MinimumRequiredVersion); return flag && flag2; } private string ErrorClient() { if (ReceivedMinimumRequiredVersion == null) { return DisplayName + " is not installed on the server."; } return (new Version(CurrentVersion) >= new Version(ReceivedMinimumRequiredVersion)) ? (DisplayName + " may not be higher than version " + ReceivedCurrentVersion + ". You have version " + CurrentVersion + ".") : (DisplayName + " needs to be at least version " + ReceivedMinimumRequiredVersion + ". You have version " + CurrentVersion + "."); } private string ErrorServer(ZRpc rpc) { return "Disconnect: The client (" + rpc.GetSocket().GetHostName() + ") doesn't have the correct " + DisplayName + " version " + MinimumRequiredVersion; } private string Error(ZRpc? rpc = null) { return (rpc == null) ? ErrorClient() : ErrorServer(rpc); } private static VersionCheck[] GetFailedClient() { return versionChecks.Where((VersionCheck check) => !check.IsVersionOk()).ToArray(); } private static VersionCheck[] GetFailedServer(ZRpc rpc) { ZRpc rpc2 = rpc; return versionChecks.Where((VersionCheck check) => check.ModRequired && !check.ValidatedClients.Contains(rpc2)).ToArray(); } private static void Logout() { Game.instance.Logout(true, true); AccessTools.DeclaredField(typeof(ZNet), "m_connectionStatus").SetValue(null, (object)(ConnectionStatus)3); } private static void DisconnectClient(ZRpc rpc) { rpc.Invoke("Error", new object[1] { 3 }); } private static void CheckVersion(ZRpc rpc, ZPackage pkg) { CheckVersion(rpc, pkg, null); } private static void CheckVersion(ZRpc rpc, ZPackage pkg, Action<ZRpc, ZPackage>? original) { string text = pkg.ReadString(); string text2 = pkg.ReadString(); string text3 = pkg.ReadString(); bool flag = false; foreach (VersionCheck versionCheck in versionChecks) { if (!(text != versionCheck.Name)) { Debug.Log((object)("Received " + versionCheck.DisplayName + " version " + text3 + " and minimum version " + text2 + " from the " + (ZNet.instance.IsServer() ? "client" : "server") + ".")); versionCheck.ReceivedMinimumRequiredVersion = text2; versionCheck.ReceivedCurrentVersion = text3; if (ZNet.instance.IsServer() && versionCheck.IsVersionOk()) { versionCheck.ValidatedClients.Add(rpc); } flag = true; } } if (flag) { return; } pkg.SetPos(0); if (original != null) { original(rpc, pkg); if (pkg.GetPos() == 0) { notProcessedNames.Add(text, text3); } } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyPrefix] private static bool RPC_PeerInfo(ZRpc rpc, ZNet __instance) { VersionCheck[] array = (__instance.IsServer() ? GetFailedServer(rpc) : GetFailedClient()); if (array.Length == 0) { return true; } VersionCheck[] array2 = array; foreach (VersionCheck versionCheck in array2) { Debug.LogWarning((object)versionCheck.Error(rpc)); } if (__instance.IsServer()) { DisconnectClient(rpc); } else { Logout(); } return false; } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] [HarmonyPrefix] private static void RegisterAndCheckVersion(ZNetPeer peer, ZNet __instance) { //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown notProcessedNames.Clear(); IDictionary dictionary = (IDictionary)typeof(ZRpc).GetField("m_functions", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(peer.m_rpc); if (dictionary.Contains(StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck"))) { object obj = dictionary[StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck")]; Action<ZRpc, ZPackage> action = (Action<ZRpc, ZPackage>)obj.GetType().GetField("m_action", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj); peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage pkg) { CheckVersion(rpc, pkg, action); }); } else { peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)CheckVersion); } foreach (VersionCheck versionCheck in versionChecks) { versionCheck.Initialize(); if (versionCheck.ModRequired || __instance.IsServer()) { Debug.Log((object)("Sending " + versionCheck.DisplayName + " version " + versionCheck.CurrentVersion + " and minimum version " + versionCheck.MinimumRequiredVersion + " to the " + (__instance.IsServer() ? "client" : "server") + ".")); ZPackage val = new ZPackage(); val.Write(versionCheck.Name); val.Write(versionCheck.MinimumRequiredVersion); val.Write(versionCheck.CurrentVersion); peer.m_rpc.Invoke("ServerSync VersionCheck", new object[1] { val }); } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] [HarmonyPrefix] private static void RemoveDisconnected(ZNetPeer peer, ZNet __instance) { if (!__instance.IsServer()) { return; } foreach (VersionCheck versionCheck in versionChecks) { versionCheck.ValidatedClients.Remove(peer.m_rpc); } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] [HarmonyPostfix] private static void ShowConnectionError(FejdStartup __instance) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) if (!__instance.m_connectionFailedPanel.activeSelf || (int)ZNet.GetConnectionStatus() != 3) { return; } bool flag = false; VersionCheck[] failedClient = GetFailedClient(); if (failedClient.Length != 0) { string text = string.Join("\n", failedClient.Select((VersionCheck check) => check.Error())); TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + text; flag = true; } foreach (KeyValuePair<string, string> item in notProcessedNames.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> kv) => kv.Key)) { if (!__instance.m_connectionFailedError.text.Contains(item.Key)) { TMP_Text connectionFailedError2 = __instance.m_connectionFailedError; connectionFailedError2.text = connectionFailedError2.text + "\nServer expects you to have " + item.Key + " (Version: " + item.Value + ") installed."; flag = true; } } if (flag) { RectTransform component = ((Component)__instance.m_connectionFailedPanel.transform.Find("Image")).GetComponent<RectTransform>(); Vector2 sizeDelta = component.sizeDelta; sizeDelta.x = 675f; component.sizeDelta = sizeDelta; __instance.m_connectionFailedError.ForceMeshUpdate(false, false); float num = __instance.m_connectionFailedError.renderedHeight + 105f; RectTransform component2 = ((Component)((Component)component).transform.Find("ButtonOk")).GetComponent<RectTransform>(); component2.anchoredPosition = new Vector2(component2.anchoredPosition.x, component2.anchoredPosition.y - (num - component.sizeDelta.y) / 2f); sizeDelta = component.sizeDelta; sizeDelta.y = num; component.sizeDelta = sizeDelta; } } } }
Plugins/itemdrawers.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using AuthoritativeConfig; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using SimpleJSON; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.Serialization; using UnityEngine.UI; using itemdrawers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] public class AssetManager { public static AssetBundle AssetBundle; public static Object[] AssetBundleObjects; public static UnityAction<ZNetScene> OnSceneAwake; public static UnityAction<ObjectDB> OnObjectDBAwake; public static void Create(Harmony harmony, string assetBundle) { harmony.PatchAll(typeof(AssetManager)); LoadAssetsFromBundle(assetBundle); } public static void LoadAssetsFromBundle(string bundleName) { AssetBundle = GetAssetBundleFromResources(bundleName); AssetBundleObjects = AssetBundle.LoadAllAssets(); } public static AssetBundle GetAssetBundleFromResources(string fileName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(fileName)); using Stream stream = executingAssembly.GetManifestResourceStream(name); return AssetBundle.LoadFromStream(stream); } public static IEnumerable<T> GetGameObjects<T>() where T : Component { Object[] assetBundleObjects = AssetBundleObjects; foreach (Object obj in assetBundleObjects) { GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null); if (val != null) { T component = val.GetComponent<T>(); if (component != null) { yield return component; } } } } public static T GetGameObject<T>(string id) where T : Component { Object[] assetBundleObjects = AssetBundleObjects; foreach (Object obj in assetBundleObjects) { GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null); if (val != null && ((Object)val).name == id) { T component = val.GetComponent<T>(); if (component != null) { return component; } } } return default(T); } public static GameObject GetGameObject(string id) { Object[] assetBundleObjects = AssetBundleObjects; foreach (Object obj in assetBundleObjects) { GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null); if (val != null && ((Object)val).name == id) { return val; } } return null; } public static IEnumerable<T> GetAssets<T>() { Object[] assetBundleObjects = AssetBundleObjects; foreach (Object val in assetBundleObjects) { if (val is T) { yield return (T)(object)((val is T) ? val : null); } } } public static T GetAsset<T>(string name) { Object[] assetBundleObjects = AssetBundleObjects; foreach (Object val in assetBundleObjects) { if (val.name == name && val is T) { return (T)(object)((val is T) ? val : null); } } return default(T); } public static T LoadAsset<T>(string name) where T : Object { return AssetBundle.LoadAsset<T>(name); } public static void LoadItems(ObjectDB db) { IEnumerable<ItemDrop> gameObjects = AssetManager.GetGameObjects<ItemDrop>(); db.m_items.AddRange(gameObjects.Select((ItemDrop x) => ((Component)x).gameObject)); db.UpdateItemHashes(); } public static void RegisterRecipes(ObjectDB db) { db.m_recipes.AddRange(from x in GetAssets<SkyheimRecipe>() select x.Convert()); db.m_recipes.AddRange(GetAssets<Recipe>()); } public static void RegisterStatusEffects(ObjectDB db) { db.m_StatusEffects.AddRange(GetAssets<StatusEffect>()); } public static void RegisterPieces() { foreach (SkyheimPieceData gameObject in AssetManager.GetGameObjects<SkyheimPieceData>()) { ItemDrop tool = gameObject.Tool; if (tool != null) { List<GameObject> pieces = tool.m_itemData.m_shared.m_buildPieces.m_pieces; if (!pieces.Contains(((Component)gameObject).gameObject)) { gameObject.Convert(); pieces.Add(((Component)gameObject).gameObject); } } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] [HarmonyPostfix] public static void ObjectDB_Awake_Postfix(ObjectDB __instance) { if ((Object)(object)ZNetScene.instance != (Object)null) { OnObjectDBAwake?.Invoke(__instance); LoadItems(__instance); RegisterRecipes(__instance); RegisterStatusEffects(__instance); } } [HarmonyPatch(typeof(FejdStartup), "SetupObjectDB")] [HarmonyPostfix] public static void FejdStartup_SetupObjectDB_Postfix(FejdStartup __instance) { LoadItems(((Component)__instance).GetComponent<ObjectDB>()); } [HarmonyPatch(typeof(ZNetScene), "Awake")] [HarmonyPostfix] public static void ZNetScene_Awake_Postfix(ZNetScene __instance) { foreach (ZNetView gameObject in AssetManager.GetGameObjects<ZNetView>()) { __instance.m_namedPrefabs.Add(StringExtensionMethods.GetStableHashCode(((Object)gameObject).name), ((Component)gameObject).gameObject); } RegisterPieces(); OnSceneAwake?.Invoke(__instance); } } public class AssetType : PropertyAttribute { public Type Type { get; protected set; } public AssetType(Type type) { Type = type; } } public static class CommonUtils { [Serializable] public class SerializableWrapper<T> { public T Value; public SerializableWrapper(T v) { Value = v; } } public struct DistanceSort : IComparer<Collider> { private Vector3 _target; public DistanceSort(Vector3 target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) _target = target; } public int Compare(Collider a, Collider b) { //IL_0006: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)a).transform.position; Vector3 position2 = ((Component)b).transform.position; return Vector3.Distance(position, _target).CompareTo(Vector3.Distance(position2, _target)); } } public static long PlayerID => Game.instance.GetPlayerProfile().GetPlayerID(); [Conditional("DEBUG")] public static void Log(string str) { Debug.Log((object)str); } [Conditional("DEBUG")] public static void LogFields(object obj) { FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo obj2 in fields) { _ = obj2.Name; obj2.GetValue(obj); } } public static T ConvertPrefabReference<T>(string prefabReference) where T : Component { if (Object.op_Implicit((Object)(object)ZNetScene.instance) && !string.IsNullOrEmpty(prefabReference)) { GameObject prefab = ZNetScene.instance.GetPrefab(prefabReference); if ((Object)(object)prefab != (Object)null) { return prefab.GetComponent<T>(); } } return default(T); } public static GameObject ConvertPrefabReference(string prefabReference) { if (Object.op_Implicit((Object)(object)ZNetScene.instance) && !string.IsNullOrEmpty(prefabReference)) { return ZNetScene.instance.GetPrefab(prefabReference); } return null; } public static T GetItemComponent<T>(ItemData item) where T : Component { if (item == null || !Object.op_Implicit((Object)(object)item.m_dropPrefab)) { return default(T); } return item.m_dropPrefab.GetComponent<T>(); } public static T Clone<T>(T obj) { return (T)obj.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(obj, null); } public static T Get<T>(this IDictionary dict, string key, T defaultValue = default(T)) { if (dict.Contains(key)) { return (T)Convert.ChangeType(dict[key], typeof(T)); } return defaultValue; } public static JSONNode ToJSON<T>(T obj) { Type type = obj.GetType(); if (obj is IList) { JSONArray jSONArray = new JSONArray(); { foreach (object item in obj as IList) { jSONArray.Add(ToJSON(item)); } return jSONArray; } } if (type.IsClass && !(obj is string)) { Type type2 = obj.GetType(); JSONObject jSONObject = new JSONObject(); FieldInfo[] fields = type2.GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { jSONObject.Add(fieldInfo.Name, ToJSON(fieldInfo.GetValue(obj))); } return jSONObject; } return (JSONNode)typeof(JSONNode).GetMethod("op_Implicit", new Type[1] { obj.GetType() }).Invoke(null, new object[1] { obj }); } } public class NameAttribute : PropertyAttribute { public string Name { get; private set; } public NameAttribute(string name) { Name = name; } } public class PrefabReferenceType : PropertyAttribute { public Type ComponentType { get; protected set; } public PrefabReferenceType(Type componentType) { ComponentType = componentType; } } public class SkyheimPieceData : MonoBehaviour, ISerializationCallbackReceiver { [Header("Requirements")] [SerializeField] [PrefabReferenceType(typeof(CraftingStation))] [FormerlySerializedAs("m_craftingStation")] private string _craftingStation; [SerializeField] [PrefabReferenceType(typeof(ItemDrop))] [FormerlySerializedAs("m_craftingTool")] private string _craftingTool; [SerializeField] [PrefabReferenceType(typeof(Piece))] [FormerlySerializedAs("m_template")] private string _template; [SerializeField] [FormerlySerializedAs("m_resources")] private List<SkyheimRecipe.SkyheimRequirement> _resources; [SerializeField] [HideInInspector] [FormerlySerializedAs("m_resources_internal")] private string _resourcesInternal; public ItemDrop Tool => CommonUtils.ConvertPrefabReference<ItemDrop>(_craftingTool); public void Convert() { RuntimeDeserialize(); Piece component = ((Component)this).GetComponent<Piece>(); component.m_craftingStation = CommonUtils.ConvertPrefabReference<CraftingStation>(_craftingStation); component.m_resources = ((IEnumerable<SkyheimRecipe.SkyheimRequirement>)_resources).Select((Func<SkyheimRecipe.SkyheimRequirement, Requirement>)((SkyheimRecipe.SkyheimRequirement x) => x)).ToArray(); Piece val = (string.IsNullOrEmpty(_template) ? null : CommonUtils.ConvertPrefabReference<Piece>(_template)); if (!((Object)(object)val != (Object)null)) { return; } component.m_placeEffect = val.m_placeEffect; WearNTear component2 = ((Component)component).GetComponent<WearNTear>(); if (Object.op_Implicit((Object)(object)component2)) { WearNTear component3 = ((Component)val).GetComponent<WearNTear>(); if (component3 != null) { component2.m_hitEffect = component3.m_hitEffect; component2.m_destroyedEffect = component3.m_destroyedEffect; component2.m_switchEffect = component3.m_switchEffect; } } } public void RuntimeDeserialize() { _resources = new List<SkyheimRecipe.SkyheimRequirement>(); JSONNode.Enumerator enumerator = JSONNode.Parse(_resourcesInternal).AsArray.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair<string, JSONNode> current = enumerator.Current; _resources.Add(new SkyheimRecipe.SkyheimRequirement(current.Value)); } } public void OnBeforeSerialize() { JSONNode jSONNode = CommonUtils.ToJSON(_resources); _resourcesInternal = jSONNode.ToString(); } public void OnAfterDeserialize() { } } [CreateAssetMenu(menuName = "Skyheim/Recipe")] public class SkyheimRecipe : ScriptableObject, ISerializationCallbackReceiver { [Serializable] public class SkyheimRequirement { [PrefabReferenceType(typeof(ItemDrop))] [FormerlySerializedAs("ResItem")] public string ResourceItem; [FormerlySerializedAs("m_amount")] public int Amount = 1; [FormerlySerializedAs("m_amountPerLevel")] public int AmountPerLevel = 1; [FormerlySerializedAs("m_recover")] public bool Recover = true; public SkyheimRequirement() { } public SkyheimRequirement(JSONNode j) { ResourceItem = j["ResourceItem"]; Amount = j["Amount"]; AmountPerLevel = j["AmountPerLevel"]; Recover = j["Recover"]; } public static implicit operator Requirement(SkyheimRequirement r) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0022: 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) //IL_003b: Expected O, but got Unknown return new Requirement { m_resItem = CommonUtils.ConvertPrefabReference<ItemDrop>(r.ResourceItem), m_amount = r.Amount, m_amountPerLevel = r.AmountPerLevel, m_recover = r.Recover }; } } [SerializeField] [PrefabReferenceType(typeof(ItemDrop))] [FormerlySerializedAs("m_item")] private string _item; [SerializeField] [FormerlySerializedAs("m_amount")] private int _amount = 1; [SerializeField] [FormerlySerializedAs("m_enabled")] private bool _enabled = true; [Header("Requirements")] [SerializeField] [PrefabReferenceType(typeof(CraftingStation))] [FormerlySerializedAs("m_craftingStation")] private string _craftingStation; [SerializeField] [PrefabReferenceType(typeof(CraftingStation))] [FormerlySerializedAs("m_repairStation")] private string _repairStation; [SerializeField] [FormerlySerializedAs("m_minStationLevel")] private int _minStationLevel = 1; [SerializeField] [FormerlySerializedAs("m_resources")] private List<SkyheimRequirement> _resources; [SerializeField] [HideInInspector] [FormerlySerializedAs("m_resources_internal")] private string _resourcesInternal; public Recipe Convert() { RuntimeDeserialize(); Recipe obj = ScriptableObject.CreateInstance<Recipe>(); ((Object)obj).name = ((Object)this).name; obj.m_item = CommonUtils.ConvertPrefabReference<ItemDrop>(_item); obj.m_craftingStation = CommonUtils.ConvertPrefabReference<CraftingStation>(_craftingStation); obj.m_repairStation = CommonUtils.ConvertPrefabReference<CraftingStation>(_repairStation); obj.m_resources = ((IEnumerable<SkyheimRequirement>)_resources).Select((Func<SkyheimRequirement, Requirement>)((SkyheimRequirement x) => x)).ToArray(); obj.m_amount = _amount; obj.m_enabled = _enabled; obj.m_minStationLevel = _minStationLevel; return obj; } public void RuntimeDeserialize() { JSONNode jSONNode = JSONNode.Parse(_resourcesInternal); _resources = new List<SkyheimRequirement>(); JSONNode.Enumerator enumerator = jSONNode.AsArray.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair<string, JSONNode> current = enumerator.Current; _resources.Add(new SkyheimRequirement(current.Value)); } } public void OnBeforeSerialize() { JSONNode jSONNode = CommonUtils.ToJSON(_resources); _resourcesInternal = jSONNode.ToString(); } public void OnAfterDeserialize() { } } public class DrawerContainer : Container, Hoverable, Interactable { public Image _image; public Text _text; private const int CurrentVersion = 0; private uint? _lastRevision; private ZNetView _nview; private Piece _piece; private ItemData _item; private int _quantity; private bool _loading; private int _pickupDelay = 10; private int _pickupMask; public void Awake_Drawer() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown _pickupMask = LayerMask.GetMask(new string[1] { "item" }); _nview = ((Component)this).GetComponent<ZNetView>(); _piece = ((Component)this).GetComponent<Piece>(); ((Component)_image).gameObject.SetActive(false); if ((Object)(object)_nview != (Object)null && _nview.GetZDO() != null) { ((Object)this).name = $"Container_{_nview.GetZDO().m_uid}"; base.m_name = "piece_chest_drawer"; base.m_nview = _nview; base.m_inventory = new Inventory(((Object)this).name, (Sprite)null, 1, 1); base.m_inventory.m_onChanged = (Action)Delegate.Combine(base.m_inventory.m_onChanged, new Action(OnInventoryChanged)); _nview.Register<int>("Drop", (Action<long, int>)RPC_Drop); _nview.Register<ZDOID>("DropResponse", (Action<long, ZDOID>)RPC_DropResponse); _nview.Register("Clear", (Action<long>)RPC_Clear); _nview.Register<string, int>("AddItem", (Action<long, string, int>)RPC_AddItem); _nview.Register<string, int>("AddItemResponse", (Action<long, string, int>)RPC_AddItemResponse); Load(); } WearNTear component = ((Component)this).GetComponent<WearNTear>(); if (component != null) { component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(base.OnDestroyed)); } ((MonoBehaviour)this).InvokeRepeating("CheckForChanges", 0f, 1f); } public void SetFontColor(Color fontColor, Color outlineColor, bool outlineEnabled) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) ((Graphic)_text).color = fontColor; Outline component = ((Component)_text).GetComponent<Outline>(); ((Behaviour)component).enabled = outlineEnabled; if (((Behaviour)component).enabled) { ((Shadow)component).effectColor = outlineColor; } } private void RetreiveItems() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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 (!ItemDrawerPlugin.RetreiveEnabled || _item == null || !Object.op_Implicit((Object)(object)_nview) || !_nview.IsOwner()) { return; } if (_pickupDelay > 0) { _pickupDelay--; return; } Collider[] array = Physics.OverlapSphere(((Component)this).transform.position + Vector3.up, ItemDrawerPlugin.RetreiveRadius, _pickupMask); foreach (Collider val in array) { if (!Object.op_Implicit((Object)(object)val.attachedRigidbody)) { continue; } ItemDrop component = ((Component)val.attachedRigidbody).GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || (Object)(object)component.m_itemData.m_dropPrefab != (Object)(object)_item.m_dropPrefab) { continue; } ZNetView component2 = ((Component)component).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component2) && component2.IsValid()) { if (!component.CanPickup(true)) { component.RequestOwn(); continue; } AddItem(((Object)component.m_itemData.m_dropPrefab).name, component.m_itemData.m_stack); ZNetScene.instance.Destroy(((Component)component).gameObject); } } } private void CheckForChanges() { if (Object.op_Implicit((Object)(object)_nview) && _nview.IsValid()) { Load(); RetreiveItems(); UpdateVisuals(); } } public string GetHoverName() { if (!Object.op_Implicit((Object)(object)_piece)) { return string.Empty; } return Localization.instance.Localize(_piece.m_name); } public string GetHoverText() { string text = ((_item != null) ? $"<color=#00FFFF>{_item.m_shared.m_name}</color> x {_quantity}" : "$piece_container_empty"); if (!ZInput.IsGamepadActive()) { string boundKeyString = ZInput.instance.GetBoundKeyString("drawer_mod_deposit_all", false); if (_quantity > 0) { text += "\n[<color=yellow><b>$KEY_Use</b></color>] Take Stack"; string boundKeyString2 = ZInput.instance.GetBoundKeyString("drawer_mod_withdraw_one", false); text = text + "\n[<color=yellow><b>" + boundKeyString2 + "+$KEY_Use</b></color>] Take One"; } else { string boundKeyString3 = ZInput.instance.GetBoundKeyString("drawer_mod_clear", false); text = text + "\n[<color=yellow><b>" + boundKeyString3 + "+$KEY_Use</b></color>] Clear Item"; } text = text + "\n[<color=yellow><b>" + boundKeyString + "+$KEY_Use</b></color>] Deposit All"; } return Localization.instance.Localize(text); } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (_item == null || (Object)(object)user != (Object)(object)Player.m_localPlayer || !PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { return false; } if (!ZInput.IsGamepadActive()) { return OnKeyboardInteract(Player.m_localPlayer); } return OnGamepadInteract(Player.m_localPlayer); } private bool OnGamepadInteract(Player player) { bool blocking = ((Character)player).m_blocking; bool crouchToggled = player.m_crouchToggled; return ProcessInputInternal(player, blocking, crouchToggled); } private bool OnKeyboardInteract(Player player) { bool button = ZInput.GetButton("drawer_mod_deposit_all"); bool button2 = ZInput.GetButton((_quantity > 0) ? "drawer_mod_withdraw_one" : "drawer_mod_clear"); return ProcessInputInternal(player, button, button2); } private bool ProcessInputInternal(Player player, bool mod0, bool mod1) { if (mod0) { return UseItem((Humanoid)(object)player, _item); } if (mod1 && _quantity <= 0) { _nview.InvokeRPC("Clear", Array.Empty<object>()); } else if (_quantity > 0) { _nview.InvokeRPC("Drop", new object[1] { mod1 ? 1 : _item.m_shared.m_maxStackSize }); } return true; } public bool UseItem(Humanoid user, ItemData item) { if (item.m_shared.m_maxStackSize <= 1) { return false; } if (_item == null || (Object)(object)_item.m_dropPrefab == (Object)(object)item.m_dropPrefab) { int num = user.GetInventory().CountItems(item.m_shared.m_name, -1, true); if (num > 0) { _nview.InvokeRPC("AddItem", new object[2] { ((Object)item.m_dropPrefab).name, num }); return true; } } return false; } private void UpdateInventory() { if (base.m_inventory.m_inventory.Count > 0) { ItemData val = base.m_inventory.m_inventory[0]; if (val.m_shared.m_name == _item.m_shared.m_name) { val.m_stack = _quantity; val.m_shared.m_maxStackSize = ItemDrawerPlugin.MaxItems; } else { _addItem(); } } else { _addItem(); } void _addItem() { base.m_inventory.m_inventory.Clear(); ItemData val2 = _item.Clone(); val2.m_stack = _quantity; val2.m_shared = CommonUtils.Clone<SharedData>(val2.m_shared); val2.m_shared.m_maxStackSize = ItemDrawerPlugin.MaxItems; base.m_inventory.m_inventory.Add(val2); } } private ItemDrop Drop(int quantity) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_009a: Unknown result type (might be due to invalid IL or missing references) if (_quantity > 0) { GameObject dropPrefab = _item.m_dropPrefab; int num = Mathf.Min(quantity, _quantity); _quantity -= num; _pickupDelay = 5; UpdateInventory(); Vector3 val = ((Component)this).transform.position + ((Component)this).transform.forward * -0.5f; GameObject obj = Object.Instantiate<GameObject>(dropPrefab, val, Quaternion.identity); obj.GetComponent<Rigidbody>().velocity = Vector3.up * 4f + ((Component)this).transform.forward * 4f; ItemDrop component = obj.GetComponent<ItemDrop>(); component.SetStack(num); return component; } return null; } public int AddItem(string name, int stack) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name); if ((Object)(object)itemPrefab == (Object)null) { ZLog.Log((object)("Failed to find item prefab " + name)); return 0; } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { ZLog.Log((object)("Invalid item " + name)); return 0; } if (_item != null && (Object)(object)_item.m_dropPrefab != (Object)(object)itemPrefab) { ZLog.Log((object)("Cannot add to container " + name)); return 0; } stack = Math.Min(stack, ItemDrawerPlugin.MaxItems - _quantity); _item = component.m_itemData; _item.m_dropPrefab = itemPrefab; _item.m_gridPos = Vector2i.zero; _quantity += stack; UpdateInventory(); OnContainerChanged(); return stack; } private void OnContainerChanged() { if (!_loading && _nview.IsOwner()) { Save(); } } private void OnInventoryChanged() { if (base.m_inventory.m_inventory.Count > 0) { ItemData val = base.m_inventory.m_inventory[0]; int num = _quantity - val.m_stack; _quantity = Math.Max(0, _quantity - num); } else { _quantity = 0; } OnContainerChanged(); UpdateVisuals(); } private void RPC_AddItem(long playerId, string prefabName, int quantity) { if (_nview.IsOwner()) { int num = AddItem(prefabName, quantity); if (num > 0) { _nview.InvokeRPC(playerId, "AddItemResponse", new object[2] { prefabName, num }); } } } private void RPC_AddItemResponse(long _, string prefabName, int quantity) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && quantity > 0) { ItemDrop component = ObjectDB.instance.GetItemPrefab(prefabName).GetComponent<ItemDrop>(); if (component != null) { string name = component.m_itemData.m_shared.m_name; ((Humanoid)Player.m_localPlayer).GetInventory().RemoveItem(name, quantity, -1, true); } } } private void RPC_Clear(long _) { if (_nview.IsOwner() && _item != null) { Clear(); OnContainerChanged(); } } private void RPC_Drop(long playerId, int quantity) { //IL_0031: 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_004b: Unknown result type (might be due to invalid IL or missing references) if (_nview.IsOwner() && _item != null) { ItemDrop val = Drop(quantity); if (val != null) { OnContainerChanged(); ZDOID uid = val.m_nview.GetZDO().m_uid; _nview.InvokeRPC(playerId, "DropResponse", new object[1] { uid }); } } } private void RPC_DropResponse(long _, ZDOID drop) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) GameObject val = ZNetScene.instance.FindInstance(drop); if ((Object)(object)val != (Object)null) { ItemDrop component = val.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && ((Humanoid)Player.m_localPlayer).GetInventory().AddItem(component.m_itemData)) { ((Character)Player.m_localPlayer).ShowPickupMessage(component.m_itemData, component.m_itemData.m_stack); ZNetScene.instance.Destroy(val); } } } private void UpdateVisuals() { if ((Object)(object)_image != (Object)null) { bool flag = _item != null && _item.m_shared.m_icons.Count() > 0; ((Component)_image).gameObject.SetActive(flag); if (flag) { _image.sprite = _item.m_shared.m_icons[0]; } } if ((Object)(object)_text != (Object)null) { _text.text = ((_quantity > 0) ? _quantity.ToString() : string.Empty); } } private void Clear() { _quantity = 0; _item = null; base.m_inventory.m_inventory.Clear(); UpdateVisuals(); } private void Save() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(0); if (_item != null) { val.Write(((Object)(object)_item.m_dropPrefab == (Object)null) ? "" : ((Object)_item.m_dropPrefab).name); val.Write(_quantity); } else { val.Write(""); } string @base = val.GetBase64(); _nview.GetZDO().Set("items", @base); _lastRevision = _nview.GetZDO().DataRevision; ZDOMan.instance.ForceSendZDO(_nview.GetZDO().m_uid); } private void Load() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown if (_nview.GetZDO().DataRevision == _lastRevision && _lastRevision.HasValue) { return; } Clear(); string @string = _nview.GetZDO().GetString("items", ""); if (!string.IsNullOrEmpty(@string)) { ZPackage val = new ZPackage(@string); val.ReadInt(); string text = val.ReadString(); if (!string.IsNullOrEmpty(text)) { int stack = val.ReadInt(); _loading = true; AddItem(text, stack); _loading = false; _lastRevision = _nview.GetZDO().DataRevision; } } } public void OnDestroyed_Drawer() { if (_nview.IsOwner() && _item != null) { while (_quantity > 0 && Object.op_Implicit((Object)(object)Drop(_item.m_shared.m_maxStackSize))) { } } } } namespace itemdrawers { [BepInPlugin("mkz.itemdrawers", "Item Drawers", "0.5.7")] public class ItemDrawerPlugin : BaseUnityPlugin { public static ItemDrawerPlugin Instance; private Harmony _harmony; private static ConfigEntry<bool> _retreiveEnabled; private static ConfigEntry<float> _retreiveRadius; private static ConfigEntry<bool> _enabled; private static ConfigEntry<int> _maxItems; private static ConfigEntry<Color> _configFontColor; private static ConfigEntry<Color> _configOutlineColor; private static ConfigEntry<bool> _configOutlineEnabled; private static ConfigEntry<string> _configKeyDepositAll; private static ConfigEntry<string> _configKeyWithdrawOne; private static ConfigEntry<string> _configKeyClear; public const string KeyDepositAll = "drawer_mod_deposit_all"; public const string KeyWithdrawOne = "drawer_mod_withdraw_one"; public const string KeyClear = "drawer_mod_clear"; public static float RetreiveRadius => _retreiveRadius.Value; public static bool RetreiveEnabled => _retreiveEnabled.Value; public static bool Enabled => _enabled.Value; public static int MaxItems => _maxItems.Value; public static bool OutlineEnabled => _configOutlineEnabled.Value; public static Color OutlineColor => _configOutlineColor.Value; public static Color FontColor => _configFontColor.Value; private Config AuthoritativeConfig => Config.Instance; public void Awake() { Instance = this; _harmony = Harmony.CreateAndPatchAll(typeof(ItemDrawerPlugin), (string)null); AssetManager.Create(_harmony, "itemdrawers"); LoadConfig(); } public void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchAll((string)null); } } [HarmonyPatch(typeof(Container), "Awake")] [HarmonyPrefix] private static bool Container_Awake_Prefix(Container __instance) { if (__instance is DrawerContainer drawerContainer) { drawerContainer.Awake_Drawer(); return false; } return true; } [HarmonyPatch(typeof(Container), "OnDestroyed")] [HarmonyPrefix] private static bool Container_OnDestroyed_Prefix(Container __instance) { if (__instance is DrawerContainer drawerContainer) { drawerContainer.OnDestroyed_Drawer(); return false; } return true; } [HarmonyPatch(typeof(Container), "Save")] [HarmonyPrefix] private static bool Container_Save_Prefix(Container __instance) { return !(__instance is DrawerContainer); } [HarmonyPatch(typeof(Container), "Load")] [HarmonyPrefix] private static bool Container_Load_Prefix(Container __instance) { return !(__instance is DrawerContainer); } [HarmonyPatch(typeof(ZNetScene), "Awake")] [HarmonyPostfix] private static void ZNetScene_Awake_Postfix() { Instance.ApplyConfig(); } [HarmonyPatch(typeof(Player), "IsOverlappingOtherPiece")] [HarmonyPostfix] private static void Player_IsOverlappingOtherPiece_PostFix(string pieceName, ref bool __result) { if (pieceName == "piece_drawer") { __result = false; } } [HarmonyPatch(typeof(ZInput), "Load")] [HarmonyPostfix] private static void ZInput_Load_PostFix(ZInput __instance) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) __instance.AddButton("drawer_mod_deposit_all", parseKeyConfig(_configKeyDepositAll, (Key)51), 0f, 0f, true, false); __instance.AddButton("drawer_mod_withdraw_one", parseKeyConfig(_configKeyWithdrawOne, (Key)53), 0f, 0f, true, false); __instance.AddButton("drawer_mod_clear", parseKeyConfig(_configKeyClear, (Key)53), 0f, 0f, true, false); static Key parseKeyConfig(ConfigEntry<string> configString, Key @default) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (Enum.TryParse<Key>(configString.Value, out Key result)) { return result; } return @default; } } private void LoadConfig() { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Expected O, but got Unknown AuthoritativeConfig.Init((BaseUnityPlugin)(object)this, defaultBindServerAuthority: true); _enabled = AuthoritativeConfig.Bind("General", "Enabled", defaultValue: true, "Enable creation of Item Drawers"); _maxItems = AuthoritativeConfig.Bind("General", "MaxItems", 9999, "The maximum number of items that can be stored in a drawer"); _retreiveEnabled = AuthoritativeConfig.Bind("Item Retreival", "Enabled", defaultValue: true, "Drawers will retreive dropped items matching their item"); _retreiveRadius = AuthoritativeConfig.Bind("Item Retreival", "Radius", 5f, "The distance drawers will check for dropped items"); _configKeyDepositAll = AuthoritativeConfig.Bind("Hotkeys", "Deposit All", "LeftShift", "Hold while interacting to deposit all", false); _configKeyWithdrawOne = AuthoritativeConfig.Bind("Hotkeys", "Withdraw One", "LeftAlt", "Hold while interacting to withdraw one", false); _configKeyClear = AuthoritativeConfig.Bind("Hotkeys", "Clear", "LeftAlt", "Hold while interacting to clear contents (only if 0 quantity)", false); _configFontColor = AuthoritativeConfig.Bind<Color>("Font", "Color", new Color(1f, 0.5f, 0f), "Drawer font color", false); _configOutlineColor = AuthoritativeConfig.Bind<Color>("Font", "Outline Color", new Color(0f, 0f, 0f), "Drawer outline color", false); _configOutlineEnabled = AuthoritativeConfig.Bind("Font", "Outline Enabled", defaultValue: true, "Enabled font outline on drawers", false); AuthoritativeConfig.OnConfigReceived.AddListener(new UnityAction(ApplyConfig)); } private void ApplyConfig() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) Piece gameObject = AssetManager.GetGameObject<Piece>("piece_drawer"); if (gameObject != null) { gameObject.m_enabled = Enabled; DrawerContainer component = ((Component)gameObject).GetComponent<DrawerContainer>(); component._text.text = MaxItems.ToString(); component.SetFontColor(_configFontColor.Value, _configOutlineColor.Value, _configOutlineEnabled.Value); } } } } namespace SimpleJSON { public enum JSONNodeType { Array = 1, Object = 2, String = 3, Number = 4, NullValue = 5, Boolean = 6, None = 7, Custom = 255 } public enum JSONTextMode { Compact, Indent } public abstract class JSONNode { public struct Enumerator { private enum Type { None, Array, Object } private Type type; private Dictionary<string, JSONNode>.Enumerator m_Object; private List<JSONNode>.Enumerator m_Array; public bool IsValid => type != Type.None; public KeyValuePair<string, JSONNode> Current { get { if (type == Type.Array) { return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current); } if (type == Type.Object) { return m_Object.Current; } return new KeyValuePair<string, JSONNode>(string.Empty, null); } } public Enumerator(List<JSONNode>.Enumerator aArrayEnum) { type = Type.Array; m_Object = default(Dictionary<string, JSONNode>.Enumerator); m_Array = aArrayEnum; } public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) { type = Type.Object; m_Object = aDictEnum; m_Array = default(List<JSONNode>.Enumerator); } public bool MoveNext() { if (type == Type.Array) { return m_Array.MoveNext(); } if (type == Type.Object) { return m_Object.MoveNext(); } return false; } } public struct ValueEnumerator { private Enumerator m_Enumerator; public JSONNode Current => m_Enumerator.Current.Value; public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public ValueEnumerator GetEnumerator() { return this; } } public struct KeyEnumerator { private Enumerator m_Enumerator; public string Current => m_Enumerator.Current.Key; public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public KeyEnumerator GetEnumerator() { return this; } } public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IDisposable, IEnumerator, IEnumerable<KeyValuePair<string, JSONNode>>, IEnumerable { private JSONNode m_Node; private Enumerator m_Enumerator; public KeyValuePair<string, JSONNode> Current => m_Enumerator.Current; object IEnumerator.Current => m_Enumerator.Current; internal LinqEnumerator(JSONNode aNode) { m_Node = aNode; if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } public bool MoveNext() { return m_Enumerator.MoveNext(); } public void Dispose() { m_Node = null; m_Enumerator = default(Enumerator); } public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator() { return new LinqEnumerator(m_Node); } public void Reset() { if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } IEnumerator IEnumerable.GetEnumerator() { return new LinqEnumerator(m_Node); } } public static bool forceASCII = false; public static bool longAsString = false; public static bool allowLineComments = true; [ThreadStatic] private static StringBuilder m_EscapeBuilder; public abstract JSONNodeType Tag { get; } public virtual JSONNode this[int aIndex] { get { return null; } set { } } public virtual JSONNode this[string aKey] { get { return null; } set { } } public virtual string Value { get { return ""; } set { } } public virtual int Count => 0; public virtual bool IsNumber => false; public virtual bool IsString => false; public virtual bool IsBoolean => false; public virtual bool IsNull => false; public virtual bool IsArray => false; public virtual bool IsObject => false; public virtual bool Inline { get { return false; } set { } } public virtual IEnumerable<JSONNode> Children { get { yield break; } } public IEnumerable<JSONNode> DeepChildren { get { foreach (JSONNode child in Children) { foreach (JSONNode deepChild in child.DeepChildren) { yield return deepChild; } } } } public IEnumerable<KeyValuePair<string, JSONNode>> Linq => new LinqEnumerator(this); public KeyEnumerator Keys => new KeyEnumerator(GetEnumerator()); public ValueEnumerator Values => new ValueEnumerator(GetEnumerator()); public virtual double AsDouble { get { double result = 0.0; if (double.TryParse(Value, NumberStyles.Float, CultureInfo.InvariantCulture, out result)) { return result; } return 0.0; } set { Value = value.ToString(CultureInfo.InvariantCulture); } } public virtual int AsInt { get { return (int)AsDouble; } set { AsDouble = value; } } public virtual float AsFloat { get { return (float)AsDouble; } set { AsDouble = value; } } public virtual bool AsBool { get { bool result = false; if (bool.TryParse(Value, out result)) { return result; } return !string.IsNullOrEmpty(Value); } set { Value = (value ? "true" : "false"); } } public virtual long AsLong { get { long result = 0L; if (long.TryParse(Value, out result)) { return result; } return 0L; } set { Value = value.ToString(); } } public virtual ulong AsULong { get { ulong result = 0uL; if (ulong.TryParse(Value, out result)) { return result; } return 0uL; } set { Value = value.ToString(); } } public virtual JSONArray AsArray => this as JSONArray; public virtual JSONObject AsObject => this as JSONObject; internal static StringBuilder EscapeBuilder { get { if (m_EscapeBuilder == null) { m_EscapeBuilder = new StringBuilder(); } return m_EscapeBuilder; } } public virtual decimal AsDecimal { get { if (!decimal.TryParse(Value, out var result)) { result = default(decimal); } return result; } set { Value = value.ToString(); } } public virtual char AsChar { get { if (IsString && Value.Length > 0) { return Value[0]; } if (IsNumber) { return (char)AsInt; } return '\0'; } set { if (IsString) { Value = value.ToString(); } else if (IsNumber) { AsInt = value; } } } public virtual uint AsUInt { get { return (uint)AsDouble; } set { AsDouble = value; } } public virtual byte AsByte { get { return (byte)AsInt; } set { AsInt = value; } } public virtual sbyte AsSByte { get { return (sbyte)AsInt; } set { AsInt = value; } } public virtual short AsShort { get { return (short)AsInt; } set { AsInt = value; } } public virtual ushort AsUShort { get { return (ushort)AsInt; } set { AsInt = value; } } public virtual DateTime AsDateTime { get { if (!DateTime.TryParse(Value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result)) { result = new DateTime(0L); } return result; } set { Value = value.ToString(CultureInfo.InvariantCulture); } } public virtual TimeSpan AsTimeSpan { get { if (!TimeSpan.TryParse(Value, CultureInfo.InvariantCulture, out var result)) { result = new TimeSpan(0L); } return result; } set { Value = value.ToString(); } } public virtual Guid AsGuid { get { Guid.TryParse(Value, out var result); return result; } set { Value = value.ToString(); } } public virtual byte[] AsByteArray { get { if (IsNull || !IsArray) { return null; } int count = Count; byte[] array = new byte[count]; for (int i = 0; i < count; i++) { array[i] = this[i].AsByte; } return array; } set { if (IsArray && value != null) { Clear(); for (int i = 0; i < value.Length; i++) { Add(value[i]); } } } } public virtual List<byte> AsByteList { get { if (IsNull || !IsArray) { return null; } int count = Count; List<byte> list = new List<byte>(count); for (int i = 0; i < count; i++) { list.Add(this[i].AsByte); } return list; } set { if (IsArray && value != null) { Clear(); for (int i = 0; i < value.Count; i++) { Add(value[i]); } } } } public virtual string[] AsStringArray { get { if (IsNull || !IsArray) { return null; } int count = Count; string[] array = new string[count]; for (int i = 0; i < count; i++) { array[i] = this[i].Value; } return array; } set { if (IsArray && value != null) { Clear(); for (int i = 0; i < value.Length; i++) { Add(value[i]); } } } } public virtual List<string> AsStringList { get { if (IsNull || !IsArray) { return null; } int count = Count; List<string> list = new List<string>(count); for (int i = 0; i < count; i++) { list.Add(this[i].Value); } return list; } set { if (IsArray && value != null) { Clear(); for (int i = 0; i < value.Count; i++) { Add(value[i]); } } } } public virtual void Add(string aKey, JSONNode aItem) { } public virtual void Add(JSONNode aItem) { Add("", aItem); } public virtual JSONNode Remove(string aKey) { return null; } public virtual JSONNode Remove(int aIndex) { return null; } public virtual JSONNode Remove(JSONNode aNode) { return aNode; } public virtual void Clear() { } public virtual JSONNode Clone() { return null; } public virtual bool HasKey(string aKey) { return false; } public virtual JSONNode GetValueOrDefault(string aKey, JSONNode aDefault) { return aDefault; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, 0, JSONTextMode.Compact); return stringBuilder.ToString(); } public virtual string ToString(int aIndent) { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, aIndent, JSONTextMode.Indent); return stringBuilder.ToString(); } internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode); public abstract Enumerator GetEnumerator(); public static implicit operator JSONNode(string s) { if (s != null) { return new JSONString(s); } return JSONNull.CreateOrGet(); } public static implicit operator string(JSONNode d) { if (!(d == null)) { return d.Value; } return null; } public static implicit operator JSONNode(double n) { return new JSONNumber(n); } public static implicit operator double(JSONNode d) { if (!(d == null)) { return d.AsDouble; } return 0.0; } public static implicit operator JSONNode(float n) { return new JSONNumber(n); } public static implicit operator float(JSONNode d) { if (!(d == null)) { return d.AsFloat; } return 0f; } public static implicit operator JSONNode(int n) { return new JSONNumber(n); } public static implicit operator int(JSONNode d) { if (!(d == null)) { return d.AsInt; } return 0; } public static implicit operator JSONNode(long n) { if (longAsString) { return new JSONString(n.ToString()); } return new JSONNumber(n); } public static implicit operator long(JSONNode d) { if (!(d == null)) { return d.AsLong; } return 0L; } public static implicit operator JSONNode(ulong n) { if (longAsString) { return new JSONString(n.ToString()); } return new JSONNumber(n); } public static implicit operator ulong(JSONNode d) { if (!(d == null)) { return d.AsULong; } return 0uL; } public static implicit operator JSONNode(bool b) { return new JSONBool(b); } public static implicit operator bool(JSONNode d) { if (!(d == null)) { return d.AsBool; } return false; } public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue) { return aKeyValue.Value; } public static bool operator ==(JSONNode a, object b) { if ((object)a == b) { return true; } bool flag = a is JSONNull || (object)a == null || a is JSONLazyCreator; bool flag2 = b is JSONNull || b == null || b is JSONLazyCreator; if (flag && flag2) { return true; } if (!flag) { return a.Equals(b); } return false; } public static bool operator !=(JSONNode a, object b) { return !(a == b); } public override bool Equals(object obj) { return (object)this == obj; } public override int GetHashCode() { return base.GetHashCode(); } internal static string Escape(string aText) { StringBuilder escapeBuilder = EscapeBuilder; escapeBuilder.Length = 0; if (escapeBuilder.Capacity < aText.Length + aText.Length / 10) { escapeBuilder.Capacity = aText.Length + aText.Length / 10; } foreach (char c in aText) { switch (c) { case '\\': escapeBuilder.Append("\\\\"); continue; case '"': escapeBuilder.Append("\\\""); continue; case '\n': escapeBuilder.Append("\\n"); continue; case '\r': escapeBuilder.Append("\\r"); continue; case '\t': escapeBuilder.Append("\\t"); continue; case '\b': escapeBuilder.Append("\\b"); continue; case '\f': escapeBuilder.Append("\\f"); continue; } if (c < ' ' || (forceASCII && c > '\u007f')) { ushort num = c; escapeBuilder.Append("\\u").Append(num.ToString("X4")); } else { escapeBuilder.Append(c); } } string result = escapeBuilder.ToString(); escapeBuilder.Length = 0; return result; } private static JSONNode ParseElement(string token, bool quoted) { if (quoted) { return token; } if (token.Length <= 5) { string text = token.ToLower(); switch (text) { case "false": case "true": return text == "true"; case "null": return JSONNull.CreateOrGet(); } } if (double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return result; } return token; } public static JSONNode Parse(string aJSON) { Stack<JSONNode> stack = new Stack<JSONNode>(); JSONNode jSONNode = null; int i = 0; StringBuilder stringBuilder = new StringBuilder(); string aKey = ""; bool flag = false; bool flag2 = false; bool flag3 = false; for (; i < aJSON.Length; i++) { switch (aJSON[i]) { case '{': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONObject()); if (jSONNode != null) { jSONNode.Add(aKey, stack.Peek()); } aKey = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); flag3 = false; break; case '[': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONArray()); if (jSONNode != null) { jSONNode.Add(aKey, stack.Peek()); } aKey = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); flag3 = false; break; case ']': case '}': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stack.Count == 0) { throw new Exception("JSON Parse: Too many closing brackets"); } stack.Pop(); if (stringBuilder.Length > 0 || flag2) { jSONNode.Add(aKey, ParseElement(stringBuilder.ToString(), flag2)); } if (jSONNode != null) { jSONNode.Inline = !flag3; } flag2 = false; aKey = ""; stringBuilder.Length = 0; if (stack.Count > 0) { jSONNode = stack.Peek(); } break; case ':': if (flag) { stringBuilder.Append(aJSON[i]); break; } aKey = stringBuilder.ToString(); stringBuilder.Length = 0; flag2 = false; break; case '"': flag = !flag; flag2 = flag2 || flag; break; case ',': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stringBuilder.Length > 0 || flag2) { jSONNode.Add(aKey, ParseElement(stringBuilder.ToString(), flag2)); } flag2 = false; aKey = ""; stringBuilder.Length = 0; flag2 = false; break; case '\n': case '\r': flag3 = true; break; case '\t': case ' ': if (flag) { stringBuilder.Append(aJSON[i]); } break; case '\\': i++; if (flag) { char c = aJSON[i]; switch (c) { case 't': stringBuilder.Append('\t'); break; case 'r': stringBuilder.Append('\r'); break; case 'n': stringBuilder.Append('\n'); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case 'u': { string s = aJSON.Substring(i + 1, 4); stringBuilder.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier)); i += 4; break; } default: stringBuilder.Append(c); break; } } break; case '/': if (allowLineComments && !flag && i + 1 < aJSON.Length && aJSON[i + 1] == '/') { while (++i < aJSON.Length && aJSON[i] != '\n' && aJSON[i] != '\r') { } } else { stringBuilder.Append(aJSON[i]); } break; default: stringBuilder.Append(aJSON[i]); break; case '\ufeff': break; } } if (flag) { throw new Exception("JSON Parse: Quotation marks seems to be messed up."); } if (jSONNode == null) { return ParseElement(stringBuilder.ToString(), flag2); } return jSONNode; } public abstract void SerializeBinary(BinaryWriter aWriter); public void SaveToBinaryStream(Stream aData) { BinaryWriter aWriter = new BinaryWriter(aData); SerializeBinary(aWriter); } public void SaveToCompressedStream(Stream aData) { throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); } public void SaveToCompressedFile(string aFileName) { throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); } public string SaveToCompressedBase64() { throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); } public void SaveToBinaryFile(string aFileName) { Directory.CreateDirectory(new FileInfo(aFileName).Directory.FullName); using FileStream aData = File.OpenWrite(aFileName); SaveToBinaryStream(aData); } public string SaveToBinaryBase64() { using MemoryStream memoryStream = new MemoryStream(); SaveToBinaryStream(memoryStream); memoryStream.Position = 0L; return Convert.ToBase64String(memoryStream.ToArray()); } public static JSONNode DeserializeBinary(BinaryReader aReader) { JSONNodeType jSONNodeType = (JSONNodeType)aReader.ReadByte(); switch (jSONNodeType) { case JSONNodeType.Array: { int num2 = aReader.ReadInt32(); JSONArray jSONArray = new JSONArray(); for (int j = 0; j < num2; j++) { jSONArray.Add(DeserializeBinary(aReader)); } return jSONArray; } case JSONNodeType.Object: { int num = aReader.ReadInt32(); JSONObject jSONObject = new JSONObject(); for (int i = 0; i < num; i++) { string aKey = aReader.ReadString(); JSONNode aItem = DeserializeBinary(aReader); jSONObject.Add(aKey, aItem); } return jSONObject; } case JSONNodeType.String: return new JSONString(aReader.ReadString()); case JSONNodeType.Number: return new JSONNumber(aReader.ReadDouble()); case JSONNodeType.Boolean: return new JSONBool(aReader.ReadBoolean()); case JSONNodeType.NullValue: return JSONNull.CreateOrGet(); default: throw new Exception("Error deserializing JSON. Unknown tag: " + jSONNodeType); } } public static JSONNode LoadFromCompressedFile(string aFileName) { throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); } public static JSONNode LoadFromCompressedStream(Stream aData) { throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); } public static JSONNode LoadFromCompressedBase64(string aBase64) { throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); } public static JSONNode LoadFromBinaryStream(Stream aData) { using BinaryReader aReader = new BinaryReader(aData); return DeserializeBinary(aReader); } public static JSONNode LoadFromBinaryFile(string aFileName) { using FileStream aData = File.OpenRead(aFileName); return LoadFromBinaryStream(aData); } public static JSONNode LoadFromBinaryBase64(string aBase64) { return LoadFromBinaryStream(new MemoryStream(Convert.FromBase64String(aBase64)) { Position = 0L }); } public static implicit operator JSONNode(decimal aDecimal) { return new JSONString(aDecimal.ToString()); } public static implicit operator decimal(JSONNode aNode) { return aNode.AsDecimal; } public static implicit operator JSONNode(char aChar) { return new JSONString(aChar.ToString()); } public static implicit operator char(JSONNode aNode) { return aNode.AsChar; } public static implicit operator JSONNode(uint aUInt) { return new JSONNumber(aUInt); } public static implicit operator uint(JSONNode aNode) { return aNode.AsUInt; } public static implicit operator JSONNode(byte aByte) { return new JSONNumber((int)aByte); } public static implicit operator byte(JSONNode aNode) { return aNode.AsByte; } public static implicit operator JSONNode(sbyte aSByte) { return new JSONNumber(aSByte); } public static implicit operator sbyte(JSONNode aNode) { return aNode.AsSByte; } public static implicit operator JSONNode(short aShort) { return new JSONNumber(aShort); } public static implicit operator short(JSONNode aNode) { return aNode.AsShort; } public static implicit operator JSONNode(ushort aUShort) { return new JSONNumber((int)aUShort); } public static implicit operator ushort(JSONNode aNode) { return aNode.AsUShort; } public static implicit operator JSONNode(DateTime aDateTime) { return new JSONString(aDateTime.ToString(CultureInfo.InvariantCulture)); } public static implicit operator DateTime(JSONNode aNode) { return aNode.AsDateTime; } public static implicit operator JSONNode(TimeSpan aTimeSpan) { return new JSONString(aTimeSpan.ToString()); } public static implicit operator TimeSpan(JSONNode aNode) { return aNode.AsTimeSpan; } public static implicit operator JSONNode(Guid aGuid) { return new JSONString(aGuid.ToString()); } public static implicit operator Guid(JSONNode aNode) { return aNode.AsGuid; } public static implicit operator JSONNode(byte[] aByteArray) { return new JSONArray { AsByteArray = aByteArray }; } public static implicit operator byte[](JSONNode aNode) { return aNode.AsByteArray; } public static implicit operator JSONNode(List<byte> aByteList) { return new JSONArray { AsByteList = aByteList }; } public static implicit operator List<byte>(JSONNode aNode) { return aNode.AsByteList; } public static implicit operator JSONNode(string[] aStringArray) { return new JSONArray { AsStringArray = aStringArray }; } public static implicit operator string[](JSONNode aNode) { return aNode.AsStringArray; } public static implicit operator JSONNode(List<string> aStringList) { return new JSONArray { AsStringList = aStringList }; } public static implicit operator List<string>(JSONNode aNode) { return aNode.AsStringList; } public static implicit operator JSONNode(int? aValue) { if (!aValue.HasValue) { return JSONNull.CreateOrGet(); } return new JSONNumber(aValue.Value); } public static implicit operator int?(JSONNode aNode) { if (aNode == null || aNode.IsNull) { return null; } return aNode.AsInt; } public static implicit operator JSONNode(float? aValue) { if (!aValue.HasValue) { return JSONNull.CreateOrGet(); } return new JSONNumber(aValue.Value); } public static implicit operator float?(JSONNode aNode) { if (aNode == null || aNode.IsNull) { return null; } return aNode.AsFloat; } public static implicit operator JSONNode(double? aValue) { if (!aValue.HasValue) { return JSONNull.CreateOrGet(); } return new JSONNumber(aValue.Value); } public static implicit operator double?(JSONNode aNode) { if (aNode == null || aNode.IsNull) { return null; } return aNode.AsDouble; } public static implicit operator JSONNode(bool? aValue) { if (!aValue.HasValue) { return JSONNull.CreateOrGet(); } return new JSONBool(aValue.Value); } public static implicit operator bool?(JSONNode aNode) { if (aNode == null || aNode.IsNull) { return null; } return aNode.AsBool; } public static implicit operator JSONNode(long? aValue) { if (!aValue.HasValue) { return JSONNull.CreateOrGet(); } return new JSONNumber(aValue.Value); } public static implicit operator long?(JSONNode aNode) { if (aNode == null || aNode.IsNull) { return null; } return aNode.AsLong; } public static implicit operator JSONNode(short? aValue) { if (!aValue.HasValue) { return JSONNull.CreateOrGet(); } return new JSONNumber(aValue.Value); } public static implicit operator short?(JSONNode aNode) { if (aNode == null || aNode.IsNull) { return null; } return aNode.AsShort; } } public class JSONArray : JSONNode { private List<JSONNode> m_List = new List<JSONNode>(); private bool inline; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Array; public override bool IsArray => true; public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_List.Count) { return new JSONLazyCreator(this); } return m_List[aIndex]; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex < 0 || aIndex >= m_List.Count) { m_List.Add(value); } else { m_List[aIndex] = value; } } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this); } set { if (value == null) { value = JSONNull.CreateOrGet(); } m_List.Add(value); } } public override int Count => m_List.Count; public override IEnumerable<JSONNode> Children { get { foreach (JSONNode item in m_List) { yield return item; } } } public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } m_List.Add(aItem); } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_List.Count) { return null; } JSONNode result = m_List[aIndex]; m_List.RemoveAt(aIndex); return result; } public override JSONNode Remove(JSONNode aNode) { m_List.Remove(aNode); return aNode; } public override void Clear() { m_List.Clear(); } public override JSONNode Clone() { JSONArray jSONArray = new JSONArray(); jSONArray.m_List.Capacity = m_List.Capacity; foreach (JSONNode item in m_List) { if (item != null) { jSONArray.Add(item.Clone()); } else { jSONArray.Add(null); } } return jSONArray; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('['); int count = m_List.Count; if (inline) { aMode = JSONTextMode.Compact; } for (int i = 0; i < count; i++) { if (i > 0) { aSB.Append(','); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append(']'); } public override void SerializeBinary(BinaryWriter aWriter) { aWriter.Write((byte)1); aWriter.Write(m_List.Count); for (int i = 0; i < m_List.Count; i++) { m_List[i].SerializeBinary(aWriter); } } } public class JSONObject : JSONNode { private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>(); private bool inline; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Object; public override bool IsObject => true; public override JSONNode this[string aKey] { get { if (m_Dict.ContainsKey(aKey)) { return m_Dict[aKey]; } return new JSONLazyCreator(this, aKey); } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = value; } else { m_Dict.Add(aKey, value); } } } public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } return m_Dict.ElementAt(aIndex).Value; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex >= 0 && aIndex < m_Dict.Count) { string key = m_Dict.ElementAt(aIndex).Key; m_Dict[key] = value; } } } public override int Count => m_Dict.Count; public override IEnumerable<JSONNode> Children { get { foreach (KeyValuePair<string, JSONNode> item in m_Dict) { yield return item.Value; } } } public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } if (aKey != null) { if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = aItem; } else { m_Dict.Add(aKey, aItem); } } else { m_Dict.Add(Guid.NewGuid().ToString(), aItem); } } public override JSONNode Remove(string aKey) { if (!m_Dict.ContainsKey(aKey)) { return null; } JSONNode result = m_Dict[aKey]; m_Dict.Remove(aKey); return result; } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } KeyValuePair<string, JSONNode> keyValuePair = m_Dict.ElementAt(aIndex); m_Dict.Remove(keyValuePair.Key); return keyValuePair.Value; } public override JSONNode Remove(JSONNode aNode) { try { KeyValuePair<string, JSONNode> keyValuePair = m_Dict.Where((KeyValuePair<string, JSONNode> k) => k.Value == aNode).First(); m_Dict.Remove(keyValuePair.Key); return aNode; } catch { return null; } } public override void Clear() { m_Dict.Clear(); } public override JSONNode Clone() { JSONObject jSONObject = new JSONObject(); foreach (KeyValuePair<string, JSONNode> item in m_Dict) { jSONObject.Add(item.Key, item.Value.Clone()); } return jSONObject; } public override bool HasKey(string aKey) { return m_Dict.ContainsKey(aKey); } public override JSONNode GetValueOrDefault(string aKey, JSONNode aDefault) { if (m_Dict.TryGetValue(aKey, out var value)) { return value; } return aDefault; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('{'); bool flag = true; if (inline) { aMode = JSONTextMode.Compact; } foreach (KeyValuePair<string, JSONNode> item in m_Dict) { if (!flag) { aSB.Append(','); } flag = false; if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } aSB.Append('"').Append(JSONNode.Escape(item.Key)).Append('"'); if (aMode == JSONTextMode.Compact) { aSB.Append(':'); } else { aSB.Append(" : "); } item.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append('}'); } public override void SerializeBinary(BinaryWriter aWriter) { aWriter.Write((byte)2); aWriter.Write(m_Dict.Count); foreach (string key in m_Dict.Keys) { aWriter.Write(key); m_Dict[key].SerializeBinary(aWriter); } } } public class JSONString : JSONNode { private string m_Data; public override JSONNodeType Tag => JSONNodeType.String; public override bool IsString => true; public override string Value { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONString(string aData) { m_Data = aData; } public override JSONNode Clone() { return new JSONString(m_Data); } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('"').Append(JSONNode.Escape(m_Data)).Append('"'); } public override bool Equals(object obj) { if (base.Equals(obj)) { return true; } if (obj is string text) { return m_Data == text; } JSONString jSONString = obj as JSONString; if (jSONString != null) { return m_Data == jSONString.m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } public override void Clear() { m_Data = ""; } public override void SerializeBinary(BinaryWriter aWriter) { aWriter.Write((byte)3); aWriter.Write(m_Data); } } public class JSONNumber : JSONNode { private double m_Data; public override JSONNodeType Tag => JSONNodeType.Number; public override bool IsNumber => true; public override string Value { get { return m_Data.ToString(CultureInfo.InvariantCulture); } set { if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { m_Data = result; } } } public override double AsDouble { get { return m_Data; } set { m_Data = value; } } public override long AsLong { get { return (long)m_Data; } set { m_Data = value; } } public override ulong AsULong { get { return (ulong)m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONNumber(double aData) { m_Data = aData; } public JSONNumber(string aData) { Value = aData; } public override JSONNode Clone() { return new JSONNumber(m_Data); } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(Value); } private static bool IsNumeric(object value) { if (!(value is int) && !(value is uint) && !(value is float) && !(value is double) && !(value is decimal) && !(value is long) && !(value is ulong) && !(value is short) && !(value is ushort) && !(value is sbyte)) { return value is byte; } return true; } public override bool Equals(object obj) { if (obj == null) { return false; } if (base.Equals(obj)) { return true; } JSONNumber jSONNumber = obj as JSONNumber; if (jSONNumber != null) { return m_Data == jSONNumber.m_Data; } if (IsNumeric(obj)) { return Convert.ToDouble(obj) == m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } public override void Clear() { m_Data = 0.0; } public override void SerializeBinary(BinaryWriter aWriter) { aWriter.Write((byte)4); aWriter.Write(m_Data); } } public class JSONBool : JSONNode { private bool m_Data; public override JSONNodeType Tag => JSONNodeType.Boolean; public override bool IsBoolean => true; public override string Value { get { return m_Data.ToString(); } set { if (bool.TryParse(value, out var result)) { m_Data = result; } } } public override bool AsBool { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONBool(bool aData) { m_Data = aData; } public JSONBool(string aData) { Value = aData; } public override JSONNode Clone() { return new JSONBool(m_Data); } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(m_Data ? "true" : "false"); } public override bool Equals(object obj) { if (obj == null) { return false; } if (obj is bool) { return m_Data == (bool)obj; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } public override void Clear() { m_Data = false; } public override void SerializeBinary(BinaryWriter aWriter) { aWriter.Write((byte)6); aWriter.Write(m_Data); } } public class JSONNull : JSONNode { private static JSONNull m_StaticInstance = new JSONNull(); public static bool reuseSameInstance = true; public override JSONNodeType Tag => JSONNodeType.NullValue; public override bool IsNull => true; public override string Value { get { return "null"; } set { } } public override bool AsBool { get { return false; } set { } } public static JSONNull CreateOrGet() { if (reuseSameInstance) { return m_StaticInstance; } return new JSONNull(); } private JSONNull() { } public override Enumerator GetEnumerator() { return default(Enumerator); } public override JSONNode Clone() { return CreateOrGet(); } public override bool Equals(object obj) { if ((object)this == obj) { return true; } return obj is JSONNull; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } public override void SerializeBinary(BinaryWriter aWriter) { aWriter.Write((byte)5); } } internal class JSONLazyCreator : JSONNode { private JSONNode m_Node; private string m_Key; public override JSONNodeType Tag => JSONNodeType.None; public override JSONNode this[int aIndex] { get { return new JSONLazyCreator(this); } set { Set(new JSONArray()).Add(value); } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this, aKey); } set { Set(new JSONObject()).Add(aKey, value); } } public override int AsInt { get { Set(new JSONNumber(0.0)); return 0; } set { Set(new JSONNumber(value)); } } public override float AsFloat { get { Set(new JSONNumber(0.0)); return 0f; } set { Set(new JSONNumber(value)); } } public override double AsDouble { get { Set(new JSONNumber(0.0)); return 0.0; } set { Set(new JSONNumber(value)); } } public override long AsLong { get { if (JSONNode.longAsString) { Set(new JSONString("0")); } else { Set(new JSONNumber(0.0)); } return 0L; } set { if (JSONNode.longAsString) { Set(new JSONString(value.ToString())); } else { Set(new JSONNumber(value)); } } } public override ulong AsULong { get { if (JSONNode.longAsString) { Set(new JSONString("0")); } else { Set(new JSONNumber(0.0)); } return 0uL; } set { if (JSONNode.longAsString) { Set(new JSONString(value.ToString())); } else { Set(new JSONNumber(value)); } } } public override bool AsBool { get { Set(new JSONBool(aData: false)); return false; } set { Set(new JSONBool(value)); } } public override JSONArray AsArray => Set(new JSONArray()); public override JSONObject AsObject => Set(new JSONObject()); public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONLazyCreator(JSONNode aNode) { m_Node = aNode; m_Key = null; } public JSONLazyCreator(JSONNode aNode, string aKey) { m_Node = aNode; m_Key = aKey; } private T Set<T>(T aVal) where T : JSONNode { if (m_Key == null) { m_Node.Add(aVal); } else { m_Node.Add(m_Key, aVal); } m_Node = null; return aVal; } public override void Add(JSONNode aItem) { Set(new JSONArray()).Add(aItem); } public override void Add(string aKey, JSONNode aItem) { Set(new JSONObject()).Add(aKey, aItem); } public static bool operator ==(JSONLazyCreator a, object b) { if (b == null) { return true; } return (object)a == b; } public static bool operator !=(JSONLazyCreator a, object b) { return !(a == b); } public override bool Equals(object obj) { if (obj == null) { return true; } return (object)this == obj; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } public override void SerializeBinary(BinaryWriter aWriter) { } } public static class JSON { public static JSONNode Parse(string aJSON) { return JSONNode.Parse(aJSON); } } } namespace AuthoritativeConfig { public class Config { private static Config _instance; public Dictionary<string, ConfigBaseEntry> _configEntries; public BaseUnityPlugin _mod; private static ConfigEntry<bool> _serverIsAuthoritative; private static bool _defaultBindAuthority; public static ManualLogSource Logger; public UnityEvent OnConfigReceived = new UnityEvent(); public static Config Instance => _instance ?? (_instance = new Config()); public static ZNet ZNet => ZNet.instance; public static string GUID => Instance._mod.Info.Metadata.GUID; public static string RPC_SYNC_GUID => "AuthoritativeConfig_" + GUID; public static int RPC_SYNC_HASH => StringExtensionMethods.GetStableHashCode(RPC_SYNC_GUID); public void Init(BaseUnityPlugin mod, bool defaultBindServerAuthority = false) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown _mod = mod; Logger = new ManualLogSource(RPC_SYNC_GUID); Logger.Sources.Add((ILogSource)(object)Logger); _configEntries = new Dictionary<string, ConfigBaseEntry>(); _defaultBindAuthority = defaultBindServerAuthority; _serverIsAuthoritative = _mod.Config.Bind<bool>("ServerAuthoritativeConfig", "ServerIsAuthoritative", true, "<Server Only> Forces Clients to use Server defined configs."); Harmony.CreateAndPatchAll(typeof(Config), (string)null); Logger.LogInfo((object)"Initialized Server Authoritative Config Manager."); } [HarmonyPatch(typeof(Game), "Start")] [HarmonyPostfix] protected static void RegisterSyncConfigRPC() { if (!ZRoutedRpc.instance.m_functions.ContainsKey(RPC_SYNC_HASH)) { Logger.LogInfo((object)("Authoritative Config Registered -> " + RPC_SYNC_GUID)); ZRoutedRpc.instance.Register<ZPackage>(RPC_SYNC_GUID, (Action<long, ZPackage>)RPC_SyncServerConfig); } foreach (ConfigBaseEntry value in Instance._configEntries.Values) { value.ClearServerValue(); } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyPostfix] protected static void RequestConfigFromServer() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown if (!ZNet.IsServer() && (int)ZNet.GetConnectionStatus() == 2) { long? num = AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", (Type[])null, (Type[])null).Invoke(ZRoutedRpc.instance, null) as long?; ZRoutedRpc.instance.InvokeRoutedRPC(num.Value, RPC_SYNC_GUID, new object[1] { (object)new ZPackage() }); Logger.LogInfo((object)("Authoritative Config Registered -> " + RPC_SYNC_GUID)); Debug.Log((object)(Instance._mod.Info.Metadata.Name + ": Authoritative Config Requested -> " + RPC_SYNC_GUID)); } else if (!ZNet.IsServer()) { Logger.LogWarning((object)"Failed to Request Configs. Bad Peer? Too Early?"); } } public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, ConfigDescription configDescription = null, bool? serverAuthoritative = null) { ConfigEntry<T> configEntry = new ConfigEntry<T>(_mod.Config.Bind<T>(section, key, defaultValue, configDescription), serverAuthoritative.HasValue ? serverAuthoritative.Value : _defaultBindAuthority); _configEntries[((object)configEntry.BaseEntry.Definition).ToString()] = configEntry; return configEntry; } public ConfigEntry<T> Bind<T>(ConfigDefinition configDefinition, T defaultValue, ConfigDescription configDescription = null, bool? serverAuthoritative = null) { ConfigEntry<T> configEntry = new ConfigEntry<T>(_mod.Config.Bind<T>(configDefinition, defaultValue, configDescription), serverAuthoritative.HasValue ? serverAuthoritative.Value : _defaultBindAuthority); _configEntries[((object)configEntry.BaseEntry.Definition).ToString()] = configEntry; return configEntry; } public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description, bool? serverAuthoritative = null) { ConfigEntry<T> configEntry = new ConfigEntry<T>(_mod.Config.Bind<T>(section, key, defaultValue, description), serverAuthoritative.HasValue ? serverAuthoritative.Value : _defaultBindAuthority); _configEntries[((object)configEntry.BaseEntry.Definition).ToString()] = configEntry; return configEntry; } public static void SendConfigToClient(long sender) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown if (!ZNet.IsServer()) { return; } ZPackage val = new ZPackage(); int num = 0; foreach (KeyValuePair<string, ConfigBaseEntry> configEntry in Instance._configEntries) { if (configEntry.Value.ServerAuthoritative) { val.Write(configEntry.Key); val.Write(configEntry.Value.BaseEntry.GetSerializedValue()); num++; Logger.LogInfo((object)("Sending Config " + configEntry.Key + ": " + configEntry.Value.BaseEntry.GetSerializedValue())); } } ZRoutedRpc.instance.InvokeRoutedRPC(sender, RPC_SYNC_GUID, new object[1] { val }); Logger.LogInfo((object)$"Sent {num} config pairs to client {sender}"); } public static void ReadConfigPkg(ZPackage pkg) { if (ZNet.IsServer()) { return; } int num = 0; while (pkg.GetPos() != pkg.Size()) { string text = pkg.ReadString(); string text2 = pkg.ReadString(); num++; if (Instance._configEntries.ContainsKey(text)) { Instance._configEntries[text].SetSerializedValue(text2); Logger.LogInfo((object)("Applied Server Authoritative config pair => " + text + ": " + text2)); } else { Logger.LogError((object)("Recieved config key we dont have locally. Possible Version Mismatch. " + text + ": " + text2)); } } Logger.LogInfo((object)$"Applied {num} config pairs"); UnityEvent onConfigReceived = Instance.OnConfigReceived; if (onConfigReceived != null) { onConfigReceived.Invoke(); } } public static void RPC_SyncServerConfig(long sender, ZPackage pkg) { if (ZNet.IsServer() && _serverIsAuthoritative.Value) { SendConfigToClient(sender); } else if (!ZNet.IsServer() && pkg != null && pkg.Size() > 0 && AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", (Type[])null, (Type[])null).Invoke(ZRoutedRpc.instance, null) as long? == sender) { ReadConfigPkg(pkg); } } } public class ConfigBaseEntry { protected object _serverValue; public ConfigEntryBase BaseEntry; public bool ServerAuthoritative; protected bool _didError; internal ConfigBaseEntry(ConfigEntryBase configEntry, bool serverAuthoritative) { BaseEntry = configEntry; ServerAuthoritative = serverAuthoritative; } public void SetSerializedValue(string value) { try { _serverValue = TomlTypeConverter.ConvertToValue(value, BaseEntry.SettingType); _didError = false; } catch (Exception ex) { Config.Logger.LogWarning((object)$"Config value of setting \"{BaseEntry.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } } public void ClearServerValue() { _serverValue = null; _didError = false; } } public class ConfigEntry<T> : ConfigBaseEntry { private readonly ConfigEntry<T> _configEntry; public T ServerValue => (T)_serverValue; public T Value { get { if (ServerAuthoritative && (Object)(object)Config.ZNet != (Object)null && !Config.ZNet.IsServer()) { if (_serverValue != null) { return ServerValue; } if (!_didError) { Config.Logger.LogWarning((object)$"No Recieved value for Server Authoritative Config. {BaseEntry.Definition}. Falling Back to Client Config."); _didError = true; } return _configEntry.Value; } return _configEntry.Value; } set { _configEntry.Value = value; } } internal ConfigEntry(ConfigEntry<T> configEntry, bool serverAuthoritative) : base((ConfigEntryBase)(object)configEntry, serverAuthoritative) { _configEntry = configEntry; } } }
Plugins/Jotunn/Jotunn.dll
Decompiled 2 years ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.GUI; using Jotunn.Managers; using Jotunn.Managers.MockSystem; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Mono.Cecil.Cil; using MonoMod.Cil; using SimpleJson; using SimpleJson.Reflection; using SoftReferenceableAssets; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.LowLevel; using UnityEngine.SceneManagement; using UnityEngine.U2D; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("JotunnTests")] [assembly: InternalsVisibleTo("JotunnDoc")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("Valheim-Modding team")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Jötunn (/ˈjɔːtʊn/, \"giant\") is a modding library for Valheim, with the goal of making the lives of mod developers easier.")] [assembly: AssemblyFileVersion("2.20.1.0")] [assembly: AssemblyInformationalVersion("2.20.1+1946eac74af0afe7e62332fd5e3c0d77d2c0d9b4")] [assembly: AssemblyProduct("JotunnLib")] [assembly: AssemblyTitle("Jotunn")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Valheim-Modding/Jotunn")] [assembly: NeutralResourcesLanguage("en")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.20.1.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } internal class CompatibilityWindow : MonoBehaviour { public ScrollRect scrollRect; public Text failedConnection; public Text localVersion; public Text remoteVersion; public Text errorMessages; public Button continueButton; public Button logFileButton; public Button troubleshootingButton; public void UpdateTextPositions() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) //IL_0072: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00ca: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown float preferredHeight = failedConnection.preferredHeight; float preferredHeight2 = localVersion.preferredHeight; float preferredHeight3 = remoteVersion.preferredHeight; float preferredHeight4 = errorMessages.preferredHeight; Vector2 anchoredPosition = ((Graphic)localVersion).rectTransform.anchoredPosition; Vector2 anchoredPosition2 = ((Graphic)remoteVersion).rectTransform.anchoredPosition; float num = preferredHeight + 32f; ((Graphic)localVersion).rectTransform.anchoredPosition = new Vector2(anchoredPosition.x, 0f - num); ((Graphic)remoteVersion).rectTransform.anchoredPosition = new Vector2(anchoredPosition2.x, 0f - num); Vector2 anchoredPosition3 = ((Graphic)errorMessages).rectTransform.anchoredPosition; float num2 = num + Mathf.Max(preferredHeight2, preferredHeight3) + 32f; ((Graphic)errorMessages).rectTransform.anchoredPosition = new Vector2(anchoredPosition3.x, 0f - num2); RectTransform val = (RectTransform)((Component)scrollRect.content).transform; val.SetSizeWithCurrentAnchors((Axis)1, num2 + preferredHeight4); } } public sealed class ConfigurationManagerAttributes { public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func<object, string> ObjToStr; public Func<string, object> StrToObj; private bool isAdminOnly; private bool isUnlocked; private static readonly PropertyInfo[] _myProperties = typeof(ConfigurationManagerAttributes).GetProperties(BindingFlags.Instance | BindingFlags.Public); private static readonly FieldInfo[] _myFields = typeof(ConfigurationManagerAttributes).GetFields(BindingFlags.Instance | BindingFlags.Public); public bool IsAdminOnly { get { return isAdminOnly; } set { isAdminOnly = value; IsUnlocked = !value; } } public Color EntryColor { get; set; } public Color DescriptionColor { get; set; } public bool IsUnlocked { get { return isUnlocked; } internal set { ReadOnly = !value; HideDefaultButton = !value; isUnlocked = value; } } public ConfigurationManagerAttributes() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) EntryColor = new Color(1f, 0.631f, 0.235f, 1f); DescriptionColor = Color.white; } public void SetFromAttributes(object[] attribs) { if (attribs == null || attribs.Length == 0) { return; } foreach (object obj in attribs) { if (obj == null) { continue; } if (!(obj is DisplayNameAttribute displayNameAttribute)) { if (!(obj is CategoryAttribute categoryAttribute)) { if (!(obj is DescriptionAttribute descriptionAttribute)) { if (!(obj is DefaultValueAttribute defaultValueAttribute)) { if (!(obj is ReadOnlyAttribute readOnlyAttribute)) { if (!(obj is BrowsableAttribute browsableAttribute)) { if (obj is string text) { switch (text) { case "ReadOnly": ReadOnly = true; break; case "Browsable": Browsable = true; break; case "Unbrowsable": case "Hidden": Browsable = false; break; case "Advanced": IsAdvanced = true; break; } continue; } Type type = obj.GetType(); if (!(type.Name == "ConfigurationManagerAttributes")) { break; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (var item in from my in _myProperties join other in fields on my.Name equals other.Name select new { my, other }) { try { object obj2 = item.other.GetValue(obj); if (obj2 != null) { if (item.my.PropertyType != item.other.FieldType && typeof(Delegate).IsAssignableFrom(item.my.PropertyType)) { obj2 = Delegate.CreateDelegate(item.my.PropertyType, ((Delegate)obj2).Target, ((Delegate)obj2).Method); } item.my.SetValue(this, obj2, null); } } catch (Exception ex) { Logger.LogWarning("Failed to copy value " + item.my.Name + " from provided tag object " + type.FullName + " - " + ex.Message); } } foreach (var item2 in from my in _myFields join other in fields on my.Name equals other.Name select new { my, other }) { try { object obj3 = item2.other.GetValue(obj); if (obj3 != null) { if (item2.my.FieldType != item2.other.FieldType && typeof(Delegate).IsAssignableFrom(item2.my.FieldType)) { obj3 = Delegate.CreateDelegate(item2.my.FieldType, ((Delegate)obj3).Target, ((Delegate)obj3).Method); } item2.my.SetValue(this, obj3); } } catch (Exception ex2) { Logger.LogWarning("Failed to copy value " + item2.my.Name + " from provided tag object " + type.FullName + " - " + ex2.Message); } } } else { Browsable = browsableAttribute.Browsable; } } else { ReadOnly = readOnlyAttribute.IsReadOnly; } } else { DefaultValue = defaultValueAttribute.Value; } } else { Description = descriptionAttribute.Description; } } else { Category = categoryAttribute.Category; } } else { DispName = displayNameAttribute.DisplayName; } } } } public static class ObjImporter { private struct meshStruct { public Vector3[] vertices; public Vector3[] normals; public Vector2[] uv; public Vector2[] uv1; public Vector2[] uv2; public int[] triangles; public int[] faceVerts; public int[] faceUVs; public Vector3[] faceData; public string name; public string fileName; } public static Mesh ImportFile(string filePath) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_006e: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //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_00b5: 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) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) meshStruct mesh = CreateMeshStruct(filePath); PopulateMeshStruct(ref mesh); Vector3[] array = (Vector3[])(object)new Vector3[mesh.faceData.Length]; Vector2[] array2 = (Vector2[])(object)new Vector2[mesh.faceData.Length]; Vector3[] array3 = (Vector3[])(object)new Vector3[mesh.faceData.Length]; int num = 0; Vector3[] faceData = mesh.faceData; foreach (Vector3 val in faceData) { array[num] = mesh.vertices[(int)val.x - 1]; if (val.y >= 1f) { array2[num] = mesh.uv[(int)val.y - 1]; } if (val.z >= 1f) { array3[num] = mesh.normals[(int)val.z - 1]; } num++; } Mesh val2 = new Mesh(); val2.vertices = array; val2.uv = array2; val2.normals = array3; val2.triangles = mesh.triangles; val2.RecalculateBounds(); val2.Optimize(); return val2; } private static meshStruct CreateMeshStruct(string filename) { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; meshStruct result = default(meshStruct); result.fileName = filename; StreamReader streamReader = File.OpenText(filename); string s = streamReader.ReadToEnd(); streamReader.Close(); using (StringReader stringReader = new StringReader(s)) { string text = stringReader.ReadLine(); char[] separator = new char[1] { ' ' }; while (text != null) { if (!text.StartsWith("f ") && !text.StartsWith("v ") && !text.StartsWith("vt ") && !text.StartsWith("vn ")) { text = stringReader.ReadLine(); if (text != null) { text = text.Replace(" ", " "); } continue; } text = text.Trim(); string[] array = text.Split(separator, 50); switch (array[0]) { case "v": num2++; break; case "vt": num3++; break; case "vn": num4++; break; case "f": num5 = num5 + array.Length - 1; num += 3 * (array.Length - 2); break; } text = stringReader.ReadLine(); if (text != null) { text = text.Replace(" ", " "); } } } result.triangles = new int[num]; result.vertices = (Vector3[])(object)new Vector3[num2]; result.uv = (Vector2[])(object)new Vector2[num3]; result.normals = (Vector3[])(object)new Vector3[num4]; result.faceData = (Vector3[])(object)new Vector3[num5]; return result; } private static void PopulateMeshStruct(ref meshStruct mesh) { //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) StreamReader streamReader = File.OpenText(mesh.fileName); string s = streamReader.ReadToEnd(); streamReader.Close(); using StringReader stringReader = new StringReader(s); string text = stringReader.ReadLine(); char[] separator = new char[1] { ' ' }; char[] separator2 = new char[1] { '/' }; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; while (text != null) { if (!text.StartsWith("f ") && !text.StartsWith("v ") && !text.StartsWith("vt ") && !text.StartsWith("vn ") && !text.StartsWith("g ") && !text.StartsWith("usemtl ") && !text.StartsWith("mtllib ") && !text.StartsWith("vt1 ") && !text.StartsWith("vt2 ") && !text.StartsWith("vc ") && !text.StartsWith("usemap ")) { text = stringReader.ReadLine(); if (text != null) { text = text.Replace(" ", " "); } continue; } text = text.Trim(); string[] array = text.Split(separator, 50); switch (array[0]) { case "v": mesh.vertices[num3] = new Vector3(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]), Convert.ToSingle(array[3])); num3++; break; case "vt": mesh.uv[num5] = new Vector2(Convert.ToSingle(array[1]), Convert.ToSingle(array[2])); num5++; break; case "vt1": mesh.uv[num6] = new Vector2(Convert.ToSingle(array[1]), Convert.ToSingle(array[2])); num6++; break; case "vt2": mesh.uv[num7] = new Vector2(Convert.ToSingle(array[1]), Convert.ToSingle(array[2])); num7++; break; case "vn": mesh.normals[num4] = new Vector3(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]), Convert.ToSingle(array[3])); num4++; break; case "f": { int num8 = 1; List<int> list = new List<int>(); while (num8 < array.Length && (array[num8] ?? "").Length > 0) { Vector3 val = default(Vector3); string[] array2 = array[num8].Split(separator2, 3); val.x = Convert.ToInt32(array2[0]); if (array2.Length > 1) { if (array2[1] != "") { val.y = Convert.ToInt32(array2[1]); } val.z = Convert.ToInt32(array2[2]); } num8++; mesh.faceData[num2] = val; list.Add(num2); num2++; } for (num8 = 1; num8 + 2 < array.Length; num8++) { mesh.triangles[num] = list[0]; num++; mesh.triangles[num] = list[num8]; num++; mesh.triangles[num] = list[num8 + 1]; num++; } break; } } text = stringReader.ReadLine(); if (text != null) { text = text.Replace(" ", " "); } } } } namespace SimpleJson { [GeneratedCode("simple-json", "1.0.0")] [EditorBrowsable(EditorBrowsableState.Never)] public class JsonArray : List<object> { public JsonArray() { } public JsonArray(int capacity) : base(capacity) { } public override string ToString() { return SimpleJson.SerializeObject(this) ?? string.Empty; } } [GeneratedCode("simple-json", "1.0.0")] [EditorBrowsable(EditorBrowsableState.Never)] public class JsonObject : IDictionary<string, object>, ICollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable { private readonly Dictionary<string, object> _members; public object this[int index] => GetAtIndex(_members, index); public ICollection<string> Keys => _members.Keys; public ICollection<object> Values => _members.Values; public object this[string key] { get { return _members[key]; } set { _members[key] = value; } } public int Count => _members.Count; public bool IsReadOnly => false; public JsonObject() { _members = new Dictionary<string, object>(); } public JsonObject(IEqualityComparer<string> comparer) { _members = new Dictionary<string, object>(comparer); } internal static object GetAtIndex(IDictionary<string, object> obj, int index) { if (obj == null) { throw new ArgumentNullException("obj"); } if (index >= obj.Count) { throw new ArgumentOutOfRangeException("index"); } int num = 0; foreach (KeyValuePair<string, object> item in obj) { if (num++ == index) { return item.Value; } } return null; } public void Add(string key, object value) { _members.Add(key, value); } public bool ContainsKey(string key) { return _members.ContainsKey(key); } public bool Remove(string key) { return _members.Remove(key); } public bool TryGetValue(string key, out object value) { return _members.TryGetValue(key, out value); } public void Add(KeyValuePair<string, object> item) { _members.Add(item.Key, item.Value); } public void Clear() { _members.Clear(); } public bool Contains(KeyValuePair<string, object> item) { if (_members.ContainsKey(item.Key)) { return _members[item.Key] == item.Value; } return false; } public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } int num = Count; using IEnumerator<KeyValuePair<string, object>> enumerator = GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair<string, object> current = enumerator.Current; array[arrayIndex++] = current; if (--num <= 0) { break; } } } public bool Remove(KeyValuePair<string, object> item) { return _members.Remove(item.Key); } public IEnumerator<KeyValuePair<string, object>> GetEnumerator() { return _members.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _members.GetEnumerator(); } public override string ToString() { return SimpleJson.SerializeObject(this); } } [GeneratedCode("simple-json", "1.0.0")] public static class SimpleJson { private const int TOKEN_NONE = 0; private const int TOKEN_CURLY_OPEN = 1; private const int TOKEN_CURLY_CLOSE = 2; private const int TOKEN_SQUARED_OPEN = 3; private const int TOKEN_SQUARED_CLOSE = 4; private const int TOKEN_COLON = 5; private const int TOKEN_COMMA = 6; private const int TOKEN_STRING = 7; private const int TOKEN_NUMBER = 8; private const int TOKEN_TRUE = 9; private const int TOKEN_FALSE = 10; private const int TOKEN_NULL = 11; private const int BUILDER_CAPACITY = 2000; private static readonly char[] EscapeTable; private static readonly char[] EscapeCharacters; private static readonly string EscapeCharactersString; private static IJsonSerializerStrategy _currentJsonSerializerStrategy; private static PocoJsonSerializerStrategy _pocoJsonSerializerStrategy; public static IJsonSerializerStrategy CurrentJsonSerializerStrategy { get { return _currentJsonSerializerStrategy ?? (_currentJsonSerializerStrategy = PocoJsonSerializerStrategy); } set { _currentJsonSerializerStrategy = value; } } [EditorBrowsable(EditorBrowsableState.Advanced)] public static PocoJsonSerializerStrategy PocoJsonSerializerStrategy => _pocoJsonSerializerStrategy ?? (_pocoJsonSerializerStrategy = new PocoJsonSerializerStrategy()); static SimpleJson() { EscapeCharacters = new char[7] { '"', '\\', '\b', '\f', '\n', '\r', '\t' }; EscapeCharactersString = new string(EscapeCharacters); EscapeTable = new char[93]; EscapeTable[34] = '"'; EscapeTable[92] = '\\'; EscapeTable[8] = 'b'; EscapeTable[12] = 'f'; EscapeTable[10] = 'n'; EscapeTable[13] = 'r'; EscapeTable[9] = 't'; } public static object DeserializeObject(string json) { if (TryDeserializeObject(json, out var obj)) { return obj; } throw new SerializationException("Invalid JSON string"); } public static bool TryDeserializeObject(string json, out object obj) { bool success = true; if (json != null) { char[] json2 = json.ToCharArray(); int index = 0; obj = ParseValue(json2, ref index, ref success); } else { obj = null; } return success; } public static object DeserializeObject(string json, Type type, IJsonSerializerStrategy jsonSerializerStrategy) { object obj = DeserializeObject(json); if (!(type == null) && (obj == null || !ReflectionUtils.IsAssignableFrom(obj.GetType(), type))) { return (jsonSerializerStrategy ?? CurrentJsonSerializerStrategy).DeserializeObject(obj, type); } return obj; } public static object DeserializeObject(string json, Type type) { return DeserializeObject(json, type, null); } public static T DeserializeObject<T>(string json, IJsonSerializerStrategy jsonSerializerStrategy) { return (T)DeserializeObject(json, typeof(T), jsonSerializerStrategy); } public static T DeserializeObject<T>(string json) { return (T)DeserializeObject(json, typeof(T), null); } public static string SerializeObject(object json, IJsonSerializerStrategy jsonSerializerStrategy) { StringBuilder stringBuilder = new StringBuilder(2000); if (!SerializeValue(jsonSerializerStrategy, json, stringBuilder)) { return null; } return stringBuilder.ToString(); } public static string SerializeObject(object json) { return SerializeObject(json, CurrentJsonSerializerStrategy); } public static string EscapeToJavascriptString(string jsonString) { if (string.IsNullOrEmpty(jsonString)) { return jsonString; } StringBuilder stringBuilder = new StringBuilder(); int num = 0; while (num < jsonString.Length) { char c = jsonString[num++]; if (c == '\\') { int num2 = jsonString.Length - num; if (num2 >= 2) { switch (jsonString[num]) { case '\\': stringBuilder.Append('\\'); num++; break; case '"': stringBuilder.Append("\""); num++; break; case 't': stringBuilder.Append('\t'); num++; break; case 'b': stringBuilder.Append('\b'); num++; break; case 'n': stringBuilder.Append('\n'); num++; break; case 'r': stringBuilder.Append('\r'); num++; break; } } } else { stringBuilder.Append(c); } } return stringBuilder.ToString(); } private static IDictionary<string, object> ParseObject(char[] json, ref int index, ref bool success) { IDictionary<string, object> dictionary = new JsonObject(); NextToken(json, ref index); bool flag = false; while (!flag) { switch (LookAhead(json, index)) { case 0: success = false; return null; case 6: NextToken(json, ref index); continue; case 2: NextToken(json, ref index); return dictionary; } string key = ParseString(json, ref index, ref success); if (!success) { success = false; return null; } int num = NextToken(json, ref index); if (num != 5) { success = false; return null; } object value = ParseValue(json, ref index, ref success); if (!success) { success = false; return null; } dictionary[key] = value; } return dictionary; } private static JsonArray ParseArray(char[] json, ref int index, ref bool success) { JsonArray jsonArray = new JsonArray(); NextToken(json, ref index); bool flag = false; while (!flag) { switch (LookAhead(json, index)) { case 0: success = false; return null; case 6: NextToken(json, ref index); continue; case 4: break; default: { object item = ParseValue(json, ref index, ref success); if (!success) { return null; } jsonArray.Add(item); continue; } } NextToken(json, ref index); break; } return jsonArray; } private static object ParseValue(char[] json, ref int index, ref bool success) { switch (LookAhead(json, index)) { case 7: return ParseString(json, ref index, ref success); case 8: return ParseNumber(json, ref index, ref success); case 1: return ParseObject(json, ref index, ref success); case 3: return ParseArray(json, ref index, ref success); case 9: NextToken(json, ref index); return true; case 10: NextToken(json, ref index); return false; case 11: NextToken(json, ref index); return null; default: success = false; return null; } } private static string ParseString(char[] json, ref int index, ref bool success) { StringBuilder stringBuilder = new StringBuilder(2000); EatWhitespace(json, ref index); char c = json[index++]; bool flag = false; while (!flag && index != json.Length) { c = json[index++]; switch (c) { case '"': flag = true; break; case '\\': { if (index == json.Length) { break; } switch (json[index++]) { case '"': stringBuilder.Append('"'); continue; case '\\': stringBuilder.Append('\\'); continue; case '/': stringBuilder.Append('/'); continue; case 'b': stringBuilder.Append('\b'); continue; case 'f': stringBuilder.Append('\f'); continue; case 'n': stringBuilder.Append('\n'); continue; case 'r': stringBuilder.Append('\r'); continue; case 't': stringBuilder.Append('\t'); continue; case 'u': break; default: continue; } int num = json.Length - index; if (num < 4) { break; } if (!(success = uint.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))) { return ""; } if (55296 <= result && result <= 56319) { index += 4; num = json.Length - index; if (num < 6 || !(new string(json, index, 2) == "\\u") || !uint.TryParse(new string(json, index + 2, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result2) || 56320 > result2 || result2 > 57343) { success = false; return ""; } stringBuilder.Append((char)result); stringBuilder.Append((char)result2); index += 6; } else { stringBuilder.Append(ConvertFromUtf32((int)result)); index += 4; } continue; } default: stringBuilder.Append(c); continue; } break; } if (!flag) { success = false; return null; } return stringBuilder.ToString(); } private static string ConvertFromUtf32(int utf32) { if (utf32 < 0 || utf32 > 1114111) { throw new ArgumentOutOfRangeException("utf32", "The argument must be from 0 to 0x10FFFF."); } if (55296 <= utf32 && utf32 <= 57343) { throw new ArgumentOutOfRangeException("utf32", "The argument must not be in surrogate pair range."); } if (utf32 < 65536) { return new string((char)utf32, 1); } utf32 -= 65536; return new string(new char[2] { (char)((utf32 >> 10) + 55296), (char)(utf32 % 1024 + 56320) }); } private static object ParseNumber(char[] json, ref int index, ref bool success) { EatWhitespace(json, ref index); int lastIndexOfNumber = GetLastIndexOfNumber(json, index); int length = lastIndexOfNumber - index + 1; string text = new string(json, index, length); object result2; if (text.IndexOf(".", StringComparison.OrdinalIgnoreCase) != -1 || text.IndexOf("e", StringComparison.OrdinalIgnoreCase) != -1) { success = double.TryParse(new string(json, index, length), NumberStyles.Any, CultureInfo.InvariantCulture, out var result); result2 = result; } else { success = long.TryParse(new string(json, index, length), NumberStyles.Any, CultureInfo.InvariantCulture, out var result3); result2 = result3; } index = lastIndexOfNumber + 1; return result2; } private static int GetLastIndexOfNumber(char[] json, int index) { int i; for (i = index; i < json.Length && "0123456789+-.eE".IndexOf(json[i]) != -1; i++) { } return i - 1; } private static void EatWhitespace(char[] json, ref int index) { while (index < json.Length && " \t\n\r\b\f".IndexOf(json[index]) != -1) { index++; } } private static int LookAhead(char[] json, int index) { int index2 = index; return NextToken(json, ref index2); } private static int NextToken(char[] json, ref int index) { EatWhitespace(json, ref index); if (index == json.Length) { return 0; } char c = json[index]; index++; switch (c) { case '{': return 1; case '}': return 2; case '[': return 3; case ']': return 4; case ',': return 6; case '"': return 7; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return 8; case ':': return 5; default: { index--; int num = json.Length - index; if (num >= 5 && json[index] == 'f' && json[index + 1] == 'a' && json[index + 2] == 'l' && json[index + 3] == 's' && json[index + 4] == 'e') { index += 5; return 10; } if (num >= 4 && json[index] == 't' && json[index + 1] == 'r' && json[index + 2] == 'u' && json[index + 3] == 'e') { index += 4; return 9; } if (num >= 4 && json[index] == 'n' && json[index + 1] == 'u' && json[index + 2] == 'l' && json[index + 3] == 'l') { index += 4; return 11; } return 0; } } } private static bool SerializeValue(IJsonSerializerStrategy jsonSerializerStrategy, object value, StringBuilder builder) { bool flag = true; if (value is string aString) { flag = SerializeString(aString, builder); } else if (value is IDictionary<string, object> dictionary) { flag = SerializeObject(jsonSerializerStrategy, dictionary.Keys, dictionary.Values, builder); } else if (value is IDictionary<string, string> dictionary2) { flag = SerializeObject(jsonSerializerStrategy, dictionary2.Keys, dictionary2.Values, builder); } else if (value is IEnumerable anArray) { flag = SerializeArray(jsonSerializerStrategy, anArray, builder); } else if (IsNumeric(value)) { flag = SerializeNumber(value, builder); } else if (value is bool) { builder.Append(((bool)value) ? "true" : "false"); } else if (value == null) { builder.Append("null"); } else { flag = jsonSerializerStrategy.TrySerializeNonPrimitiveObject(value, out var output); if (flag) { SerializeValue(jsonSerializerStrategy, output, builder); } } return flag; } private static bool SerializeObject(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable keys, IEnumerable values, StringBuilder builder) { builder.Append("{"); IEnumerator enumerator = keys.GetEnumerator(); IEnumerator enumerator2 = values.GetEnumerator(); bool flag = true; while (enumerator.MoveNext() && enumerator2.MoveNext()) { object current = enumerator.Current; object current2 = enumerator2.Current; if (!flag) { builder.Append(","); } if (current is string aString) { SerializeString(aString, builder); } else if (!SerializeValue(jsonSerializerStrategy, current2, builder)) { return false; } builder.Append(":"); if (!SerializeValue(jsonSerializerStrategy, current2, builder)) { return false; } flag = false; } builder.Append("}"); return true; } private static bool SerializeArray(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable anArray, StringBuilder builder) { builder.Append("["); bool flag = true; foreach (object item in anArray) { if (!flag) { builder.Append(","); } if (!SerializeValue(jsonSerializerStrategy, item, builder)) { return false; } flag = false; } builder.Append("]"); return true; } private static bool SerializeString(string aString, StringBuilder builder) { if (aString.IndexOfAny(EscapeCharacters) == -1) { builder.Append('"'); builder.Append(aString); builder.Append('"'); return true; } builder.Append('"'); int num = 0; char[] array = aString.ToCharArray(); for (int i = 0; i < array.Length; i++) { char c = array[i]; if (c >= EscapeTable.Length || EscapeTable[(uint)c] == '\0') { num++; continue; } if (num > 0) { builder.Append(array, i - num, num); num = 0; } builder.Append('\\'); builder.Append(EscapeTable[(uint)c]); } if (num > 0) { builder.Append(array, array.Length - num, num); } builder.Append('"'); return true; } private static bool SerializeNumber(object number, StringBuilder builder) { if (number is long) { builder.Append(((long)number).ToString(CultureInfo.InvariantCulture)); } else if (number is ulong) { builder.Append(((ulong)number).ToString(CultureInfo.InvariantCulture)); } else if (number is int) { builder.Append(((int)number).ToString(CultureInfo.InvariantCulture)); } else if (number is uint) { builder.Append(((uint)number).ToString(CultureInfo.InvariantCulture)); } else if (number is decimal) { builder.Append(((decimal)number).ToString(CultureInfo.InvariantCulture)); } else if (number is float) { builder.Append(((float)number).ToString(CultureInfo.InvariantCulture)); } else { builder.Append(Convert.ToDouble(number, CultureInfo.InvariantCulture).ToString("r", CultureInfo.InvariantCulture)); } return true; } private static bool IsNumeric(object value) { if (value is sbyte) { return true; } if (value is byte) { return true; } if (value is short) { return true; } if (value is ushort) { return true; } if (value is int) { return true; } if (value is uint) { return true; } if (value is long) { return true; } if (value is ulong) { return true; } if (value is float) { return true; } if (value is double) { return true; } if (value is decimal) { return true; } return false; } } [GeneratedCode("simple-json", "1.0.0")] public interface IJsonSerializerStrategy { bool TrySerializeNonPrimitiveObject(object input, out object output); object DeserializeObject(object value, Type type); } [GeneratedCode("simple-json", "1.0.0")] public class PocoJsonSerializerStrategy : IJsonSerializerStrategy { internal IDictionary<Type, ReflectionUtils.ConstructorDelegate> ConstructorCache; internal IDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>> GetCache; internal IDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>> SetCache; internal static readonly Type[] EmptyTypes = new Type[0]; internal static readonly Type[] ArrayConstructorParameterTypes = new Type[1] { typeof(int) }; private static readonly string[] Iso8601Format = new string[3] { "yyyy-MM-dd\\THH:mm:ss.FFFFFFF\\Z", "yyyy-MM-dd\\THH:mm:ss\\Z", "yyyy-MM-dd\\THH:mm:ssK" }; public PocoJsonSerializerStrategy() { ConstructorCache = new ReflectionUtils.ThreadSafeDictionary<Type, ReflectionUtils.ConstructorDelegate>(ContructorDelegateFactory); GetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>>(GetterValueFactory); SetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>>(SetterValueFactory); } protected virtual string MapClrMemberNameToJsonFieldName(string clrPropertyName) { return clrPropertyName; } internal virtual ReflectionUtils.ConstructorDelegate ContructorDelegateFactory(Type key) { return ReflectionUtils.GetContructor(key, key.IsArray ? ArrayConstructorParameterTypes : EmptyTypes); } internal virtual IDictionary<string, ReflectionUtils.GetDelegate> GetterValueFactory(Type type) { IDictionary<string, ReflectionUtils.GetDelegate> dictionary = new Dictionary<string, ReflectionUtils.GetDelegate>(); foreach (PropertyInfo property in ReflectionUtils.GetProperties(type)) { if (property.CanRead) { MethodInfo getterMethodInfo = ReflectionUtils.GetGetterMethodInfo(property); if (!getterMethodInfo.IsStatic && getterMethodInfo.IsPublic) { dictionary[MapClrMemberNameToJsonFieldName(property.Name)] = ReflectionUtils.GetGetMethod(property); } } } foreach (FieldInfo field in ReflectionUtils.GetFields(type)) { if (!field.IsStatic && field.IsPublic) { dictionary[MapClrMemberNameToJsonFieldName(field.Name)] = ReflectionUtils.GetGetMethod(field); } } return dictionary; } internal virtual IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> SetterValueFactory(Type type) { IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> dictionary = new Dictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>(); foreach (PropertyInfo property in ReflectionUtils.GetProperties(type)) { if (property.CanWrite) { MethodInfo setterMethodInfo = ReflectionUtils.GetSetterMethodInfo(property); if (!setterMethodInfo.IsStatic && setterMethodInfo.IsPublic) { dictionary[MapClrMemberNameToJsonFieldName(property.Name)] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(property.PropertyType, ReflectionUtils.GetSetMethod(property)); } } } foreach (FieldInfo field in ReflectionUtils.GetFields(type)) { if (!field.IsInitOnly && !field.IsStatic && field.IsPublic) { dictionary[MapClrMemberNameToJsonFieldName(field.Name)] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(field.FieldType, ReflectionUtils.GetSetMethod(field)); } } return dictionary; } public virtual bool TrySerializeNonPrimitiveObject(object input, out object output) { if (!TrySerializeKnownTypes(input, out output)) { return TrySerializeUnknownTypes(input, out output); } return true; } public virtual object DeserializeObject(object value, Type type) { if (type == null) { throw new ArgumentNullException("type"); } string text = value as string; if (type == typeof(Guid) && string.IsNullOrEmpty(text)) { return default(Guid); } if (value == null) { return null; } object obj = null; if (text != null) { if (text.Length != 0) { if (type == typeof(DateTime) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTime))) { return DateTime.ParseExact(text, Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); } if (type == typeof(DateTimeOffset) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTimeOffset))) { return DateTimeOffset.ParseExact(text, Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); } if (type == typeof(Guid) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid))) { return new Guid(text); } if (type == typeof(Uri)) { if (Uri.IsWellFormedUriString(text, UriKind.RelativeOrAbsolute) && Uri.TryCreate(text, UriKind.RelativeOrAbsolute, out Uri result)) { return result; } return null; } if (type == typeof(string)) { return text; } return Convert.ChangeType(text, type, CultureInfo.InvariantCulture); } obj = ((type == typeof(Guid)) ? ((object)default(Guid)) : ((!ReflectionUtils.IsNullableType(type) || !(Nullable.GetUnderlyingType(type) == typeof(Guid))) ? text : null)); if (!ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid)) { return text; } } else if (value is bool) { return value; } bool flag = value is long; bool flag2 = value is double; if ((flag && type == typeof(long)) || (flag2 && type == typeof(double))) { return value; } if ((flag2 && type != typeof(double)) || (flag && type != typeof(long))) { obj = ((type == typeof(int) || type == typeof(long) || type == typeof(double) || type == typeof(float) || type == typeof(bool) || type == typeof(decimal) || type == typeof(byte) || type == typeof(short)) ? Convert.ChangeType(value, type, CultureInfo.InvariantCulture) : value); if (ReflectionUtils.IsNullableType(type)) { return ReflectionUtils.ToNullableType(obj, type); } return obj; } if (value is IDictionary<string, object> dictionary) { IDictionary<string, object> dictionary2 = dictionary; if (ReflectionUtils.IsTypeDictionary(type)) { Type[] genericTypeArguments = ReflectionUtils.GetGenericTypeArguments(type); Type type2 = genericTypeArguments[0]; Type type3 = genericTypeArguments[1]; Type key = typeof(Dictionary<, >).MakeGenericType(type2, type3); IDictionary dictionary3 = (IDictionary)ConstructorCache[key](); foreach (KeyValuePair<string, object> item in dictionary2) { dictionary3.Add(item.Key, DeserializeObject(item.Value, type3)); } obj = dictionary3; } else if (type == typeof(object)) { obj = value; } else { obj = ConstructorCache[type](); foreach (KeyValuePair<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> item2 in SetCache[type]) { if (dictionary2.TryGetValue(item2.Key, out var value2)) { value2 = DeserializeObject(value2, item2.Value.Key); item2.Value.Value(obj, value2); } } } } else if (value is IList<object> list) { IList<object> list2 = list; IList list3 = null; if (type.IsArray) { list3 = (IList)ConstructorCache[type](list2.Count); int num = 0; foreach (object item3 in list2) { list3[num++] = DeserializeObject(item3, type.GetElementType()); } } else if (ReflectionUtils.IsTypeGenericeCollectionInterface(type) || ReflectionUtils.IsAssignableFrom(typeof(IList), type)) { Type genericListElementType = ReflectionUtils.GetGenericListElementType(type); list3 = (IList)(ConstructorCache[type] ?? ConstructorCache[typeof(List<>).MakeGenericType(genericListElementType)])(list2.Count); foreach (object item4 in list2) { list3.Add(DeserializeObject(item4, genericListElementType)); } } obj = list3; } return obj; } protected virtual object SerializeEnum(Enum p) { return Convert.ToDouble(p, CultureInfo.InvariantCulture); } protected virtual bool TrySerializeKnownTypes(object input, out object output) { bool result = true; if (input is DateTime) { output = ((DateTime)input).ToUniversalTime().ToString(Iso8601Format[0], CultureInfo.InvariantCulture); } else if (input is DateTimeOffset) { output = ((DateTimeOffset)input).ToUniversalTime().ToString(Iso8601Format[0], CultureInfo.InvariantCulture); } else if (input is Guid) { output = ((Guid)input).ToString("D"); } else if (input is Uri) { output = input.ToString(); } else if (input is Enum p) { output = SerializeEnum(p); } else { result = false; output = null; } return result; } protected virtual bool TrySerializeUnknownTypes(object input, out object output) { if (input == null) { throw new ArgumentNullException("input"); } output = null; Type type = input.GetType(); if (type.FullName == null) { return false; } IDictionary<string, object> dictionary = new JsonObject(); IDictionary<string, ReflectionUtils.GetDelegate> dictionary2 = GetCache[type]; foreach (KeyValuePair<string, ReflectionUtils.GetDelegate> item in dictionary2) { if (item.Value != null) { dictionary.Add(MapClrMemberNameToJsonFieldName(item.Key), item.Value(input)); } } output = dictionary; return true; } } } namespace SimpleJson.Reflection { [GeneratedCode("reflection-utils", "1.0.0")] internal class ReflectionUtils { public delegate object GetDelegate(object source); public delegate void SetDelegate(object source, object value); public delegate object ConstructorDelegate(params object[] args); public delegate TValue ThreadSafeDictionaryValueFactory<TKey, TValue>(TKey key); private static class Assigner<T> { public static T Assign(ref T left, T right) { return left = right; } } public sealed class ThreadSafeDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable { private readonly object _lock = new object(); private readonly ThreadSafeDictionaryValueFactory<TKey, TValue> _valueFactory; private Dictionary<TKey, TValue> _dictionary; public ICollection<TKey> Keys => _dictionary.Keys; public ICollection<TValue> Values => _dictionary.Values; public TValue this[TKey key] { get { return Get(key); } set { throw new NotImplementedException(); } } public int Count => _dictionary.Count; public bool IsReadOnly { get { throw new NotImplementedException(); } } public ThreadSafeDictionary(ThreadSafeDictionaryValueFactory<TKey, TValue> valueFactory) { _valueFactory = valueFactory; } private TValue Get(TKey key) { if (_dictionary == null) { return AddValue(key); } if (!_dictionary.TryGetValue(key, out var value)) { return AddValue(key); } return value; } private TValue AddValue(TKey key) { TValue val = _valueFactory(key); lock (_lock) { if (_dictionary == null) { _dictionary = new Dictionary<TKey, TValue>(); _dictionary[key] = val; } else { if (_dictionary.TryGetValue(key, out var value)) { return value; } Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>(_dictionary); dictionary[key] = val; _dictionary = dictionary; } } return val; } public void Add(TKey key, TValue value) { throw new NotImplementedException(); } public bool ContainsKey(TKey key) { return _dictionary.ContainsKey(key); } public bool Remove(TKey key) { throw new NotImplementedException(); } public bool TryGetValue(TKey key, out TValue value) { value = this[key]; return true; } public void Add(KeyValuePair<TKey, TValue> item) { throw new NotImplementedException(); } public void Clear() { throw new NotImplementedException(); } public bool Contains(KeyValuePair<TKey, TValue> item) { throw new NotImplementedException(); } public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { throw new NotImplementedException(); } public bool Remove(KeyValuePair<TKey, TValue> item) { throw new NotImplementedException(); } public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return _dictionary.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _dictionary.GetEnumerator(); } } private static readonly object[] EmptyObjects = new object[0]; public static Type GetTypeInfo(Type type) { return type; } public static Attribute GetAttribute(MemberInfo info, Type type) { if (info == null || type == null || !Attribute.IsDefined(info, type)) { return null; } return Attribute.GetCustomAttribute(info, type); } public static Type GetGenericListElementType(Type type) { IEnumerable<Type> interfaces = type.GetInterfaces(); foreach (Type item in interfaces) { if (IsTypeGeneric(item) && item.GetGenericTypeDefinition() == typeof(IList<>)) { return GetGenericTypeArguments(item)[0]; } } return GetGenericTypeArguments(type)[0]; } public static Attribute GetAttribute(Type objectType, Type attributeType) { if (objectType == null || attributeType == null || !Attribute.IsDefined(objectType, attributeType)) { return null; } return Attribute.GetCustomAttribute(objectType, attributeType); } public static Type[] GetGenericTypeArguments(Type type) { return type.GetGenericArguments(); } public static bool IsTypeGeneric(Type type) { return GetTypeInfo(type).IsGenericType; } public static bool IsTypeGenericeCollectionInterface(Type type) { if (!IsTypeGeneric(type)) { return false; } Type genericTypeDefinition = type.GetGenericTypeDefinition(); if (!(genericTypeDefinition == typeof(IList<>)) && !(genericTypeDefinition == typeof(ICollection<>))) { return genericTypeDefinition == typeof(IEnumerable<>); } return true; } public static bool IsAssignableFrom(Type type1, Type type2) { return GetTypeInfo(type1).IsAssignableFrom(GetTypeInfo(type2)); } public static bool IsTypeDictionary(Type type) { if (typeof(IDictionary).IsAssignableFrom(type)) { return true; } if (!GetTypeInfo(type).IsGenericType) { return false; } Type genericTypeDefinition = type.GetGenericTypeDefinition(); return genericTypeDefinition == typeof(IDictionary<, >); } public static bool IsNullableType(Type type) { if (GetTypeInfo(type).IsGenericType) { return type.GetGenericTypeDefinition() == typeof(Nullable<>); } return false; } public static object ToNullableType(object obj, Type nullableType) { if (obj != null) { return Convert.ChangeType(obj, Nullable.GetUnderlyingType(nullableType), CultureInfo.InvariantCulture); } return null; } public static bool IsValueType(Type type) { return GetTypeInfo(type).IsValueType; } public static IEnumerable<ConstructorInfo> GetConstructors(Type type) { return type.GetConstructors(); } public static ConstructorInfo GetConstructorInfo(Type type, params Type[] argsType) { IEnumerable<ConstructorInfo> constructors = GetConstructors(type); foreach (ConstructorInfo item in constructors) { ParameterInfo[] parameters = item.GetParameters(); if (argsType.Length != parameters.Length) { continue; } int num = 0; bool flag = true; ParameterInfo[] parameters2 = item.GetParameters(); foreach (ParameterInfo parameterInfo in parameters2) { if (parameterInfo.ParameterType != argsType[num]) { flag = false; break; } } if (flag) { return item; } } return null; } public static IEnumerable<PropertyInfo> GetProperties(Type type) { return type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } public static IEnumerable<FieldInfo> GetFields(Type type) { return type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } public static MethodInfo GetGetterMethodInfo(PropertyInfo propertyInfo) { return propertyInfo.GetGetMethod(nonPublic: true); } public static MethodInfo GetSetterMethodInfo(PropertyInfo propertyInfo) { return propertyInfo.GetSetMethod(nonPublic: true); } public static ConstructorDelegate GetContructor(ConstructorInfo constructorInfo) { return GetConstructorByExpression(constructorInfo); } public static ConstructorDelegate GetContructor(Type type, params Type[] argsType) { return GetConstructorByExpression(type, argsType); } public static ConstructorDelegate GetConstructorByReflection(ConstructorInfo constructorInfo) { return (object[] args) => constructorInfo.Invoke(args); } public static ConstructorDelegate GetConstructorByReflection(Type type, params Type[] argsType) { ConstructorInfo constructorInfo = GetConstructorInfo(type, argsType); if (!(constructorInfo == null)) { return GetConstructorByReflection(constructorInfo); } return null; } public static ConstructorDelegate GetConstructorByExpression(ConstructorInfo constructorInfo) { ParameterInfo[] parameters = constructorInfo.GetParameters(); ParameterExpression parameterExpression = Expression.Parameter(typeof(object[]), "args"); Expression[] array = new Expression[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Expression index = Expression.Constant(i); Type parameterType = parameters[i].ParameterType; Expression expression = Expression.ArrayIndex(parameterExpression, index); Expression expression2 = Expression.Convert(expression, parameterType); array[i] = expression2; } NewExpression body = Expression.New(constructorInfo, array); Expression<Func<object[], object>> expression3 = Expression.Lambda<Func<object[], object>>(body, new ParameterExpression[1] { parameterExpression }); Func<object[], object> compiledLambda = expression3.Compile(); return (object[] args) => compiledLambda(args); } public static ConstructorDelegate GetConstructorByExpression(Type type, params Type[] argsType) { ConstructorInfo constructorInfo = GetConstructorInfo(type, argsType); if (!(constructorInfo == null)) { return GetConstructorByExpression(constructorInfo); } return null; } public static GetDelegate GetGetMethod(PropertyInfo propertyInfo) { return GetGetMethodByExpression(propertyInfo); } public static GetDelegate GetGetMethod(FieldInfo fieldInfo) { return GetGetMethodByExpression(fieldInfo); } public static GetDelegate GetGetMethodByReflection(PropertyInfo propertyInfo) { MethodInfo methodInfo = GetGetterMethodInfo(propertyInfo); return (object source) => methodInfo.Invoke(source, EmptyObjects); } public static GetDelegate GetGetMethodByReflection(FieldInfo fieldInfo) { return (object source) => fieldInfo.GetValue(source); } public static GetDelegate GetGetMethodByExpression(PropertyInfo propertyInfo) { MethodInfo getterMethodInfo = GetGetterMethodInfo(propertyInfo); ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance"); UnaryExpression instance = ((!IsValueType(propertyInfo.DeclaringType)) ? Expression.TypeAs(parameterExpression, propertyInfo.DeclaringType) : Expression.Convert(parameterExpression, propertyInfo.DeclaringType)); Func<object, object> compiled = Expression.Lambda<Func<object, object>>(Expression.TypeAs(Expression.Call(instance, getterMethodInfo), typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile(); return (object source) => compiled(source); } public static GetDelegate GetGetMethodByExpression(FieldInfo fieldInfo) { ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance"); MemberExpression expression = Expression.Field(Expression.Convert(parameterExpression, fieldInfo.DeclaringType), fieldInfo); GetDelegate compiled = Expression.Lambda<GetDelegate>(Expression.Convert(expression, typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile(); return (object source) => compiled(source); } public static SetDelegate GetSetMethod(PropertyInfo propertyInfo) { return GetSetMethodByExpression(propertyInfo); } public static SetDelegate GetSetMethod(FieldInfo fieldInfo) { return GetSetMethodByExpression(fieldInfo); } public static SetDelegate GetSetMethodByReflection(PropertyInfo propertyInfo) { MethodInfo methodInfo = GetSetterMethodInfo(propertyInfo); return delegate(object source, object value) { methodInfo.Invoke(source, new object[1] { value }); }; } public static SetDelegate GetSetMethodByReflection(FieldInfo fieldInfo) { return delegate(object source, object value) { fieldInfo.SetValue(source, value); }; } public static SetDelegate GetSetMethodByExpression(PropertyInfo propertyInfo) { MethodInfo setterMethodInfo = GetSetterMethodInfo(propertyInfo); ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value"); UnaryExpression instance = ((!IsValueType(propertyInfo.DeclaringType)) ? Expression.TypeAs(parameterExpression, propertyInfo.DeclaringType) : Expression.Convert(parameterExpression, propertyInfo.DeclaringType)); UnaryExpression unaryExpression = ((!IsValueType(propertyInfo.PropertyType)) ? Expression.TypeAs(parameterExpression2, propertyInfo.PropertyType) : Expression.Convert(parameterExpression2, propertyInfo.PropertyType)); Action<object, object> compiled = Expression.Lambda<Action<object, object>>(Expression.Call(instance, setterMethodInfo, unaryExpression), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); return delegate(object source, object val) { compiled(source, val); }; } public static SetDelegate GetSetMethodByExpression(FieldInfo fieldInfo) { ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value"); Action<object, object> compiled = Expression.Lambda<Action<object, object>>(Assign(Expression.Field(Expression.Convert(parameterExpression, fieldInfo.DeclaringType), fieldInfo), Expression.Convert(parameterExpression2, fieldInfo.FieldType)), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); return delegate(object source, object val) { compiled(source, val); }; } public static BinaryExpression Assign(Expression left, Expression right) { MethodInfo method = typeof(Assigner<>).MakeGenericType(left.Type).GetMethod("Assign"); return Expression.Add(left, right, method); } } } namespace Jotunn { public static class ArrayExtensions { public static T[] Populate<T>(this T[] arr, T value) { for (int i = 0; i < arr.Length; i++) { arr[i] = value; } return arr; } } public static class ConfigEntryBaseExtension { public static bool IsVisible(this ConfigEntryBase configurationEntry) { ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes(); ConfigDescription description = configurationEntry.Description; configurationManagerAttributes.SetFromAttributes((description != null) ? description.Tags : null); return configurationManagerAttributes.Browsable != false; } public static bool IsSyncable(this ConfigEntryBase configurationEntry) { if (configurationEntry.Description.Tags.FirstOrDefault((object x) => x is ConfigurationManagerAttributes) is ConfigurationManagerAttributes configurationManagerAttributes) { return configurationManagerAttributes.IsAdminOnly; } return false; } public static string GetBoundButtonName(this ConfigEntryBase configurationEntry) { if (configurationEntry == null) { throw new ArgumentNullException("configurationEntry"); } if (configurationEntry.SettingType != typeof(KeyCode) && configurationEntry.SettingType != typeof(KeyboardShortcut) && configurationEntry.SettingType != typeof(InputManager.GamepadButton)) { return null; } if (!InputManager.ButtonToConfigDict.TryGetValue(configurationEntry, out var value)) { return null; } return value.Name; } public static ButtonConfig GetButtonConfig(this ConfigEntryBase configurationEntry) { if (configurationEntry == null) { throw new ArgumentNullException("configurationEntry"); } if (configurationEntry.SettingType != typeof(KeyCode) && configurationEntry.SettingType != typeof(KeyboardShortcut) && configurationEntry.SettingType != typeof(InputManager.GamepadButton)) { return null; } InputManager.ButtonToConfigDict.TryGetValue(configurationEntry, out var value); return value; } internal static object GetLocalValue(this ConfigEntryBase configurationEntry) { if (SynchronizationManager.Instance.localValues.TryGetValue(configurationEntry, out var value)) { return value; } return null; } internal static void SetLocalValue(this ConfigEntryBase configurationEntry, object value) { SynchronizationManager.Instance.localValues[configurationEntry] = value; } internal static ConfigurationManagerAttributes GetConfigurationManagerAttributes(this ConfigEntryBase configEntry) { return (ConfigurationManagerAttributes)configEntry.Description.Tags.FirstOrDefault((object x) => x is ConfigurationManagerAttributes); } } internal static class EventExtensions { public static void SafeInvoke(this Action events) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action action = (Action)invocationList[i]; try { action(); } catch (Exception ex) { Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}"); } } } public static void SafeInvoke<TArg1>(this Action<TArg1> events, TArg1 arg1) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action<TArg1> action = (Action<TArg1>)invocationList[i]; try { action(arg1); } catch (Exception ex) { Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}"); } } } public static void SafeInvoke<TArg1, TArg2>(this Action<TArg1, TArg2> events, TArg1 arg1, TArg2 arg2) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action<TArg1, TArg2> action = (Action<TArg1, TArg2>)invocationList[i]; try { action(arg1, arg2); } catch (Exception ex) { Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}"); } } } public static void SafeInvoke<TEventArg>(this EventHandler<TEventArg> events, object sender, TEventArg arg1) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { EventHandler<TEventArg> eventHandler = (EventHandler<TEventArg>)invocationList[i]; try { eventHandler(sender, arg1); } catch (Exception ex) { Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {eventHandler.Method.DeclaringType.Name}.{eventHandler.Method.Name}:\n{ex}"); } } } } public static class ExposedGameObjectExtension { public static GameObject OrNull(this GameObject @this) { if (!Object.op_Implicit((Object)(object)@this)) { return null; } return @this; } public static T OrNull<T>(this T @this) where T : Object { if (!Object.op_Implicit((Object)(object)@this)) { return default(T); } return @this; } public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component { T result = default(T); if (!gameObject.TryGetComponent<T>(ref result)) { return gameObject.AddComponent<T>(); } return result; } public static Component AddComponentCopy<T>(this GameObject gameObject, T duplicate) where T : Component { Component val = gameObject.AddComponent(((object)duplicate).GetType()); PropertyInfo[] properties = ((object)duplicate).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { switch (propertyInfo.Name) { case "mesh": if (duplicate is MeshFilter) { continue; } break; case "material": case "materials": if (duplicate is Renderer) { continue; } break; case "bounds": if (duplicate is Renderer) { continue; } break; case "name": case "rayTracingMode": case "tag": continue; } if (propertyInfo.CanWrite && propertyInfo.GetMethod != null) { propertyInfo.SetValue(val, propertyInfo.GetValue(duplicate)); } } FieldInfo[] fields = ((object)duplicate).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (!(fieldInfo.Name == "rayTracingMode")) { fieldInfo.SetValue(val, fieldInfo.GetValue(duplicate)); } } return val; } public static bool HasAnyComponent(this GameObject gameObject, params Type[] components) { foreach (Type type in components) { if (Object.op_Implicit((Object)(object)gameObject.GetComponent(type))) { return true; } } return false; } public static bool HasAnyComponent(this GameObject gameObject, params string[] componentNames) { foreach (string text in componentNames) { if (Object.op_Implicit((Object)(object)gameObject.GetComponent(text))) { return true; } } return false; } public static bool HasAllComponents(this GameObject gameObject, params string[] componentNames) { foreach (string text in componentNames) { if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(text))) { return false; } } return true; } public static bool HasAllComponents(this GameObject gameObject, params Type[] components) { foreach (Type type in components) { if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(type))) { return false; } } return true; } public static bool HasAnyComponentInChildren(this GameObject gameObject, bool includeInactive = false, params Type[] components) { foreach (Type type in components) { if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren(type, includeInactive))) { return true; } } return false; } public static Transform FindDeepChild(this GameObject gameObject, string childName, IterativeSearchType searchType = 1) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return gameObject.transform.FindDeepChild(childName, searchType); } public static Transform FindDeepChild(this GameObject gameObject, IEnumerable<string> childNames, IterativeSearchType searchType = 1) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) Transform val = gameObject.transform; foreach (string childName in childNames) { val = val.FindDeepChild(childName, searchType); if (!Object.op_Implicit((Object)(object)val)) { return null; } } return val; } } internal static class GameObjectGUIExtension { internal static GameObject SetToTextHeight(this GameObject go) { go.GetComponent<RectTransform>().SetSizeWithCurrentAnchors((Axis)1, go.GetComponentInChildren<Text>().preferredHeight + 3f); return go; } internal static GameObject SetUpperLeft(this GameObject go) { //IL_0012: 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) //IL_003c: 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) RectTransform component = go.GetComponent<RectTransform>(); component.anchorMax = new Vector2(0f, 1f); component.anchorMin = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); component.anchoredPosition = new Vector2(0f, 0f); return go; } internal static GameObject SetMiddleLeft(this GameObject go) { //IL_0012: 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) //IL_003c: 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) RectTransform component = go.GetComponent<RectTransform>(); component.anchorMax = new Vector2(0f, 0.5f); component.anchorMin = new Vector2(0f, 0.5f); component.pivot = new Vector2(0f, 0.5f); component.anchoredPosition = new Vector2(0f, 0f); return go; } internal static GameObject SetBottomLeft(this GameObject go) { //IL_0012: 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) //IL_003c: 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) RectTransform component = go.GetComponent<RectTransform>(); component.anchorMax = new Vector2(0f, 0f); component.anchorMin = new Vector2(0f, 0f); component.pivot = new Vector2(0f, 0f); component.anchoredPosition = new Vector2(0f, 0f); return go; } internal static GameObject SetUpperRight(this GameObject go) { //IL_0012: 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) //IL_003c: 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) RectTransform component = go.GetComponent<RectTransform>(); component.anchorMax = new Vector2(1f, 1f); component.anchorMin = new Vector2(1f, 1f); component.pivot = new Vector2(1f, 1f); component.anchoredPosition = new Vector2(0f, 0f); return go; } internal static GameObject SetMiddleRight(this GameObject go) { //IL_0012: 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) //IL_003c: 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) RectTransform component = go.GetComponent<RectTransform>(); component.anchorMax = new Vector2(1f, 0.5f); component.anchorMin = new Vector2(1f, 0.5f); component.pivot = new Vector2(1f, 0.5f); component.anchoredPosition = new Vector2(0f, 0f); return go; } internal static GameObject SetBottomRight(this GameObject go) { //IL_0012: 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) //IL_003c: 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) RectTransform component = go.GetComponent<RectTransform>(); component.anchorMax = new Vector2(1f, 0f); component.anchorMin = new Vector2(1f, 0f); component.pivot = new Vector2(1f, 0f); component.anchoredPosition = new Vector2(0f, 0f); return go; } internal static GameObject SetUpperCenter(this GameObject go) { //IL_0012: 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) //IL_003c: 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) RectTransform component = go.GetComponent<RectTransform>(); component.anchorMax = new Vector2(0.5f, 1f); component.anchorMin = new Vector2(0.5f, 1f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = new Vector2(0f, 0f); return go; } internal static GameObject SetMiddleCenter(this GameObject go) { //IL_0012: 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) //IL_003c: 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) RectTransform component = go.GetComponent<RectTransform>(); component.anchorMax = new Vector2(0.5f, 0.5f); component.anchorMin = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = new Vector2(0f, 0f); return go; } internal static GameObject SetBottomCenter(this GameObject go) { //IL_0012: 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) //IL_003c: 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) RectTransform component = go.GetComponent<RectTransform>(); component.anchorMax = new Vector2(0.5f, 0f); component.anchorMin = new Vector2(0.5f, 0f); component.pivot = new Vector2(0.5f, 0f); component.anchoredPosition = new Vector2(0f, 0f); return go; } internal static GameObject SetSize(this GameObject go, float width, float height) { RectTransform component = go.GetComponent<RectTransform>(); component.SetSizeWithCurrentAnchors((Axis)0, width); component.SetSizeWithCurrentAnchors((Axis)1, height); return go; } internal static GameObject SetWidth(this GameObject go, float width) { RectTransform component = go.GetComponent<RectTransform>(); component.SetSizeWithCurrentAnchors((Axis)0, width); return go; } internal static GameObject SetHeight(this GameObject go, float height) { RectTransform component = go.GetComponent<RectTransform>(); component.SetSizeWithCurrentAnchors((Axis)1, height); return go; } internal static float GetWidth(this GameObject go) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) RectTransform component = go.GetComponent<RectTransform>(); Rect rect = component.rect; return ((Rect)(ref rect)).width; } internal static float GetHeight(this GameObject go) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) RectTransform component = go.GetComponent<RectTransform>(); Rect rect = component.rect; return ((Rect)(ref rect)).height; } internal static float GetTextHeight(this GameObject go) { return go.GetComponent<Text>().preferredHeight; } internal static GameObject SetText(this GameObject go, string text) { Text component = go.GetComponent<Text>(); if ((Object)(object)component != (Object)null) { component.text = text; } TMP_Text component2 = go.GetComponent<TMP_Text>(); if ((Object)(object)component2 != (Object)null) { component2.text = text; } return go; } } public static class GameObjectExtension { public static bool IsValid(this GameObject self) { string text = ((Object)self).name; if (text.IndexOf('(') > 0) { text = text.Substring(((Object)self).name.IndexOf('(')).Trim(); } if (string.IsNullOrEmpty(text)) { Logger.LogError("GameObject must have a name!"); return false; } if (Object.op_Implicit((Object)(object)self.GetComponent<ZNetView>()) && ((Object)self).name.IndexOfAny(new char[2] { ')', ' ' }) > 0) { Logger.LogError("GameObject name '" + ((Object)self).name + "' must not contain parenthesis or spaces!"); return false; } return true; } } public static class ItemDropExtension { public static string TokenName(this ItemDrop self) { return self.m_itemData.m_shared.m_name; } } public static class ItemDataExtension { public static string TokenName(this ItemData self) { return self.m_shared.m_name; } } public static class RecipeExtension { public static bool IsValid(this Recipe self) { try { string text = ((Object)self).name; if (text.IndexOf('(') > 0) { text = text.Substring(((Object)self).name.IndexOf('(')).Trim(); } if (string.IsNullOrEmpty(text)) { throw new Exception("Recipe must have a name !"); } return true; } catch (Exception data) { Logger.LogError(data); return false; } } } public static class PieceExtension { public static string TokenName(this Piece self) { return self.m_name; } } public static class StatusEffectExtension { public static string TokenName(this StatusEffect self) { return self.m_name; } public static bool IsValid(this StatusEffect self) { try { string text = ((Object)self).name; if (text.IndexOf('(') > 0) { text = text.Substring(((Object)self).name.IndexOf('(')).Trim(); } if (string.IsNullOrEmpty(text)) { throw new Exception("StatusEffect must have a name !"); } return true; } catch (Exception data) { Logger.LogError(data); return false; } } } public static class PrefabExtension { public static void FixReferences(this object objectToFix) { MockManager.FixReferences(objectToFix, 0); } public static void FixReferences(this GameObject gameObject) { gameObject.FixReferences(recursive: false); } public static void FixReferences(this GameObject gameObject, bool recursive) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown Component[] components = gameObject.GetComponents<Component>(); foreach (Component val in components) { if (!(val is Transform)) { MockManager.FixReferences(val, 0); } } if (!recursive) { return; } List<Tuple<Transform, GameObject>> list = new List<Tuple<Transform, GameObject>>(); foreach (Transform item in gameObject.transform) { Transform val2 = item; GameObject realPrefabFromMock = MockManager.GetRealPrefabFromMock<GameObject>((Object)(object)((Component)val2).gameObject); if (Object.op_Implicit((Object)(object)realPrefabFromMock)) { list.Add(new Tuple<Transform, GameObject>(val2, realPrefabFromMock)); } else { ((Component)val2).gameObject.FixReferences(recursive: true); } } foreach (Tuple<Transform, GameObject> item2 in list) { MockManager.ReplaceMockGameObject(item2.Item1, item2.Item2, gameObject); } } public static void CloneFields(this GameObject gameObject, GameObject objectToClone) { Dictionary<FieldInfo, object> dictionary = new Dictionary<FieldInfo, object>(); Component[] componentsInChildren = objectToClone.GetComponentsInChildren<Component>(); Component[] array = componentsInChildren; foreach (Component val in array) { FieldInfo[] fields = ((object)val).GetType().GetFields((BindingFlags)(-1)); foreach (FieldInfo fieldInfo in fields) { if (!fieldInfo.IsLiteral && !fieldInfo.IsInitOnly) { dictionary.Add(fieldInfo, fieldInfo.GetValue(val)); } } if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(((object)val).GetType()))) { gameObject.AddComponent(((object)val).GetType()); } } Component[] componentsInChildren2 = gameObject.GetComponentsInChildren<Component>(); Component[] array2 = componentsInChildren2; foreach (Component val2 in array2) { FieldInfo[] fields2 = ((object)val2).GetType().GetFields((BindingFlags)(-1)); foreach (FieldInfo fieldInfo2 in fields2) { if (dictionary.TryGetValue(fieldInfo2, out var value)) { fieldInfo2.SetValue(val2, value); } } } } } internal static class ObjectExtension { public static string GetObjectString(this object obj) { if (obj == null) { return "null"; } string text = $"{obj}"; Type type = obj.GetType(); IEnumerable<FieldInfo> enumerable = from f in type.GetFields() where f.IsPublic select f; foreach (FieldInfo item in enumerable) { object value = item.GetValue(obj); string text2 = ((value == null) ? "null" : value.ToString()); text = text + "\n " + item.Name + ": " + text2; } PropertyInfo[] properties = type.GetProperties(); PropertyInfo[] array = properties; foreach (PropertyInfo propertyInfo in array) { object value2 = propertyInfo.GetValue(obj, null); string text3 = ((value2 == null) ? "null" : value2.ToString()); text = text + "\n " + propertyInfo.Name + ": " + text3; } return text; } } public static class RectTransformExtensions { public static bool Overlaps(this RectTransform a, RectTransform b) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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) Rect val = a.WorldRect(); return ((Rect)(ref val)).Overlaps(b.WorldRect()); } public static bool Overlaps(this RectTransform a, RectTransform b, bool allowInverse) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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) Rect val = a.WorldRect(); return ((Rect)(ref val)).Overlaps(b.WorldRect(), allowInverse); } public static Rect WorldRect(this RectTransform rectTransform) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) //IL_0033: 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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) Vector2 sizeDelta = rectTransform.sizeDelta; float num = sizeDelta.x * ((Transform)rectTransform).lossyScale.x; float num2 = sizeDelta.y * ((Transform)rectTransform).lossyScale.y; Vector3 position = ((Transform)rectTransform).position; return new Rect(position.x - num / 2f, position.y - num2 / 2f, num, num2); } } public static class ZNetExtension { public enum ZNetInstanceType { Local, Client, Server } public static bool IsLocalInstance(this ZNet znet) { if (znet.IsServer()) { return !znet.IsDedicated(); } return false; } public static bool IsClientInstance(this ZNet znet) { if (!znet.IsServer()) { return !znet.IsDedicated(); } return false; } public static bool IsServerInstance(this ZNet znet) { if (znet.IsServer()) { return znet.IsDedicated(); } return false; } public static ZNetInstanceType GetInstanceType(this ZNet znet) { if (znet.IsLocalInstance()) { return ZNetInstanceType.Local; } if (znet.IsClientInstance()) { return ZNetInstanceType.Client; } return ZNetInstanceType.Server; } public static bool IsAdmin(this ZNet znet, long uid) { if (!Object.op_Implicit((Object)(object)znet)) { Logger.LogWarning("IsAdmin check failed: ZNet is null"); return false; } if (znet.m_adminList == null) { Logger.LogWarning("IsAdmin check failed: admin list is only available on the server"); return false; } ZNetPeer peer = znet.GetPeer(uid); if (peer == null) { Logger.LogWarning($"IsAdmin check failed: peer not found with id {uid}"); return false; } string hostName = peer.m_socket.GetHostName(); if (!string.IsNullOrEmpty(hostName)) { return znet.ListContainsId(znet.m_adminList, hostName); } return false; } } internal interface IManager { void Init(); } public class Logger { public static bool ShowDate = false; private static Logger instance = new Logger(); private readonly Dictionary<string, ManualLogSource> logger = new Dictionary<string, ManualLogSource>(); internal static void Destroy() { LogDebug("Destroying Logger"); foreach (KeyValuePair<string, ManualLogSource> item in instance.logger) { Logger.Sources.Remove((ILogSource)(object)item.Value); } instance.logger.Clear(); } private ManualLogSource GetLogger() { Type declaringType = new StackFrame(3).GetMethod().DeclaringType; if (!logger.TryGetValue(declaringType.FullName, out var value)) { value = Logger.CreateLogSource(declaringType.FullName); logger.Add(declaringType.FullName, value); } return value; } private static void Log(LogLevel level, BepInPlugin sourceMod, object data) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) string text = string.Empty; if (ShowDate) { text = text + "[" + DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo) + "] "; } if (sourceMod != null) { text = text + "[" + sourceMod.Name + "] "; } instance.GetLogger().Log(level, (object)$"{text}{data}"); } public static void LogFatal(object data) { Log((LogLevel)1, null, data); } public static void LogFatal(BepInPlugin sourceMod, object data) { Log((LogLevel)1, sourceMod, data); } public static void LogError(object data) { Log((LogLevel)2, null, data); } public static void LogError(BepInPlugin sourceMod, object data) { Log((LogLevel)2, sourceMod, data); } public static void LogWarning(object data) { Log((LogLevel)4, null, data); } public static void LogWarning(BepInPlugin sourceMod, object data) { Log((LogLevel)4, sourceMod, data); } public static void LogMessage(object data) { Log((LogLevel)8, null, data); } public static void LogMessage(BepInPlugin sourceMod, object data) { Log((LogLevel)8, sourceMod, data); } public static void LogInfo(object data) { Log((LogLevel)16, null, data); } public static void LogInfo(BepInPlugin sourceMod, object data) { Log((LogLevel)16, sourceMod, data); } public static void LogDebug(object data) { Log((LogLevel)32, null, data); } public static void LogDebug(BepInPlugin sourceMod, object data) { Log((LogLevel)32, sourceMod, data); } } [BepInPlugin("com.jotunn.jotunn", "Jotunn", "2.20.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(CompatibilityLevel.VersionCheckOnly, VersionStrictness.Minor)] public class Main : BaseUnityPlugin { public const string Version = "2.20.1"; public const string ModName = "Jotunn"; public const string ModGuid = "com.jotunn.jotunn"; internal static Main Instance; internal static Harmony Harmony = new Harmony("com.jotunn.jotunn"); private static GameObject rootObject; internal static GameObject RootObject => GetRootObject(); private void Awake() { Instance = this; GetRootObject(); ModCompatibility.Init(); ((IManager)SynchronizationManager.Instance).Init(); Runtime.MakeAllAssetsLoadable(); Game.isModded = true; } private void Start() { PatchInit.InitializePatches(); AutomaticLocalizationsLoading.Init(); } private void OnApplicationQuit() { AssetBundle.UnloadAllAssetBundles(false); } private static GameObject GetRootObject() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)rootObject)) { return rootObject; } rootObject = new GameObject("_JotunnRoot"); Object.DontDestroyOnLoad((Object)(object)rootObject); return rootObject; } internal static void LogInit(string module) { Logger.LogInfo("Initializing " + module); if (!Object.op_Implicit((Object)(object)Instance)) { string data = module + " was accessed before Jotunn Awake, this can cause unexpected behaviour. Please make sure to add `[BepInDependency(Jotunn.Main.ModGuid)]` next to your BaseUnityPlugin"; Logger.LogWarning(BepInExUtils.GetSourceModMetadata(), data); } } } internal class ClassMember { private static readonly Dictionary<Type, ClassMember> CachedClassMembers = new Dictionary<Type, ClassMember>(); public List<MemberBase> Members { get; private set; } = new List<MemberBase>(); public Type Type { get; private set; } private ClassMember(Type type, IEnumerable<FieldInfo> fieldInfos, IEnumerable<PropertyInfo> propertyInfos) { Type = type; foreach (FieldInfo fieldInfo in fieldInfos) { AddMember(new FieldMember(fieldInfo)); } foreach (PropertyInfo propertyInfo in propertyInfos) { AddMember(new PropertyMember(propertyInfo)); } } private void AddMember(MemberBase member) { if (member.IsClass && !(member.MemberType == typeof(string)) && (!(member.EnumeratedType != null) || (member.IsEnumeratedClass && !(member.EnumeratedType == typeof(string)))) && !member.HasCustomAttribute<NonSerializedAttribute>()) { Members.Add(member); } } private static T[] GetMembersFromType<T>(Type type, Func<Type, T[]> getMembers) { T[] array = getMembers(type); Type baseType = type.BaseType; while (baseType != null) { T[] second = getMembers(baseType); array = array.Union(second).ToArray(); baseType = baseType.BaseType; } return array; } public static ClassMember GetClassMember(Type type) { if (CachedClassMembers.TryGetValue(type, out var value)) { return value; } FieldInfo[] membersFromType = GetMembersFromType(type, (Type t) => t.GetFields(~BindingFlags.Static)); PropertyInfo[] membersFromType2 = GetMembersFromType(type, (Type t) => t.GetProperties(~BindingFlags.Static)); value = new ClassMember(type, membersFromType, membersFromType2); CachedClassMembers[type] = value; return value; } } internal class FieldMember : MemberBase { private readonly FieldInfo fieldInfo; public FieldMember(FieldInfo fieldInfo) { this.fieldInfo = fieldInfo; base.MemberType = fieldInfo.FieldType; base.IsUnityObject = base.MemberType.IsSameOrSubclass(typeof(Object)); base.IsClass = base.MemberType.IsClass; base.HasGetMethod = true; base.EnumeratedType = base.MemberType.GetEnumeratedType(); base.IsEnumerableOfUnityObjects = base.EnumeratedType?.IsSameOrSubclass(typeof(Object)) ?? false; base.IsEnumeratedClass = base.EnumeratedType?.IsClass ?? false; } public override object GetValue(object obj) { try { return fieldInfo.GetValue(obj); } catch { return null; } } public override void SetValue(object obj, object value) { fieldInfo.SetValue(obj, value); } public override bool HasCustomAttribute<T>() { return fieldInfo.GetCustomAttribute<T>() != null; } } internal abstract class MemberBase { public bool HasGetMethod { get; protected set; } public Type MemberType { get; protected set; } public Type EnumeratedType { get; protected set; } public bool IsUnityObject { get; protected set; } public bool IsClass { get; protected set; } public bool IsEnumerableOfUnityObjects { get; protected set; } public bool IsEnumeratedClass { get; protected set; } public abstract object GetValue(object obj); public abstract void SetValue(object obj, object value); public abstract bool HasCustomAttribute<T>() where T : Attribute; } internal class PropertyMember : MemberBase { private readonly PropertyInfo propertyInfo; public PropertyMember(PropertyInfo propertyInfo) { this.propertyInfo = propertyInfo; base.MemberType = propertyInfo.PropertyType; base.IsUnityObject = base.MemberType.IsSameOrSubclass(typeof(Object)); base.IsClass = base.MemberType.IsClass; base.HasGetMethod = propertyInfo.GetIndexParameters().Length == 0 && propertyInfo.GetMethod != null; base.EnumeratedType = base.MemberType.GetEnumeratedType(); base.IsEnumerableOfUnityObjects = base.EnumeratedType?.IsSameOrSubclass(typeof(Object)) ?? false; base.IsEnumeratedClass = base.EnumeratedType?.IsClass ?? false; } public override object GetValue(object obj) { try { return propertyInfo.GetValue(obj); } catch { return null; } } public override void SetValue(object obj, object value) { propertyInfo.SetValue(obj, value); } public override bool HasCustomAttribute<T>() { return propertyInfo.GetCustomAttribute<T>() != null; } } } namespace Jotunn.Utils { public static class AssetUtils { public const char AssetBundlePathSeparator = '$'; public static Texture2D LoadTexture(string texturePath, bool relativePath = true) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown string text = texturePath; if (relativePath) { text = Path.Combine(Paths.PluginPath, texturePath); } if (!File.Exists(text)) { return null; } if (!text.EndsWith(".png") && !text.EndsWith(".jpg")) { throw new Exception("LoadTexture can only load png or jpg textures"); } byte[] array = File.ReadAllBytes(text); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); return val; } public static Sprite LoadSpriteFromFile(string spritePath) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return LoadSpriteFromFile(spritePath, Vector2.zero); } public static Sprite LoadSpriteFromFile(string spritePath, Vector2 pivot) { //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) Texture2D val = LoadTexture(spritePath); if ((Object)(object)val != (Object)null) { return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), pivot); } return null; } public static Mesh LoadMesh(string meshPath) { string text = Path.Combine(Paths.PluginPath, meshPath); if (!File.Exists(text)) { return null; } return ObjImporter.ImportFile(text); } public static AssetBundle LoadAssetBundle(string bundlePath) { string text = Path.Combine(Paths.PluginPath, bundlePath); if (!File.Exists(text)) { return null; } return AssetBundle.LoadFromFile(text); } public static AssetBundle LoadAssetBundleFromResources(string bundleName, Assembly resourceAssembly) { if (resourceAssembly == null) { throw new ArgumentNullException("Parameter resourceAssembly can not be null."); } string text = null; try { text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(bundleName)); } catch (Exception) { } if (text == null) { Logger.LogError("AssetBundle " + bundleName + " not found in assembly manifest"); return null; } using Stream stream = resourceAssembly.GetManifestResourceStream(text); return AssetBundle.LoadFromStream(stream); } public static AssetBundle LoadAssetBundleFromResources(string bundleName) { return LoadAssetBundleFromResources(bundleName, ReflectionHelper.GetCallingAssembly()); } public static string LoadTextFromResources(string fileName, Assembly resourceAssembly) { if (resourceAssembly == null) { throw new ArgumentNullException("Parameter resourceAssembly can not be null."); } string text = null; try { text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(fileName)); } catch (Exception) { } if (text == null) { Logger.LogError("File " + fileName + " not found in assembly manifest"); return null; } using Stream stream = resourceAssembly.GetManifestResourceStream(text); using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } public static string LoadTextFromResources(string fileName) { return LoadTextFromResources(fileName, ReflectionHelper.GetCallingAssembly()); } public static string LoadText(string path) { string text = Path.Combine(Paths.PluginPath, path); if (!File.Exists(text)) { Logger.LogError("Error, failed to load contents from non-existant path: $" + text); return null; } return File.ReadAllText(text); } public static Sprite LoadSprite(string assetPath) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) string text = Path.Combine(Paths.PluginPath, assetPath); if (!File.Exists(text)) { return null; } if (text.Contains('$'.ToString())) { string[] array = text.Split(new char[1] { '$' }); string text2 = array[0]; string text3 = array[1]; AssetBundle val = AssetBundle.LoadFromFile(text2); Sprite result = val.LoadAsset<Sprite>(text3); val.Unload(false); return result; } Texture2D val2 = LoadTexture(text, relativePath: false); if (!Object.op_Implicit((Object)(object)val2)) { return null; } return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), Vector2.zero); } internal static bool TryLoadPrefab(BepInPlugin sourceMod, AssetBundle assetBundle, string assetName, out GameObject prefab) { try { prefab = assetBundle.LoadAsset<GameObject>(assetName); } catch (Exception arg) { prefab = null; Logger.LogError(sourceMod, $"Failed to load prefab '{assetName}' from AssetBundle {assetBundle}:\n{arg}"); return false; } if (!Object.op_Implicit((Object)(object
Plugins/MagicPlugin.dll
Decompiled 2 years 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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using AzuExtendedPlayerInventory; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using ItemManager; using JetBrains.Annotations; using Jewelcrafting; using LocalizationManager; using MagicPlugin.Functions; using MagicPlugin.JCAdditions; using MagicPlugin.SE; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyFileVersion("1.9.7")] [assembly: Guid("0119FA22-B3BE-4E92-B9A3-3B9637D974C5")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("blacks7ar")] [assembly: AssemblyProduct("MagicPlugin")] [assembly: AssemblyDescription("https://valheim.thunderstore.io/package/blacks7ar/MagicPlugin/")] [assembly: AssemblyTitle("MagicPlugin")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyConfiguration("")] [assembly: CompilationRelaxations(8)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.9.7.0")] [module: UnverifiableCode] [module: <478eb20d-f964-497a-a007-52aaa3ed1860>RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [<78d51af7-f084-4c61-9150-d7e7a1ea4cda>Embedded] [CompilerGenerated] internal sealed class <78d51af7-f084-4c61-9150-d7e7a1ea4cda>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [<78d51af7-f084-4c61-9150-d7e7a1ea4cda>Embedded] [CompilerGenerated] internal sealed class <28b12b44-6375-4e11-9e02-6a4dbe9ebb91>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <28b12b44-6375-4e11-9e02-6a4dbe9ebb91>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <28b12b44-6375-4e11-9e02-6a4dbe9ebb91>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [<78d51af7-f084-4c61-9150-d7e7a1ea4cda>Embedded] [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class <4d1f27f8-1bec-4783-8c94-e9b33a4c026d>NullableContextAttribute : Attribute { public readonly byte Flag; public <4d1f27f8-1bec-4783-8c94-e9b33a4c026d>NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [<78d51af7-f084-4c61-9150-d7e7a1ea4cda>Embedded] internal sealed class <478eb20d-f964-497a-a007-52aaa3ed1860>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <478eb20d-f964-497a-a007-52aaa3ed1860>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MagicPlugin { [BepInPlugin("blacks7ar.MagicPlugin", "MagicPlugin", "1.9.7")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private const string modGUID = "blacks7ar.MagicPlugin"; public const string modName = "MagicPlugin"; public const string modAuthor = "blacks7ar"; public const string modVersion = "1.9.7"; public const string modLink = "https://valheim.thunderstore.io/package/blacks7ar/MagicPlugin/"; private static string configFileName = "blacks7ar.MagicPlugin.cfg"; private static string configFileFullPath; public static readonly ManualLogSource MPLogger; private static readonly Harmony _harmony; private static readonly ConfigSync _configSync; private static ConfigEntry<MagicPlugin.Functions.Toggle> _serverConfigLocked; public static ConfigEntry<float> _magicVelocity; public static ConfigEntry<float> _magciAccuracy; public static ConfigEntry<MagicPlugin.Functions.Toggle> _enableExpMultiplier; public static ConfigEntry<MagicPlugin.Functions.Toggle> _displayExpGained; public static ConfigEntry<float> _bmExpMultiplier; public static ConfigEntry<float> _emExpMultiplier; public static ConfigEntry<MagicPlugin.Functions.Toggle> _enableTomeSlot; public static ConfigEntry<MagicPlugin.Functions.Toggle> _enableEarringSlot; public static GameObject _PrefabContainer; public static Sprite _skullTotemIcon; public static Sprite _neckTotemIcon; public static Sprite _wolfTotemIcon; public static Sprite _crystalTotemIcon; public static Sprite _modersIcon; public static Sprite _yagluthsIcon; public static GameObject _skullTotemProjectile; public static GameObject _armoredSkellies; public static Plugin _Instance; public ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool _synchronizedConfig = true) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (_synchronizedConfig ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); _configSync.AddConfigEntry<T>(val2).SynchronizedConfig = _synchronizedConfig; return val2; } private void ConfigWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, configFileName); fileSystemWatcher.Changed += OnConfigChanged; fileSystemWatcher.Created += OnConfigChanged; fileSystemWatcher.Renamed += OnConfigChanged; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void OnConfigChanged(object sender, FileSystemEventArgs e) { if (!File.Exists(configFileFullPath)) { return; } try { Logging.LogDebug("OnConfigChanged called.."); ((BaseUnityPlugin)this).Config.Reload(); } catch { Logging.LogError("There was an issue loading your " + configFileName); Logging.LogError("Please check you config entries for spelling and format!"); } } public void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Expected O, but got Unknown //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Expected O, but got Unknown //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Expected O, but got Unknown _Instance = this; Localizer.Load(); _serverConfigLocked = config("1- ServerSync", "Lock Configuration", MagicPlugin.Functions.Toggle.On, new ConfigDescription("If On, the configuration is locked and can be changed by server admins only.", (AcceptableValueBase)null, Array.Empty<object>())); _configSync.AddLockingConfigEntry<MagicPlugin.Functions.Toggle>(_serverConfigLocked); _magicVelocity = config("2- General", "Velocity Multiplier", 2f, new ConfigDescription("Magic projectiles velocity multiplier.\nRecommended: 2", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>())); _magciAccuracy = config("2- General", "Accuracy Multiplier", 0f, new ConfigDescription("Magic projectiles accuracy multiplier.\nRecommended: 0", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { new MagicPlugin.Functions.ConfigurationManagerAttributes { ShowRangeAsPercent = false } })); _enableTomeSlot = config("2- General", "Enable Tome Slot", MagicPlugin.Functions.Toggle.On, new ConfigDescription("If On, tomes or books has a dedicated slot when using Azu ExtendPlayerInventory mod.", (AcceptableValueBase)null, Array.Empty<object>())); _enableTomeSlot.SettingChanged += delegate { MagicSlot.AddCustomSlot(_enableTomeSlot); }; MagicSlot.AddCustomSlot(_enableTomeSlot); _enableEarringSlot = config("2- General", "Enable Earring Slot", MagicPlugin.Functions.Toggle.On, new ConfigDescription("If On, earrings has a dedicated slot when using Azu ExtendedPlayerInventory mod.", (AcceptableValueBase)null, Array.Empty<object>())); _enableEarringSlot.SettingChanged += delegate { MagicSlot.AddCustomSlot(_enableEarringSlot); }; MagicSlot.AddCustomSlot(_enableEarringSlot); _enableExpMultiplier = config("4- Skill Exp", "Enable Exp Multiplier", MagicPlugin.Functions.Toggle.On, new ConfigDescription("Enable/Disables exp multiplier.", (AcceptableValueBase)null, Array.Empty<object>())); _displayExpGained = config("4- Skill Exp", "Display Exp Gained", MagicPlugin.Functions.Toggle.On, new ConfigDescription("Enable/Disables exp gain notifications", (AcceptableValueBase)null, Array.Empty<object>())); _bmExpMultiplier = config("4- Skill Exp", "BloodMagic Exp Multiplier", 1f, new ConfigDescription("Exp multiplier for BloodMagic skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>())); _emExpMultiplier = config("4- Skill Exp", "ElementalMagic Exp Multiplier", 1f, new ConfigDescription("Exp multiplier for ElementalMagic skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>())); PrefabContainer(); ConfigSetup.Init(); PrefabsSetup.Init(); RingsAndNecklaces.Init(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); ConfigWatcher(); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } public static void PrefabContainer() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown _PrefabContainer = new GameObject("BMP_ClonedPrefabs"); _PrefabContainer.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_PrefabContainer); } static Plugin() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; configFileFullPath = configPath + directorySeparatorChar + configFileName; MPLogger = Logger.CreateLogSource("MagicPlugin"); _harmony = new Harmony("blacks7ar.MagicPlugin"); _configSync = new ConfigSync("blacks7ar.MagicPlugin") { DisplayName = "MagicPlugin", CurrentVersion = "1.9.7", MinimumRequiredVersion = "1.9.7", ModRequired = true }; } } } namespace MagicPlugin.SE { public class ArcticBuff : StatusEffect { private float m_eitrRegen; public void Awake() { base.m_name = "Arctic Buff"; ((Object)this).name = base.m_name; base.m_tooltip = $"The Polarwolf armor set gives enough protection against cold and freezing. It is imbued with magic so its wearer will replenish eitr faster.\n\nEitr regen increased by <color=orange>+{Mathf.FloorToInt(m_eitrRegen)}%\nResistant</color> VS <color=orange>Cold</color> and <color=orange>Freezing</color>"; } public void SetEitrRegen(float bonus) { m_eitrRegen = bonus; base.m_tooltip = $"The Polarwolf armor set gives enough protection against cold and freezing. It is imbued with magic so its wearer will replenish eitr faster.\n\nEitr regen increased by <color=orange>+{Mathf.FloorToInt(m_eitrRegen)}%\nResistant</color> VS <color=orange>Cold</color> and <color=orange>Freezing</color>"; } public override void ModifyEitrRegen(ref float eitrRegen) { eitrRegen += m_eitrRegen / 100f; } } public class AddEitr : StatusEffect { public float m_eitr; public void Awake() { base.m_tooltip = $"Boost wearer's <color=orange>Eitr</color> by <color=orange>+{m_eitr}</color>."; } public void SetEitr(float eitr) { m_eitr = eitr; base.m_tooltip = $"Boost wearer's <color=orange>Eitr</color> by <color=orange>+{m_eitr}</color>."; } } public class Elementalist : StatusEffect { public float m_elementalMagic; public void Awake() { ((Object)this).name = "bmp_elementalist"; base.m_name = "Elementalist Belt"; base.m_tooltip = "Boost Elemental Magics skill level." + $"\n<color=orange>ElementalMagic: +{m_elementalMagic}</color>"; } public void SetElementalMagic(float value) { m_elementalMagic = value; base.m_tooltip = "Boost Elemental Magics skill level." + $"\n<color=orange>ElementalMagic: +{m_elementalMagic}</color>"; } } public class ForestMagic : StatusEffect { private float m_eitrRegen; public void Awake() { base.m_name = "Forest Magic"; ((Object)this).name = base.m_name; base.m_tooltip = $"This pair of armor doesn't give enough armor defense to its wearer but will be beneficial to a newborn Mage.\n\nEitr regen increased by <color=orange>+{Mathf.FloorToInt(m_eitrRegen)}%</color>"; } public void SetEitrRegen(float bonus) { m_eitrRegen = bonus; base.m_tooltip = $"This pair of armor doesn't give enough armor defense to its wearer but will be beneficial to a newborn Mage.\n\nEitr regen increased by <color=orange>+{Mathf.FloorToInt(m_eitrRegen)}%</color>"; } public override void ModifyEitrRegen(ref float eitrRegen) { eitrRegen += m_eitrRegen / 100f; } } public class HealGroup : StatusEffect { public float m_healthOverTime; public float m_healthOverTimeInterval; public float m_healthOverTimeDuration; public float m_healthOverTimeTimer; public float m_healthOverTimeTicks; public float m_healthOverTimeTickHP; public SkillType m_levelUpSkill; public float m_levelUpSkillFactor = 0.2f; public void Awake() { base.m_name = "Staff Of Healing"; ((Object)this).name = "healstaff_cooldown"; base.m_tooltip = "Heals everyone over time." + $"\n<color=orange>HealOverTime: {Mathf.FloorToInt(m_healthOverTime / (m_healthOverTimeDuration / m_healthOverTimeInterval))}</color>" + $"\n<color=orange>Duration: {m_healthOverTimeDuration}secs</color>"; base.m_icon = PrefabsSetup._magicBundle.LoadAsset<Sprite>("bmr_heart_icon"); } public void SetHealthOverTimeInterval(float value) { m_healthOverTimeInterval = value; base.m_tooltip = "Heals everyone over time." + $"\n<color=orange>HealOverTime: {Mathf.FloorToInt(m_healthOverTime / (m_healthOverTimeDuration / m_healthOverTimeInterval))}</color>" + $"\n<color=orange>Duration: {m_healthOverTimeDuration}secs</color>"; } public void SetHealthOverTime(float value) { m_healthOverTime = value; base.m_tooltip = "Heals everyone over time." + $"\n<color=orange>HealOverTime: {Mathf.FloorToInt(m_healthOverTime / (m_healthOverTimeDuration / m_healthOverTimeInterval))}</color>" + $"\n<color=orange>Duration: {m_healthOverTimeDuration}secs</color>"; } public void SetHealthOverTimeDuration(float value) { m_healthOverTimeDuration = value; base.m_tooltip = "Heals everyone over time." + $"\n<color=orange>HealOverTime: {Mathf.FloorToInt(m_healthOverTime / (m_healthOverTimeDuration / m_healthOverTimeInterval))}</color>" + $"\n<color=orange>Duration: {m_healthOverTimeDuration}secs</color>"; } public override void Setup(Character character) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) ((StatusEffect)this).Setup(character); if (m_healthOverTime > 0f && m_healthOverTimeInterval > 0f) { if (m_healthOverTimeDuration <= 0f) { m_healthOverTimeDuration = base.m_ttl; } m_healthOverTimeTicks = m_healthOverTimeDuration / m_healthOverTimeInterval; m_healthOverTimeTickHP = m_healthOverTime / m_healthOverTimeTicks; m_levelUpSkill = (SkillType)10; } } public override void UpdateStatusEffect(float dt) { ((StatusEffect)this).UpdateStatusEffect(dt); if (m_healthOverTimeTicks > 0f) { m_healthOverTimeTimer += dt; if (m_healthOverTimeTimer > m_healthOverTimeInterval) { m_healthOverTimeTimer = 0f; m_healthOverTimeTicks -= 1f; base.m_character.Heal(m_healthOverTimeTickHP, true); } } } } public class Hogwarts : StatusEffect { public float m_damageMultiplier; public void Awake() { ((Object)this).name = "bmp_hogwarts"; base.m_name = "Hogwarts Belt"; base.m_tooltip = "Boost wearer's elemental damages." + $"\n<color=orange>Damage Multiplier: {m_damageMultiplier}x</color>"; } public void SetDamageMultiplier(float value) { m_damageMultiplier = value; base.m_tooltip = "Boost wearer's elemental damages." + $"\n<color=orange>Damage Multiplier: {m_damageMultiplier}x</color>"; } } public class Necromancer : StatusEffect { public float m_bloodMagic; public void Awake() { ((Object)this).name = "bmp_necromancer"; base.m_name = "Necromancers Belt"; base.m_tooltip = "Boost Blood Magics skill level." + $"\n<color=orange>BloodMagic: +{m_bloodMagic}</color>"; } public void SetBloodMagic(float value) { m_bloodMagic = value; base.m_tooltip = "Boost Blood Magics skill level." + $"\n<color=orange>BloodMagic: +{m_bloodMagic}</color>"; } } public class SlowFallAndEitr : StatusEffect { public float m_eitr; public float m_maxFallSpeed = 5f; public float m_fallDamageModifier = -1f; public void Awake() { base.m_name = "Slow Fall"; base.m_tooltip = "$bmr_featherfall_tooltip" + $"\nLimit fall speed: <color=orange>{m_maxFallSpeed}m/s</color>" + $"\nFall damage: <color=orange>{m_fallDamageModifier}%</color>" + $"\nEitr: <color=orange>+{m_eitr}</color>"; base.m_icon = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite x) => ((Object)x).name == "SlowFall")); } public void SetEitr(float eitr) { m_eitr = eitr; base.m_tooltip = "$bmr_featherfall_tooltip" + $"\nLimit fall speed: <color=orange>{m_maxFallSpeed}m/s</color>" + $"\nFall damage: <color=orange>{m_fallDamageModifier}%</color>" + $"\nEitr: <color=orange>+{m_eitr}</color>"; } public override void ModifyWalkVelocity(ref Vector3 vel) { if (m_maxFallSpeed > 0f && vel.y < 0f - m_maxFallSpeed) { vel.y = 0f - m_maxFallSpeed; } } public override void ModifyFallDamage(float baseDamage, ref float damage) { damage += baseDamage * m_fallDamageModifier; if (damage < 0f) { damage = 0f; } } } } namespace MagicPlugin.Patches { [HarmonyPatch] public class AttackPatch { [HarmonyPatch(typeof(Attack), "Start")] [HarmonyPostfix] public static void AttackStart_Postfix(Attack __instance) { if (__instance == null) { return; } Humanoid character = __instance.m_character; Player val = (Player)(object)((character is Player) ? character : null); if (val == null) { return; } string name = __instance.m_weapon.m_shared.m_name; if (name == null) { return; } switch (name.Length) { case 18: switch (name[5]) { case 's': if (name == "$bmp_surtlingstaff") { float damageMultiplier9 = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier9; } break; case 'e': if (name == "$bmp_eikthyrsstaff") { float damageMultiplier10 = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier10; } break; case 'l': if (name == "$bmp_lightningwand") { float damageMultiplier8 = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier8; } break; } break; case 16: switch (name[5]) { case 'a': if (name == "$bmp_arcticstaff") { float damageMultiplier6 = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier6; } break; case 'p': if (name == "$bmp_poisonstaff") { float damageMultiplier5 = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier5; } break; } break; case 15: switch (name[5]) { case 'f': if (name == "$bmp_flamestaff") { float damageMultiplier3 = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier3; } break; case 'p': if (name == "$bmp_poisonwand") { float damageMultiplier2 = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier2; } break; } break; case 14: switch (name[5]) { case 's': if (name == "$bmp_staffheal" && ((Character)val).GetHealth() < ((Character)val).GetMaxHealth()) { ((Character)val).RaiseSkill((SkillType)10, 0.2f); } break; case 'f': if (name == "$bmp_flamewand") { float damageMultiplier11 = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier11; } break; } break; case 19: if (name == "$bmp_lightningstaff") { float damageMultiplier7 = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier7; } break; case 17: if (name == "$bmp_thunderstaff") { float damageMultiplier4 = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier4; } break; case 12: if (name == "$bmp_icewand") { float damageMultiplier = 1f + 2f * ((Character)val).GetSkillFactor((SkillType)9); __instance.m_weapon.m_shared.m_attack.m_damageMultiplier = damageMultiplier; } break; case 13: break; } } [HarmonyPrefix] [HarmonyPatch(typeof(Attack), "FireProjectileBurst")] public static bool FireProjectileBurst_Prefix(Attack __instance) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 if (__instance != null) { Humanoid character = __instance.m_character; Player player = (Player)(object)((character is Player) ? character : null); if (player != null) { SkillType skillType = __instance.m_weapon.m_shared.m_skillType; if (__instance.m_weapon == null || (int)skillType != 9) { return true; } string name = __instance.m_weapon.m_shared.m_name; if (__instance.m_weapon.m_shared.m_name.EndsWith("scepter") || __instance.m_weapon.m_shared.m_name.Contains("flamestaff") || __instance.m_weapon.m_shared.m_name.Contains("thunderstaff") || __instance.m_weapon.m_shared.m_ammoType.Contains("ammo_spells")) { return true; } if ((Object)(object)__instance.m_weapon.m_shared.m_secondaryAttack.m_attackProjectile != (Object)null && ((Object)__instance.m_weapon.m_shared.m_secondaryAttack.m_attackProjectile).name == "BDS_DvergerStaffFire_clusterbomb_projectile") { return true; } if ((name == "$bmp_arcticstaff" || name == "$item_stafficeshards") ? true : false) { Attack obj = __instance; obj.m_projectileVel *= 1.2f; Attack obj2 = __instance; obj2.m_projectileVelMin *= 1.2f; Attack obj3 = __instance; obj3.m_projectileAccuracy *= 0f; Attack obj4 = __instance; obj4.m_projectileAccuracyMin *= 0f; } else { Plugin._magicVelocity.SettingChanged += delegate { Attack obj11 = __instance; obj11.m_projectileVel *= Plugin._magicVelocity.Value; Attack obj12 = __instance; obj12.m_projectileVelMin *= Plugin._magicVelocity.Value; }; Attack obj5 = __instance; obj5.m_projectileVel *= Plugin._magicVelocity.Value; Attack obj6 = __instance; obj6.m_projectileVelMin *= Plugin._magicVelocity.Value; Plugin._magciAccuracy.SettingChanged += delegate { Attack obj9 = __instance; obj9.m_projectileAccuracy *= Plugin._magciAccuracy.Value; Attack obj10 = __instance; obj10.m_projectileAccuracyMin *= Plugin._magciAccuracy.Value; }; Attack obj7 = __instance; obj7.m_projectileAccuracy *= Plugin._magciAccuracy.Value; Attack obj8 = __instance; obj8.m_projectileAccuracyMin *= Plugin._magciAccuracy.Value; } if (((Object)__instance.m_attackProjectile).name.ToLower().Contains("surtlingstaff")) { ConfigSetup._surtlingStaffAOE.SettingChanged += delegate { __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_aoe = ConfigSetup._surtlingStaffAOE.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); }; __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_aoe = ConfigSetup._surtlingStaffAOE.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); } if (((Object)__instance.m_attackProjectile).name.ToLower().Contains("eikthyrsstaff")) { ConfigSetup._eikthyrStaffAOE.SettingChanged += delegate { __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_aoe = ConfigSetup._eikthyrStaffAOE.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); }; __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_aoe = ConfigSetup._eikthyrStaffAOE.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); } if (((Object)__instance.m_attackProjectile).name.ToLower().Contains("lightningstaff")) { ConfigSetup._lightningStaffAOE.SettingChanged += delegate { __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_aoe = ConfigSetup._lightningStaffAOE.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); }; __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_aoe = ConfigSetup._lightningStaffAOE.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); } if (((Object)__instance.m_attackProjectile).name.ToLower().Contains("poisonstaff")) { ConfigSetup._poisonStaffAOE.SettingChanged += delegate { __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_aoe = ConfigSetup._poisonStaffAOE.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); }; __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_aoe = ConfigSetup._poisonStaffAOE.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); } if (((Object)__instance.m_attackProjectile).name.ToLower().Contains("arcticstaff")) { ConfigSetup._arcticStaffAOE.SettingChanged += delegate { __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_aoe = ConfigSetup._arcticStaffAOE.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); }; __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_aoe = ConfigSetup._arcticStaffAOE.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); } if (((Object)__instance.m_attackProjectile).name == "bmp_modersheritage_projectile") { SpawnAbility component = __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_spawnOnHit.gameObject.GetComponent<SpawnAbility>(); Projectile iceblast = component.m_spawnPrefab[0].gameObject.GetComponent<Projectile>(); ConfigSetup._modersAoeRange.SettingChanged += delegate { iceblast.m_aoe = ConfigSetup._modersAoeRange.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); }; iceblast.m_aoe = ConfigSetup._modersAoeRange.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); ConfigSetup._modersChopDamage.SettingChanged += delegate { iceblast.m_damage.m_chop = ConfigSetup._modersChopDamage.Value; }; iceblast.m_damage.m_chop = ConfigSetup._modersChopDamage.Value; ConfigSetup._modersFrostDamage.SettingChanged += delegate { iceblast.m_damage.m_frost = ConfigSetup._modersFrostDamage.Value + ConfigSetup._modersFrostDamage.Value * ((Character)player).GetSkillFactor((SkillType)9); }; iceblast.m_damage.m_frost = ConfigSetup._modersFrostDamage.Value + ConfigSetup._modersFrostDamage.Value * ((Character)player).GetSkillFactor((SkillType)9); ConfigSetup._modersPickaxeDamage.SettingChanged += delegate { iceblast.m_damage.m_pickaxe = ConfigSetup._modersPickaxeDamage.Value; }; iceblast.m_damage.m_pickaxe = ConfigSetup._modersPickaxeDamage.Value; ConfigSetup._modersPierceDamage.SettingChanged += delegate { iceblast.m_damage.m_pierce = ConfigSetup._modersPierceDamage.Value; }; iceblast.m_damage.m_pierce = ConfigSetup._modersPierceDamage.Value; } if (((Object)__instance.m_attackProjectile).name == "bmp_yagluthsheritage_projectile") { SpawnAbility component2 = __instance.m_attackProjectile.gameObject.GetComponent<Projectile>().m_spawnOnHit.gameObject.GetComponent<SpawnAbility>(); Projectile meteors = component2.m_spawnPrefab[0].gameObject.GetComponent<Projectile>(); ConfigSetup._yagluthAoeRange.SettingChanged += delegate { meteors.m_aoe = ConfigSetup._yagluthAoeRange.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); }; meteors.m_aoe = ConfigSetup._yagluthAoeRange.Value + 2f * ((Character)player).GetSkillFactor((SkillType)9); ConfigSetup._yagluthBluntDamage.SettingChanged += delegate { meteors.m_damage.m_blunt = ConfigSetup._yagluthBluntDamage.Value; }; meteors.m_damage.m_blunt = ConfigSetup._yagluthBluntDamage.Value; ConfigSetup._yagluthChopDamage.SettingChanged += delegate { meteors.m_damage.m_chop = ConfigSetup._yagluthChopDamage.Value; }; meteors.m_damage.m_chop = ConfigSetup._yagluthChopDamage.Value; ConfigSetup._yagluthFireDamage.SettingChanged += delegate { meteors.m_damage.m_fire = ConfigSetup._yagluthFireDamage.Value + ConfigSetup._yagluthFireDamage.Value * ((Character)player).GetSkillFactor((SkillType)9); }; meteors.m_damage.m_fire = ConfigSetup._yagluthFireDamage.Value + ConfigSetup._yagluthFireDamage.Value * ((Character)player).GetSkillFactor((SkillType)9); ConfigSetup._yagluthPickaxeDamage.SettingChanged += delegate { meteors.m_damage.m_pickaxe = ConfigSetup._yagluthPickaxeDamage.Value; }; meteors.m_damage.m_pickaxe = ConfigSetup._yagluthPickaxeDamage.Value; } return true; } } return true; } } [HarmonyPatch] public class DestructiblePatch { [HarmonyPatch(typeof(Destructible), "RPC_Damage")] public static class RpcDamagePatch { private static bool Prefix(Destructible __instance, HitData hit) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Invalid comparison between Unknown and I4 //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Invalid comparison between Unknown and I4 Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val == null || ((Humanoid)val).GetCurrentWeapon() == null || ((Humanoid)val).GetCurrentWeapon() == ((Humanoid)val).m_unarmedWeapon.m_itemData) { return true; } if (((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name == "BMP_SurtlingStaff" && (int)__instance.m_destructibleType == 2 && hit.m_damage.m_chop > 0f && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { hit.m_toolTier = (short)((Humanoid)val).GetCurrentWeapon().m_quality; ((Character)val).RaiseSkill((SkillType)13, 0.2f); } if ((((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name == "BMP_EikthyrsStaff" || ((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name == "BMP_LightningStaff") && (int)__instance.m_damages.m_pickaxe != 3 && (int)__instance.m_destructibleType != 2 && hit.m_damage.m_pickaxe > 0f && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { hit.m_toolTier = (short)((Humanoid)val).GetCurrentWeapon().m_quality; ((Character)val).RaiseSkill((SkillType)12, 0.2f); } return true; } } } [HarmonyPatch] public class HumanoidPatch { [HarmonyPostfix] [HarmonyPatch(typeof(Humanoid), "IsItemEquiped")] private static void IsItemEquipped_Postfix(Humanoid __instance, ItemData item, ref bool __result) { if (AzuExtendedPlayerInventory.API.IsLoaded()) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && MagicSlot._magicSlots.TryGetValue(((Humanoid)val).m_visEquipment, out var value) && (value._equippedTomeItem == item || value._equippedEarringItem == item)) { __result = true; } } } [HarmonyPatch(typeof(Humanoid), "SetupVisEquipment")] [HarmonyPrefix] private static void SetupVisEquipment_Prefix(Humanoid __instance) { if (AzuExtendedPlayerInventory.API.IsLoaded()) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && MagicSlot._magicSlots.TryGetValue(((Humanoid)val).m_visEquipment, out var value)) { value.SetTomeItem((value._equippedTomeItem == null) ? "" : ((Object)value._equippedTomeItem.m_dropPrefab).name); value.SetEarringItem((value._equippedEarringItem == null) ? "" : ((Object)value._equippedEarringItem.m_dropPrefab).name); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Humanoid), "UnequipAllItems")] private static void UnEquipAllItems_Prefix(Humanoid __instance) { if (AzuExtendedPlayerInventory.API.IsLoaded()) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { ((Humanoid)val).UnequipItem(MagicSlot._magicSlots[((Humanoid)val).m_visEquipment]._equippedTomeItem, false); ((Humanoid)val).UnequipItem(MagicSlot._magicSlots[((Humanoid)val).m_visEquipment]._equippedEarringItem, false); } } } [HarmonyPatch(typeof(Humanoid), "EquipItem")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> EquipItemTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); int num = list.FindLastIndex((CodeInstruction i) => CodeInstructionExtensions.LoadsConstant(i, (Enum)(object)(ItemType)18)); Label? label = default(Label?); do { num++; } while (!CodeInstructionExtensions.Branches(list[num], ref label)); list.InsertRange(num + 1, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[5] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Ldarg_2, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(HumanoidPatch), "EquipItem", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Brtrue, (object)label.Value) }); return list; } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> UnEquipItemTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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 MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Humanoid), "SetupEquipment", (Type[])null, (Type[])null); List<CodeInstruction> list = instructions.ToList(); int num = list.FindIndex((CodeInstruction i) => CodeInstructionExtensions.Calls(i, methodInfo)); list.InsertRange(num - 1, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(HumanoidPatch), "UnEquipItem", (Type[])null, (Type[])null)) }); return list; } [HarmonyPatch(typeof(Humanoid), "UpdateEquipmentStatusEffects")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StatusEffectsTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); list.InsertRange(2, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldloc_0, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(HumanoidPatch), "AddStatusEffects", (Type[])null, (Type[])null)) }); return list; } private static bool EquipItem(Humanoid humanoid, ItemData item, bool triggerEquipmentEffects) { if (!AzuExtendedPlayerInventory.API.IsLoaded()) { return false; } Player val = (Player)(object)((humanoid is Player) ? humanoid : null); if (val == null) { return false; } if (MagicSlot.IsTomeItem(item)) { ((Humanoid)val).UnequipItem(MagicSlot._magicSlots[((Humanoid)val).m_visEquipment]._equippedTomeItem, triggerEquipmentEffects); MagicSlot._magicSlots[((Humanoid)val).m_visEquipment]._equippedTomeItem = item; return true; } if (MagicSlot.IsEarringItem(item)) { ((Humanoid)val).UnequipItem(MagicSlot._magicSlots[((Humanoid)val).m_visEquipment]._equippedEarringItem, triggerEquipmentEffects); MagicSlot._magicSlots[((Humanoid)val).m_visEquipment]._equippedEarringItem = item; return true; } return false; } private static void UnEquipItem(Humanoid humanoid, ItemData item) { if (!AzuExtendedPlayerInventory.API.IsLoaded()) { return; } Player val = (Player)(object)((humanoid is Player) ? humanoid : null); if (val != null) { if (MagicSlot._magicSlots[((Humanoid)val).m_visEquipment]._equippedTomeItem == item) { MagicSlot._magicSlots[((Humanoid)val).m_visEquipment]._equippedTomeItem = null; } if (MagicSlot._magicSlots[((Humanoid)val).m_visEquipment]._equippedEarringItem == item) { MagicSlot._magicSlots[((Humanoid)val).m_visEquipment]._equippedEarringItem = null; } } } private static void AddStatusEffects(Humanoid humanoid, HashSet<StatusEffect> statusEffects) { if (!AzuExtendedPlayerInventory.API.IsLoaded()) { return; } Player val = (Player)(object)((humanoid is Player) ? humanoid : null); if (val != null && MagicSlot._magicSlots.TryGetValue(((Humanoid)val).m_visEquipment, out var value)) { StatusEffect val2 = value._equippedTomeItem?.m_shared.m_equipStatusEffect; if (val2 != null) { statusEffects.Add(val2); } StatusEffect val3 = value._equippedEarringItem?.m_shared.m_equipStatusEffect; if (val3 != null) { statusEffects.Add(val3); } } } } [HarmonyPatch] public class ItemDataPatch { [HarmonyPatch(typeof(ItemData), "GetDamage", new Type[] { typeof(int), typeof(float) })] [HarmonyPostfix] public static void GetDamage_Postfix(ItemData __instance, ref DamageTypes __result) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && ((Humanoid)localPlayer).m_inventory.m_inventory.Exists((ItemData x) => x == __instance)) { float skillFactor = ((Character)localPlayer).GetSkillFactor((SkillType)9); if (((Character)localPlayer).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("bmp_hogwarts"))) { float num = 1f + skillFactor * ConfigSetup._hogwartsBeltBonus.Value; __result.m_fire *= num; __result.m_frost *= num; __result.m_lightning *= num; __result.m_poison *= num; __result.m_spirit *= num; } } } } [HarmonyPatch] public class ItemDropPatch { [HarmonyPatch(typeof(ItemDrop), "Awake")] [HarmonyPostfix] public static void ItemDropAwake_Postfix(ItemDrop __instance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); if (!(((Scene)(ref activeScene)).name != "main") && !((Object)(object)__instance == (Object)null)) { switch (__instance.m_itemData.m_shared.m_name) { case "$bmp_modersinheritence": StatsSetup.ModersHeritage(__instance); break; case "$bmp_yagluthsinheritence": StatsSetup.YagluthsHeritage(__instance); break; case "$bmp_flamescepter": StatsSetup.FlameScepter(__instance); break; case "$bmp_icescepter": StatsSetup.IceScepter(__instance); break; case "$bmp_lightningscepter": StatsSetup.LightningScepter(__instance); break; case "$bmp_dvergrbelt": StatsSetup.DvergrBelt(__instance); break; } } } } [HarmonyPatch] public class MineRock5Patch { [HarmonyPatch(typeof(MineRock5), "RPC_Damage")] public static class RpcDamagePatch { private static void Prefix(MineRock5 __instance, HitData hit) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null && ((Humanoid)val).GetCurrentWeapon() != null && ((Humanoid)val).GetCurrentWeapon() != ((Humanoid)val).m_unarmedWeapon.m_itemData) { int quality = ((Humanoid)val).GetCurrentWeapon().m_quality; if ((!(((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name != "BMP_EikthyrsStaff") || !(((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name != "BMP_LightningStaff")) && quality >= __instance.m_minToolTier && hit.m_damage.m_pickaxe > 0f && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { hit.m_toolTier = (short)quality; ((Character)val).RaiseSkill((SkillType)12, 0.2f); } } } } [HarmonyPatch(typeof(MineRock5), "DamageArea")] public static class DamageAreaPatch { private static void Prefix(MineRock5 __instance, HitData hit) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null && ((Humanoid)val).GetCurrentWeapon() != null && ((Humanoid)val).GetCurrentWeapon() != ((Humanoid)val).m_unarmedWeapon.m_itemData) { int quality = ((Humanoid)val).GetCurrentWeapon().m_quality; if ((!(((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name != "BMP_EikthyrsStaff") || !(((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name != "BMP_LightningStaff")) && quality >= __instance.m_minToolTier && hit.m_damage.m_pickaxe > 0f && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { hit.m_toolTier = (short)quality; ((Character)val).RaiseSkill((SkillType)12, 0.2f); } } } } } [HarmonyPatch] public class MineRockPatch { [HarmonyPatch(typeof(MineRock), "RPC_Hit")] public static class RpcHitPatch { private static void Prefix(MineRock __instance, HitData hit) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null && ((Humanoid)val).GetCurrentWeapon() != null && ((Humanoid)val).GetCurrentWeapon() != ((Humanoid)val).m_unarmedWeapon.m_itemData) { int? num = ((Humanoid)val).GetCurrentWeapon()?.m_quality; if ((!(((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name != "BMP_EikthyrsStaff") || !(((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name != "BMP_LightningStaff")) && !(num < __instance.m_minToolTier) && hit.m_damage.m_pickaxe > 0f && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { hit.m_toolTier = (short)num.Value; ((Character)val).RaiseSkill((SkillType)12, 0.2f); } } } } } [HarmonyPatch] public class ObjectDBPatch { [HarmonyPostfix] [HarmonyPatch(typeof(ObjectDB), "Awake")] [HarmonyPriority(700)] private static void Awake_Postfix(ObjectDB __instance) { __instance.m_StatusEffects.Add((StatusEffect)(object)Helper.CreateCooldown("necktotem_cooldown", "NeckTotem", Plugin._neckTotemIcon)); __instance.m_StatusEffects.Add((StatusEffect)(object)Helper.CreateCooldown("wolftotem_cooldown", "WolfTotem", Plugin._wolfTotemIcon)); __instance.m_StatusEffects.Add((StatusEffect)(object)Helper.CreateCooldown("crystaltotem_cooldown", "CrystalTotem", Plugin._crystalTotemIcon)); __instance.m_StatusEffects.Add((StatusEffect)(object)Helper.CreateCooldown("skulltotem_cooldown", "SkullTotem", Plugin._skullTotemIcon)); __instance.m_StatusEffects.Add((StatusEffect)(object)Helper.CreateCooldown("modersheritage_cooldown", "ModersHeritage", Plugin._modersIcon)); __instance.m_StatusEffects.Add((StatusEffect)(object)Helper.CreateCooldown("yagluthsheritage_cooldown", "YagluthsHeritage", Plugin._yagluthsIcon)); } } [HarmonyPatch] public class PlayerPatch { [HarmonyPatch(typeof(Player), "UpdateEnvStatusEffects")] [HarmonyPrefix] private static bool UpdateEnvStatusEffect_Prefix(Player __instance) { if (!((Character)__instance).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("Arctic Buff"))) { return true; } if (EnvMan.IsCold()) { ((Character)__instance).GetSEMan().RemoveStatusEffect(StringExtensionMethods.GetStableHashCode("Cold"), false); } if (EnvMan.IsFreezing()) { ((Character)__instance).GetSEMan().RemoveStatusEffect(StringExtensionMethods.GetStableHashCode("Freezing"), false); } return true; } [HarmonyPatch(typeof(Player), "GetTotalFoodValue")] [HarmonyPostfix] public static void GetTotalFoodValue_Postfix(ref Player __instance, ref float eitr) { if (!((Object)(object)__instance == (Object)null)) { SetEitr(__instance, "bmr_tatteredcape", ConfigSetup._tatteredCapeEitr.Value, ref eitr); SetEitr(__instance, "bmr_tatteredchest", ConfigSetup._tatteredChestEitr.Value, ref eitr); SetEitr(__instance, "bmr_tatteredhelm", ConfigSetup._tatteredHelmEitr.Value, ref eitr); SetEitr(__instance, "bmr_tatteredlegs", ConfigSetup._tatteredLegsEitr.Value, ref eitr); SetEitr(__instance, "bmr_sorcererscape", ConfigSetup._sorcerersCapeEitr.Value, ref eitr); SetEitr(__instance, "bmr_sorcerershat", ConfigSetup._sorcerersHatEitr.Value, ref eitr); SetEitr(__instance, "bmr_sorcererstrousers", ConfigSetup._sorcerersTrousersEitr.Value, ref eitr); SetEitr(__instance, "bmr_sorcererstunic", ConfigSetup._sorcerersTunicEitr.Value, ref eitr); SetEitr(__instance, "bmr_warlockscape", ConfigSetup._warlocksCapeEitr.Value, ref eitr); SetEitr(__instance, "bmr_warlockshood", ConfigSetup._warlocksHoodEitr.Value, ref eitr); SetEitr(__instance, "bmr_warlockspants", ConfigSetup._warlocksPantsEitr.Value, ref eitr); SetEitr(__instance, "bmr_warlocksvest", ConfigSetup._warlocksVestEitr.Value, ref eitr); SetEitr(__instance, "bmr_polarwolfcape", ConfigSetup._polarWolfCapeEitr.Value, ref eitr); SetEitr(__instance, "bmr_polarwolfchest", ConfigSetup._polarWolfChestEitr.Value, ref eitr); SetEitr(__instance, "bmr_polarwolfhood", ConfigSetup._polarWolfHoodEitr.Value, ref eitr); SetEitr(__instance, "bmr_polarwolflegs", ConfigSetup._polarWolfLegEitr.Value, ref eitr); SetEitr(__instance, "bmr_seekercape", ConfigSetup._seekerCapeEitr.Value, ref eitr); SetEitr(__instance, "bmr_seekerchest", ConfigSetup._seekerChestEitr.Value, ref eitr); SetEitr(__instance, "bmr_seekerhat", ConfigSetup._seekerHatEitr.Value, ref eitr); SetEitr(__instance, "bmr_seekerlegs", ConfigSetup._seekerLegsEitr.Value, ref eitr); SetEitr(__instance, "bmr_crimsoncape", ConfigSetup._crimsonCapeEitr.Value, ref eitr); SetEitr(__instance, "bmr_crimsonchest", ConfigSetup._crimsonChestEitr.Value, ref eitr); SetEitr(__instance, "bmr_crimsonhood", ConfigSetup._crimsonHoodEitr.Value, ref eitr); SetEitr(__instance, "bmr_crimsonlegs", ConfigSetup._crimsonLegsEitr.Value, ref eitr); SetEitr(__instance, "bmp_eitrbelt", ConfigSetup._eitrBeltEitrBonus.Value, ref eitr); SetEitr(__instance, "bmp_eitr_earring", ConfigSetup._eitrEarringEitr.Value, ref eitr); SetEitr(__instance, "bmp_beginners_magicbook", ConfigSetup._beginnersBookEitr.Value, ref eitr); SetEitr(__instance, "bmp_advance_magicbook", ConfigSetup._advanceBookEitr.Value, ref eitr); SetEitr(__instance, "bmp_druidstome", ConfigSetup._druidsTomeEitr.Value, ref eitr); if (Jewelcrafting.API.IsLoaded()) { SetEitr(__instance, "bmp_eitr_ring", RingsAndNecklaces._eitrRingEitr.Value, ref eitr); SetEitr(__instance, "bmp_eitr_necklace", RingsAndNecklaces._eitrNecklaceEitr.Value, ref eitr); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })] public static void UpdateStats_Postfix(Player __instance) { if (!((Character)__instance).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("healstaff_cooldown"))) { return; } foreach (string item in new List<string> { "Frost", "Smoked", "Burning", "Poison", "Wet", "Tared", "Freezing", "Frost" }.Where((string se) => ((Character)__instance).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode(se)))) { ((Character)__instance).GetSEMan().RemoveStatusEffect(StringExtensionMethods.GetStableHashCode(item), false); } } [HarmonyPrefix] [HarmonyPriority(800)] [HarmonyPatch(typeof(Player), "Awake")] private static void Awake_Prefix(Player __instance) { if (Jewelcrafting.API.IsLoaded()) { MagicSlot._magicSlots.Add(((Component)__instance).GetComponent<VisEquipment>(), new MagicSlot(((Component)__instance).GetComponent<VisEquipment>())); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "GetEquipmentEitrRegenModifier")] public static void GetEquipmentEitrRegenModifier_Postfix(ref Player __instance, ref float __result) { __result += ((Humanoid)__instance).GetInventory().GetEquippedItems().Where(MagicSlot.IsTomeItem) .Sum((ItemData item) => item.m_shared.m_eitrRegenModifier); __result += ((Humanoid)__instance).GetInventory().GetEquippedItems().Where(MagicSlot.IsEarringItem) .Sum((ItemData item) => item.m_shared.m_eitrRegenModifier); if (Jewelcrafting.API.IsLoaded()) { __result += (from i in ((Humanoid)__instance).GetInventory().GetEquippedItems() where i.m_shared.m_name.StartsWith("$jc_ring_") || i.m_shared.m_name.StartsWith("$jc_necklace_") select i).Sum((ItemData i) => i.m_shared.m_eitrRegenModifier); } } private static void SetEitr(Player player, string statEffect, float amount, ref float eitr) { if (((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode(statEffect))) { eitr += amount; } } } [HarmonyPatch] public class SEManPatch { [HarmonyPrefix] [HarmonyPatch(typeof(SEMan), "Internal_AddStatusEffect")] public static bool InternalAddStatusEffect_Prefix(SEMan __instance, ref int nameHash) { if (!__instance.HaveStatusEffect(StringExtensionMethods.GetStableHashCode("Arctic Buff"))) { return true; } if (nameHash != StringExtensionMethods.GetStableHashCode("Freezing")) { return nameHash != StringExtensionMethods.GetStableHashCode("Cold"); } return false; } } [HarmonyPatch] public static class SkillsPatch { [HarmonyPatch(typeof(Skills), "RaiseSkill")] public static class RaiseSkillPatch { public static void Prefix(ref SkillType skillType, ref float factor) { //IL_0010: 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_0014: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 if (Plugin._enableExpMultiplier.Value != MagicPlugin.Functions.Toggle.On) { return; } SkillType val = skillType; if ((int)val != 9) { if ((int)val == 10) { factor *= Plugin._bmExpMultiplier.Value; } } else { factor *= Plugin._emExpMultiplier.Value; } } public static void Postfix(Skills __instance, SkillType skillType) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (Plugin._enableExpMultiplier.Value != MagicPlugin.Functions.Toggle.On || Plugin._displayExpGained.Value != MagicPlugin.Functions.Toggle.On || ((int)skillType != 10 && (int)skillType != 9)) { return; } try { if (__instance.GetSkillLevel((SkillType)10) < 100f || __instance.GetSkillLevel((SkillType)9) < 100f) { Skill skill = __instance.GetSkill(skillType); float value = skill.m_accumulator / (skill.GetNextLevelRequirement() / 100f); ((Character)__instance.m_player).Message((MessageType)1, $"Level {skill.m_level.tFloat(0)} {skill.m_info.m_skill} [{skill.m_accumulator.tFloat(2)}/{skill.GetNextLevelRequirement().tFloat(2)}] ({value.tFloat(0)}%)", 0, skill.m_info.m_icon); } } catch { } } } [HarmonyPatch(typeof(Skills), "GetSkillLevel")] [HarmonyPostfix] public static void GetSkillLevel_Postfix(Skills __instance, SkillType skillType, ref float __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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) if ((int)skillType != 9) { if ((int)skillType == 10) { float level = __instance.GetSkill(skillType).m_level; if (((Character)__instance.m_player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("bmp_necromancer"))) { level += ConfigSetup._necromancerBeltBonus.Value; ((Character)__instance.m_player).GetSEMan().ModifySkillLevel(skillType, ref level); __result = level; } else { ((Character)__instance.m_player).GetSEMan().ModifySkillLevel(skillType, ref level); __result = level; } } } else { float level2 = __instance.GetSkill(skillType).m_level; if (((Character)__instance.m_player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("bmp_elementalist"))) { level2 += ConfigSetup._elementalistBeltBonus.Value; ((Character)__instance.m_player).GetSEMan().ModifySkillLevel(skillType, ref level2); __result = level2; } else { ((Character)__instance.m_player).GetSEMan().ModifySkillLevel(skillType, ref level2); __result = level2; } } } } [HarmonyPatch] public class SpawnAbilityPatch { [HarmonyPrefix] [HarmonyPatch(typeof(SpawnAbility), "Spawn")] private static bool Spawn_Prefix(SpawnAbility __instance) { //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_046c: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && __instance.m_weapon != null) { Character owner = __instance.m_owner; Player val = (Player)(object)((owner is Player) ? owner : null); if (val != null) { switch (__instance.m_weapon.m_shared.m_name) { case "$bmp_necktotem": { if (((Character)val).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("necktotem_cooldown"))) { ((Character)val).Message((MessageType)2, "<size=28>Gate of Valhalla is not yet ready.</size>", 0, (Sprite)null); return false; } StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("necktotem_cooldown")); ConfigSetup._neckTotemCooldown.SettingChanged += delegate { statusEffect.m_ttl = ConfigSetup._neckTotemCooldown.Value; }; statusEffect.m_ttl = ConfigSetup._neckTotemCooldown.Value; ((Character)val).GetSEMan().AddStatusEffect(statusEffect, false, 0, 0f); return true; } case "$bmp_wolftotem": { if (((Character)val).GetSkillLevel((SkillType)10) < (float)ConfigSetup._wolfTotemLevel.Value) { ((Character)val).Message((MessageType)2, "<size=28>You're not worthy to summon the <color=red>God of Flames</color></size>", 0, (Sprite)null); return false; } if (((Character)val).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("wolftotem_cooldown"))) { ((Character)val).Message((MessageType)2, "<size=28>Gate of Valhalla is not yet ready!</size>", 0, (Sprite)null); return false; } StatusEffect statusEffect2 = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("wolftotem_cooldown")); ConfigSetup._wolfTotemCooldown.SettingChanged += delegate { statusEffect2.m_ttl = ConfigSetup._wolfTotemCooldown.Value; }; statusEffect2.m_ttl = ConfigSetup._wolfTotemCooldown.Value; ((Character)val).GetSEMan().AddStatusEffect(statusEffect2, false, 0, 0f); return true; } case "$bmp_crystaltotem": { if (((Character)val).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("crystaltotem_cooldown"))) { ((Character)val).Message((MessageType)2, "<size=28>Gate of Valhalla is not yet ready!</size>", 0, (Sprite)null); return false; } StatusEffect statusEffect3 = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("crystaltotem_cooldown")); ConfigSetup._crystalTotemCooldown.SettingChanged += delegate { statusEffect3.m_ttl = ConfigSetup._crystalTotemCooldown.Value; }; statusEffect3.m_ttl = ConfigSetup._crystalTotemCooldown.Value; ((Character)val).GetSEMan().AddStatusEffect(statusEffect3, false, 0, 0f); return true; } case "$bmp_skulltotem": { if (((Character)val).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("skulltotem_cooldown"))) { ((Character)val).Message((MessageType)2, "<size=28>Gate of Valhalla is not yet ready!</size>", 0, (Sprite)null); return false; } StatusEffect statusEffect4 = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("skulltotem_cooldown")); ConfigSetup._skullTotemCooldown.SettingChanged += delegate { statusEffect4.m_ttl = ConfigSetup._skullTotemCooldown.Value; }; statusEffect4.m_ttl = ConfigSetup._skullTotemCooldown.Value; ((Character)val).GetSEMan().AddStatusEffect(statusEffect4, false, 0, 0f); return true; } case "$bmp_modersinheritence": { if (((Character)val).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("modersheritage_cooldown"))) { ((Character)val).Message((MessageType)2, "<size=28>Attack not ready!</size>", 0, (Sprite)null); return false; } StatusEffect statusEffect5 = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("modersheritage_cooldown")); ConfigSetup._modersCooldown.SettingChanged += delegate { statusEffect5.m_ttl = ConfigSetup._modersCooldown.Value; }; statusEffect5.m_ttl = ConfigSetup._modersCooldown.Value; if (ConfigSetup._modersCooldown.Value > 0f) { ((Character)val).GetSEMan().AddStatusEffect(statusEffect5, false, 0, 0f); } Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_himminafl_aoe"), ((Character)val).GetCenterPoint(), Quaternion.identity); return true; } case "$bmp_yagluthsinheritence": { if (((Character)val).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("yagluthsheritage_cooldown"))) { ((Character)val).Message((MessageType)2, "<size=28>Attack not ready!</size>", 0, (Sprite)null); return false; } StatusEffect statusEffect6 = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("yagluthsheritage_cooldown")); ConfigSetup._yagluthsCooldown.SettingChanged += delegate { statusEffect6.m_ttl = ConfigSetup._yagluthsCooldown.Value; }; statusEffect6.m_ttl = ConfigSetup._yagluthsCooldown.Value; if (ConfigSetup._yagluthsCooldown.Value > 0f) { ((Character)val).GetSEMan().AddStatusEffect(statusEffect6, false, 0, 0f); } Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_himminafl_aoe"), ((Character)val).GetCenterPoint(), Quaternion.identity); return true; } default: return true; } } } return true; } } [HarmonyPatch] public class TreeBasePatch { [HarmonyPatch(typeof(TreeBase), "RPC_Damage")] public static class RpcDamagePatch { private static void Prefix(TreeBase __instance, HitData hit) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null && ((Humanoid)val).GetCurrentWeapon() != null && ((Humanoid)val).GetCurrentWeapon() != ((Humanoid)val).m_unarmedWeapon.m_itemData) { int quality = ((Humanoid)val).GetCurrentWeapon().m_quality; if (!(((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name != "BMP_SurtlingStaff") && quality >= __instance.m_minToolTier && hit.m_damage.m_chop > 0f && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { hit.m_toolTier = (short)quality; ((Character)val).RaiseSkill((SkillType)13, 0.2f); } } } } } [HarmonyPatch] public class TreeLogPatch { [HarmonyPatch(typeof(TreeLog), "RPC_Damage")] public static class RpcDamagePatch { private static void Prefix(TreeLog __instance, HitData hit) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null && ((Humanoid)val).GetCurrentWeapon() != null && ((Humanoid)val).GetCurrentWeapon() != ((Humanoid)val).m_unarmedWeapon.m_itemData) { int quality = ((Humanoid)val).GetCurrentWeapon().m_quality; if (!(((Object)((Humanoid)val).GetCurrentWeapon().m_dropPrefab).name != "BMP_SurtlingStaff") && quality >= __instance.m_minToolTier && hit.m_damage.m_chop > 0f && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { hit.m_toolTier = (short)quality; ((Character)val).RaiseSkill((SkillType)13, 0.2f); } } } } } [HarmonyPatch] public class VisEquipmentPatch { [HarmonyPatch(typeof(VisEquipment), "OnEnable")] [HarmonyPostfix] private static void OnEnable_Postfix(VisEquipment __instance) { if (!MagicSlot._magicSlots.ContainsKey(__instance) && __instance.m_isPlayer) { MagicSlot._magicSlots[__instance] = new MagicSlot(__instance); } } [HarmonyPostfix] [HarmonyPatch(typeof(VisEquipment), "OnDisable")] private static void OnDisable_Postfix(VisEquipment __instance) { MagicSlot._magicSlots.Remove(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(VisEquipment), "UpdateEquipmentVisuals")] private static void UpdateEquipmentVisuals_Postfix(VisEquipment __instance) { if (__instance.m_isPlayer) { MagicSlot._magicSlots[__instance].UpdateEquipmentVisuals(); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] public class ZNetScenePatch { public static void Postfix(ZNetScene __instance) { //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_006c: 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_007b: Expected O, but got Unknown if (!((Object)(object)__instance == (Object)null)) { List<GameObject> prefabs = __instance.m_prefabs; if (prefabs != null && prefabs.Count > 0) { Plugin.PrefabContainer(); PrefabsSetup.CreateSummon(__instance); SpawnAbility component = Plugin._skullTotemProjectile.GetComponent<SpawnAbility>(); component.m_spawnPrefab = (GameObject[])(object)new GameObject[1] { Plugin._armoredSkellies }; component.m_preSpawnEffects.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { new EffectData { m_prefab = __instance.GetPrefab("fx_summon_skeleton_spawn"), m_enabled = true, m_variant = 0 } }; } } } } } namespace MagicPlugin.JCAdditions { public static class RingsAndNecklaces { public static ConfigEntry<float> _eitrRingEitr; public static ConfigEntry<float> _eitrNecklaceEitr; public static void Init() { if (Jewelcrafting.API.IsLoaded()) { DvergrRing(); EitrRing(); FireResistRing(); FrostResistRing(); PoisonResistRing(); DvergrNecklace(); EitrNecklace(); FireResistNecklace(); FrostResistNecklace(); PoisonResistNecklace(); } } private static void DvergrRing() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) Item item = new Item(Jewelcrafting.API.CreateRingFromTemplate("Blue", Color.blue)); ItemDrop component = item.Prefab.GetComponent<ItemDrop>(); component.m_itemData.m_shared.m_name = "$jc_ring_dvergrring"; component.m_itemData.m_shared.m_description = "$jc_ring_dvergrring_description"; component.m_itemData.m_shared.m_maxQuality = 1; component.m_itemData.m_shared.m_eitrRegenModifier = 0.25f; item.Crafting.Add(((Object)Jewelcrafting.API.GetGemcuttersTable()).name, 3); item.MaximumRequiredStationLevel = 3; item.RequiredItems.Add("Perfect_Blue_Socket", 5); item.RequiredItems.Add("Chain", 2); item.RequiredItems.Add("Eitr", 16); item.Configurable = Configurability.Recipe | Configurability.Stats; } private static void EitrRing() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown Item item = new Item(Jewelcrafting.API.CreateRingFromTemplate("Purple", new Color(128f, 0f, 128f))); ItemDrop component = item.Prefab.GetComponent<ItemDrop>(); component.m_itemData.m_shared.m_name = "$jc_ring_eitrring"; component.m_itemData.m_shared.m_description = "$jc_ring_eitrring_description"; component.m_itemData.m_shared.m_maxQuality = 1; string group = Localization.instance.Localize("$jc_ring_eitrring").Trim(); _eitrRingEitr = Plugin._Instance.config(group, "Eitr Bonus", 46f, new ConfigDescription("Eitr ring eitr bonus.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { new MagicPlugin.Functions.ConfigurationManagerAttributes { ShowRangeAsPercent = false } })); item.Crafting.Add(((Object)Jewelcrafting.API.GetGemcuttersTable()).name, 3); item.MaximumRequiredStationLevel = 3; item.RequiredItems.Add("Perfect_Purple_Socket", 5); item.RequiredItems.Add("Chain", 2); item.RequiredItems.Add("Eitr", 16); item.Configurable = Configurability.Recipe; AddEitr statusEffect = ScriptableObject.CreateInstance<AddEitr>(); ((Object)statusEffect).name = "bmp_eitr_ring"; ((StatusEffect)statusEffect).m_name = component.m_itemData.m_shared.m_name; AddEitr addEitr = statusEffect; ItemData itemData = component.m_itemData; ((StatusEffect)addEitr).m_icon = ((itemData != null) ? itemData.GetIcon() : null); _eitrRingEitr.SettingChanged += delegate { statusEffect.SetEitr(_eitrRingEitr.Value); }; statusEffect.SetEitr(_eitrRingEitr.Value); component.m_itemData.m_shared.m_equipStatusEffect = (StatusEffect)(object)statusEffect; } private static void FireResistRing() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) Item item = new Item(Jewelcrafting.API.CreateRingFromTemplate("Red", Color.red)); ItemDrop component = item.Prefab.GetComponent<ItemDrop>(); component.m_itemData.m_shared.m_name = "$jc_ring_fireresistring"; component.m_itemData.m_shared.m_description = "$jc_ring_fireresistring_description"; component.m_itemData.m_shared.m_maxQuality = 1; item.Crafting.Add(((Object)Jewelcrafting.API.GetGemcuttersTable()).name, 3); item.MaximumRequiredStationLevel = 3; item.RequiredItems.Add("Perfect_Red_Socket", 5); item.RequiredItems.Add("Chain", 2); item.RequiredItems.Add("TrophySurtling", 1); item.Configurable = Configurability.Recipe; SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>(); ((Object)val).name = "bmp_fireresist_ring"; ((StatusEffect)val).m_name = component.m_itemData.m_shared.m_name; ((StatusEffect)val).m_icon = component.m_itemData.GetIcon(); val.m_mods = new List<DamageModPair>(1) { new DamageModPair { m_type = (DamageType)32, m_modifier = (DamageModifier)5 } }; component.m_itemData.m_shared.m_equipStatusEffect = (StatusEffect)(object)val; } private static void FrostResistRing() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) Item item = new Item(Jewelcrafting.API.CreateRingFromTemplate("Cyan", Color.cyan)); ItemDrop component = item.Prefab.GetComponent<ItemDrop>(); component.m_itemData.m_shared.m_name = "$jc_ring_frostresistring"; component.m_itemData.m_shared.m_description = "$jc_ring_frostresistring_description"; component.m_itemData.m_shared.m_maxQuality = 1; item.Crafting.Add(((Object)Jewelcrafting.API.GetGemcuttersTable()).name, 3); item.MaximumRequiredStationLevel = 3; item.RequiredItems.Add("Perfect_Blue_Socket", 5); item.RequiredItems.Add("Chain", 2); item.RequiredItems.Add("FreezeGland", 16); item.Configurable = Configurability.Recipe; SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>(); ((Object)val).name = "bmp_frostresist_ring"; ((StatusEffect)val).m_name = component.m_itemData.m_shared.m_name; ((StatusEffect)val).m_icon = component.m_itemData.GetIcon(); val.m_mods = new List<DamageModPair>(1) { new DamageModPair { m_type = (DamageType)64, m_modifier = (DamageModifier)5 } }; component.m_itemData.m_shared.m_equipStatusEffect = (StatusEffect)(object)val; } private static void PoisonResistRing() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) Item item = new Item(Jewelcrafting.API.CreateRingFromTemplate("Green", Color.green)); ItemDrop component = item.Prefab.GetComponent<ItemDrop>(); component.m_itemData.m_shared.m_name = "$jc_ring_poisonresistring"; component.m_itemData.m_shared.m_description = "$jc_ring_poisonresistring_description"; component.m_itemData.m_shared.m_maxQuality = 1; item.Crafting.Add(((Object)Jewelcrafting.API.GetGemcuttersTable()).name, 3); item.MaximumRequiredStationLevel = 3; item.RequiredItems.Add("Perfect_Green_Socket", 5); item.RequiredItems.Add("Chain", 2); item.RequiredItems.Add("Guck", 16); item.Configurable = Configurability.Recipe; SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>(); ((Object)val).name = "bmp_poisonresist_ring"; ((StatusEffect)val).m_name = component.m_itemData.m_shared.m_name; ((StatusEffect)val).m_icon = component.m_itemData.GetIcon(); val.m_mods = new List<DamageModPair>(1) { new DamageModPair { m_type = (DamageType)256, m_modifier = (DamageModifier)5 } }; component.m_itemData.m_shared.m_equipStatusEffect = (StatusEffect)(object)val; } private static void DvergrNecklace() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) Item item = new Item(Jewelcrafting.API.CreateNecklaceFromTemplate("Blue", Color.blue)); ItemDrop component = item.Prefab.GetComponent<ItemDrop>(); component.m_itemData.m_shared.m_name = "$jc_necklace_dvergrnecklace"; component.m_itemData.m_shared.m_description = "$jc_necklace_dvergrnecklace_description"; component.m_itemData.m_shared.m_maxQuality = 1; component.m_itemData.m_shared.m_eitrRegenModifier = 0.25f; item.Crafting.Add(((Object)Jewelcrafting.API.GetGemcuttersTable()).name, 3); item.MaximumRequiredStationLevel = 3; item.RequiredItems.Add("Perfect_Blue_Socket", 5); item.RequiredItems.Add("Chain", 2); item.Configurable = Configurability.Recipe | Configurability.Stats; } private static void EitrNecklace() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown Item item = new Item(Jewelcrafting.API.CreateNecklaceFromTemplate("Purple", new Color(128f, 0f, 128f))); ItemDrop component = item.Prefab.GetComponent<ItemDrop>(); component.m_itemData.m_shared.m_name = "$jc_necklace_eitrnecklace"; component.m_itemData.m_shared.m_description = "$jc_necklace_eitrnecklace_description"; component.m_itemData.m_shared.m_maxQuality = 1; string group = Localization.instance.Localize("$jc_necklace_eitrnecklace").Trim(); _eitrNecklaceEitr = Plugin._Instance.config(group, "Eitr Bonus", 42f, new ConfigDescription("Eitr necklace eitr bonus.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { new MagicPlugin.Functions.ConfigurationManagerAttributes { ShowRangeAsPercent = false } })); item.Crafting.Add(((Object)Jewelcrafting.API.GetGemcuttersTable()).name, 3); item.MaximumRequiredStationLevel = 3; item.RequiredItems.Add("Perfect_Purple_Socket", 5); item.RequiredItems.Add("Chain", 2); item.RequiredItems.Add("Eitr", 16); item.Configurable = Configurability.Recipe; AddEitr statusEffect = ScriptableObject.CreateInstance<AddEitr>(); ((Object)statusEffect).name = "bmp_eitr_necklace"; ((StatusEffect)statusEffect).m_name = component.m_itemData.m_shared.m_name; ((StatusEffect)statusEffect).m_icon = component.m_itemData.GetIcon(); _eitrNecklaceEitr.SettingChanged += delegate { statusEffect.SetEitr(_eitrNecklaceEitr.Value); }; statusEffect.SetEitr(_eitrNecklaceEitr.Value); component.m_itemData.m_shared.m_equipStatusEffect = (StatusEffect)(object)statusEffect; } private static void FireResistNecklace() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) Item item = new Item(Jewelcrafting.API.CreateNecklaceFromTemplate("Red", Color.red)); ItemDrop component = item.Prefab.GetComponent<ItemDrop>(); component.m_itemData.m_shared.m_name = "$jc_necklace_fireresistnecklace"; component.m_itemData.m_shared.m_description = "$jc_necklace_fireresistnecklace_description"; component.m_itemData.m_shared.m_maxQuality = 1; item.Crafting.Add(((Object)Jewelcrafting.API.GetGemcuttersTable()).name, 3); item.MaximumRequiredStationLevel = 3; item.RequiredItems.Add("Perfect_Red_Socket", 5); item.RequiredItems.Add("Chain", 2); item.RequiredItems.Add("TrophySurtling", 1); item.Configurable = Configurability.Recipe; SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>(); ((Object)val).name = "bmp_fireresist_necklace"; ((StatusEffect)val).m_name = component.m_itemData.m_shared.m_name; ((StatusEffect)val).m_icon = component.m_itemData.GetIcon(); val.m_mods = new List<DamageModPair>(1) { new DamageModPair { m_type = (DamageType)32, m_modifier = (DamageModifier)5 } }; component.m_itemData.m_shared.m_equipStatusEffect = (StatusEffect)(object)val; } private static void FrostResistNecklace() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) Item item = new Item(Jewelcrafting.API.CreateNecklaceFromTemplate("Cyan", Color.cyan)); ItemDrop component = item.Prefab.GetComponent<ItemDrop>(); component.m_itemData.m_shared.m_name = "$jc_necklace_frostresistnecklace"; component.m_itemData.m_shared.m_description = "$jc_necklace_frostresistnecklace_description"; component.m_itemData.m_shared.m_maxQuality = 1; item.Crafting.Add(((Object)Jewelcrafting.API.GetGemcuttersTable()).name, 3); item.MaximumRequiredStationLevel = 3; item.RequiredItems.Add("Perfect_Blue_Socket", 5); item.RequiredItems.Add("Chain", 2); item.RequiredItems.Add("FreezeGland", 16); item.Configurable = Configurability.Recipe; SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>(); ((Object)val).name = "bmp_frostresist_necklace"; ((StatusEffect)val).m_name = component.m_itemData.m_shared.m_name; ((StatusEffect)val).m_icon = component.m_itemData.GetIcon(); val.m_mods = new List<DamageModPair>(1) { new DamageModPair { m_type = (DamageType)64, m_modifier = (DamageModifier)5 } }; component.m_itemData.m_shared.m_equipStatusEffect = (StatusEffect)(object)val; } private static void PoisonResistNecklace() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) Item item = new Item(Jewelcrafting.API.CreateNecklaceFromTemplate("Green", Color.green)); ItemDrop component = item.Prefab.GetComponent<ItemDrop>(); component.m_itemData.m_shared.m_name = "$jc_necklace_poisonresistnecklace"; component.m_itemData.m_shared.m_description = "$jc_necklace_poisonresistnecklace_description"; component.m_itemData.m_shared.m_maxQuality = 1; item.Crafting.Add(((Object)Jewelcrafting.API.GetGemcuttersTable()).name, 3); item.MaximumRequiredStationLevel = 3; item.RequiredItems.Add("Perfect_Green_Socket", 5); item.RequiredItems.Add("Chain", 2); item.RequiredItems.Add("Guck", 16); item.Configurable = Configurability.Recipe; SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>(); ((Object)val).name = "bmp_poisonresist_necklace"; ((StatusEffect)val).m_name = component.m_itemData.m_shared.m_name; ((StatusEffect)val).m_icon = component.m_itemData.GetIcon(); val.m_mods = new List<DamageModPair>(1) { new DamageModPair { m_type = (DamageType)256, m_modifier = (DamageModifier)5 } }; component.m_itemData.m_shared.m_equipStatusEffect = (StatusEffect)(object)val; } } } namespace MagicPlugin.Functions { public class ArmoredSkeleton : MonoBehaviour { public string[] m_weapons2h = new string[8] { "THSwordKrom", "Battleaxe", "BattleaxeCrystal", "AtgeirBlackmetal", "AtgeirHimminAfl", "AtgeirIron", "SledgeDemolisher", "SledgeIron" }; public string[] m_helmet = new string[4] { "HelmetIron", "HelmetDrake", "HelmetPadded", "HelmetCarapace" }; public string[] m_chest = new string[4] { "ArmorIronChest", "ArmorWolfChest", "ArmorPaddedCuirass", "ArmorCarapaceChest" }; public string[] m_legs = new string[4] { "ArmorIronLegs", "ArmorWolfLegs", "ArmorPaddedGreaves", "ArmorCarapaceLegs" }; public string[] m_cape = new string[3] { "CapeWolf", "CapeFeather", "CapeLox" }; private VisEquipment m_visEquipment; private Humanoid m_humanoid; private void Awake() { //IL_0028: 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) m_visEquipment = ((Component)this).GetComponent<VisEquipment>(); m_humanoid = ((Component)this).GetComponent<Humanoid>(); Helper.seed += (int)((((Component)this).gameObject.transform.position.x + ((Component)this).gameObject.transform.position.y) * 1000f); SetupRandomEquipment(); SetupRandomWeapons(); } private void SetupRandomEquipment() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown ItemSet[] array = new ItemSet[1]; ItemSet val = new ItemSet(); val.m_items = (GameObject[])(object)new GameObject[4] { ObjectDB.instance.GetItemPrefab(m_helmet.GetRandomElement()), ObjectDB.instance.GetItemPrefab(m_chest.GetRandomElement()), ObjectDB.instance.GetItemPrefab(m_legs.GetRandomElement()), ObjectDB.instance.GetItemPrefab(m_cape.GetRandomElement()) }; array[0] = val; ItemSet[] randomSets = (ItemSet[])(object)array; m_humanoid.m_randomSets = randomSets; } private void SetupRandomWeapons() { m_humanoid.m_randomWeapon = (GameObject[])(object)new GameObject[1] { ObjectDB.instance.GetItemPrefab(m_weapons2h.GetRandomElement()) }; m_visEquipment.SetRightItem(((Object)ObjectDB.instance.GetItemPrefab(m_weapons2h.GetRandomElement())).name); m_visEquipment.SetRightHandEquipped(StringExtensionMethods.GetStableHashCode(((Object)ObjectDB.instance.GetItemPrefab(m_weapons2h.GetRandomElement())).name)); } } public static class ConfigSetup { public static ConfigEntry<float> _eitrBeltEitrBonus; public static ConfigEntry<float> _elementalistBeltBonus; public static ConfigEntry<float> _necromancerBeltBonus; public static ConfigEntry<float> _dvergrBeltBonus; public static ConfigEntry<float> _hogwartsBeltBonus; public static ConfigEntry<float> _surtlingStaffAOE; public static ConfigEntry<float> _neckTotemCooldown; public static ConfigEntry<float> _wolfTotemCooldown; public static ConfigEntry<int> _wolfTotemLevel; public static ConfigEntry<float> _crystalTotemCooldown; public static ConfigEntry<float> _skullTotemCooldown; public static ConfigEntry<float> _eikthyrStaffAOE; public static ConfigEntry<float> _lightningStaffAOE; public static ConfigEntry<float> _arcticStaffAOE; public static ConfigEntry<float> _healOverTime; public static ConfigEntry<float> _healOverTimeDuration; public static ConfigEntry<float> _healOverTimeInterval; public static ConfigEntry<float> _healStaffCooldown; public static ConfigEntry<float> _poisonStaffAOE; public static ConfigEntry<float> _modersPierceDamage; public static ConfigEntry<float> _modersChopDamage; public static ConfigEntry<float> _modersPickaxeDamage; public static ConfigEntry<float> _modersFrostDamage; public static ConfigEntry<float> _modersAoeRange; public static ConfigEntry<float> _modersEitrDrain; public static ConfigEntry<float> _modersStaminaDrain; public static ConfigEntry<float> _yagluthBluntDamage; public static ConfigEntry<float> _yagluthChopDamage; public static ConfigEntry<float> _yagluthPickaxeDamage; public static ConfigEntry<float> _yagluthFireDamage; public static ConfigEntry<float> _yagluthAoeRange; public static ConfigEntry<float> _yagluthsEitrDrain; public static ConfigEntry<float> _yagluthsStaminaDrain; public static ConfigEntry<float> _neckzillaHealth; public static ConfigEntry<float> _neckzillaAtkDmgSlash; public static ConfigEntry<float> _neckzillaAtkDmgPoison; public static ConfigEntry<float> _neckzillaAtkDmg2; public static ConfigEntry<float> _occultistHealth; public static ConfigEntry<float> _occultistAtk1Slash; public static ConfigEntry<float> _occultistAtk1Fire; public static ConfigEntry<float> _occultistAtk2Slash; public static ConfigEntry<float> _occultistAtk2Fire; public static ConfigEntry<float> _occultistAtk3Fire; public static ConfigEntry<float> _armoredSkeletonHealth; public static ConfigEntry<float> _toxicSlimeHealth; public static ConfigEntry<float> _toxicSlimeAoe; public static ConfigEntry<float> _fierySlimeHealth; public static ConfigEntry<float> _fierySlimeAoe; public static ConfigEntry<float> _frostySlimeHealth; public static ConfigEntry<float> _frostySlimeAoe; public static ConfigEntry<float> _lightningSlimeHealth; public static ConfigEntry<float> _lightningSlimeAoe; public static ConfigEntry<float> _beginnersBookEitr; public static ConfigEntry<float> _advanceBookEitr; public static ConfigEntry<float> _druidsTomeEitr; public static ConfigEntry<float> _flameScepterMagicSourcePrimary; public static ConfigEntry<float> _flameScepterMagicSourceSecondary; public static ConfigEntry<float> _iceScepterMagicSourcePrimary; public static ConfigEntry<float> _iceScepterMagicSourceSecondary; public static ConfigEntry<float> _lightningScepterMagicSourcePrimary; public static ConfigEntry<float> _lightningScepterMagicSourceSecondary; public static ConfigEntry<float> _eitrEarringEitr; public static ConfigEntry<float> _modersCooldown; public static ConfigEntry<float> _yagluthsCooldown; public static ConfigEntry<float> _tatteredCapeEitr; public static ConfigEntry<float> _tatteredChestEitr; public static ConfigEntry<float> _tatteredHelmEitr; public static ConfigEntry<float> _tatteredLegsEitr; public static ConfigEntry<float> _sorcerersCapeEitr; public static ConfigEntry<float> _sorcerersTunicEitr; public static ConfigEntry<float> _sorcerersHatEitr; public static ConfigEntry<float> _sorcerersTrousersEitr; public static ConfigEntry<float> _warlocksCapeEitr; public static ConfigEntry<float> _warlocksVestEitr; public static ConfigEntry<float> _warlocksHoodEitr; public static ConfigEntry<float> _warlocksPantsEitr; public static ConfigEntry<float> _polarWolfCapeEitr; public static ConfigEntry<float> _polarWolfChestEitr; public static ConfigEntry<float> _polarWolfHoodEitr; public static ConfigEntry<float> _polarWolfLegEitr; public static ConfigEntry<float> _seekerCapeEitr; public static ConfigEntry<float> _seekerChestEitr; public static ConfigEntry<float> _seekerHatEitr; public static ConfigEntry<float> _seekerLegsEitr; public static ConfigEntry<float> _crimsonCapeEitr; public static ConfigEntry<float> _crimsonChestEitr; public static ConfigEntry<float> _crimsonHoodEitr; public static ConfigEntry<float> _crimsonLegsEitr; public static ConfigEntry<MagicSource> _flameScepterSource; public static ConfigEntry<MagicSource> _iceScepterSource; public static ConfigEntry<MagicSource> _lightningScepterSource; public static void Init() { TatteredSet(); SorcerersSets(); WarlocksSets(); PolarWolfSets(); SeekerSets(); CrimsonSets(); DvergrBelt(); EitrBelt(); ElementalistBelt(); HogwartsBelt(); NecromancerBelt(); CrystalTotem(); EikthyrStaff(); LightningStaff(); ArcticStaff(); HealStaff(); ModersHeritage(); NeckTotem(); PoisonStaff(); SurtlingStaff(); WolfTotem(); YagluthsHeritage(); SkullTotem(); Others(); BeginnersBook(); AdvanceBook(); FlameScepter(); IceScepter(); LightningScepter(); DruidsTome(); Earrings(); } private static void TatteredSet() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown string group = Localization.instance.Localize("$bmr_tattered_cape").Trim(); _tatteredCapeEitr = Plugin._Instance.config(group, "Eitr Bonus", 10f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group2 = Localization.instance.Localize("$bmr_tattared_chest").Trim(); _tatteredChestEitr = Plugin._Instance.config(group2, "Eitr Bonus", 12f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group3 = Localization.instance.Localize("$bmr_tattered_helm").Trim(); _tatteredHelmEitr = Plugin._Instance.config(group3, "Eitr Bonus", 10f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group4 = Localization.instance.Localize("$bmr_tattered_legs").Trim(); _tatteredLegsEitr = Plugin._Instance.config(group4, "Eitr Bonus", 12f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); } private static void SorcerersSets() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown string group = Localization.instance.Localize("$bmr_sorcerers_cape").Trim(); _sorcerersCapeEitr = Plugin._Instance.config(group, "Eitr Bonus", 14f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group2 = Localization.instance.Localize("$bmr_sorcerers_hat").Trim(); _sorcerersHatEitr = Plugin._Instance.config(group2, "Eitr Bonus", 16f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group3 = Localization.instance.Localize("$bmr_sorcerers_trousers").Trim(); _sorcerersTrousersEitr = Plugin._Instance.config(group3, "Eitr Bonus", 14f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group4 = Localization.instance.Localize("$bmr_sorcerers_tunic").Trim(); _sorcerersTunicEitr = Plugin._Instance.config(group4, "Eitr Bonus", 16f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); } private static void WarlocksSets() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown string group = Localization.instance.Localize("$bmr_warlocks_cape").Trim(); _warlocksCapeEitr = Plugin._Instance.config(group, "Eitr Bonus", 22f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group2 = Localization.instance.Localize("$bmr_warlocks_hood").Trim(); _warlocksHoodEitr = Plugin._Instance.config(group2, "Eitr Bonus", 24f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group3 = Localization.instance.Localize("$bmr_warlocks_pants").Trim(); _warlocksPantsEitr = Plugin._Instance.config(group3, "Eitr Bonus", 22f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group4 = Localization.instance.Localize("$bmr_warlocks_vest"); _warlocksVestEitr = Plugin._Instance.config(group4, "Eitr Bonus", 24f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); } private static void PolarWolfSets() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown string group = Localization.instance.Localize("$bmr_polarwolf_cape").Trim(); _polarWolfCapeEitr = Plugin._Instance.config(group, "Eitr Bonus", 18f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group2 = Localization.instance.Localize("$bmr_polarwolf_chest").Trim(); _polarWolfChestEitr = Plugin._Instance.config(group2, "Eitr Bonus", 20f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group3 = Localization.instance.Localize("$bmr_polarwolf_hood").Trim(); _polarWolfHoodEitr = Plugin._Instance.config(group3, "Eitr Bonus", 18f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); string group4 = Localization.instance.Localize("$bmr_polarwolf_legs").Trim(); _polarWolfLegEitr = Plugin._Instance.config(group4, "Eitr Bonus", 20f, new ConfigDescription("Eitr amount given to player when equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); } private static void SeekerSets() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown string group = Localization.instance.Localize("$bmr_seeker_cape").Trim(); _seekerCapeEitr = Plugin._Instance.config(group, "Eitr Bonus", 26f, new ConfigDescription("Eitr amount given to player when equi
Plugins/MultiCraft.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CraftFromContainers; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] namespace MultiCraft; [HarmonyPatch(typeof(InventoryGui), "Show")] public static class CraftGUI_Patch { private static void Postfix(Container container) { MultiCraft_UI.instance?.Start(); MultiCraft_Logic.instance?.Start(); } public static void Update() { if (MultiCraft_Logic.Started && InventoryGui.IsVisible()) { MultiCraft_Logic.instance.Update(); } } } [HarmonyPatch(typeof(InventoryGui), "Hide")] public static class CraftGUI_Hide_Patch { private static void Postfix() { if (MultiCraft_Logic.Started) { MultiCraft_Logic.instance.ResetMultiCrafting(); } } } internal class Helper { public static ManualLogSource Logger; public static bool CraftFromContainersRunning = false; private static string CraftFromContainersGUID = "aedenthorn.CraftFromContainers"; public static bool CraftFromContainersInstalledAndActive { get; private set; } public static void CheckAvailabilityForCraftFromContainersPlugin() { CraftFromContainersRunning = false; BaseUnityPlugin[] componentsInChildren = GameObject.Find("BepInEx_Manager").GetComponentsInChildren<BaseUnityPlugin>(); for (int i = 0; i < componentsInChildren.Length; i++) { if (componentsInChildren[i].Info.Metadata.GUID == CraftFromContainersGUID) { CraftFromContainersRunning = IsCraftFromContainersEnabled(); } } } public static bool IsCraftFromContainersEnabled() { GameObject val = GameObject.Find("BepInEx_Manager"); Debug.Log((object)("Found bepInExManager: " + (object)val)); BaseUnityPlugin[] componentsInChildren = val.GetComponentsInChildren<BaseUnityPlugin>(); for (int i = 0; i < componentsInChildren.Length; i++) { if (componentsInChildren[i].Info.Metadata.GUID == "aedenthorn.CraftFromContainers") { return BepInExPlugin.modEnabled.Value; } } return false; } public static int GetAvailableItems(string itemName) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return 0; } int num = 0; if (CraftFromContainersRunning) { num = GetItemsInCloseContainers(itemName); } return ((Humanoid)localPlayer).GetInventory().CountItems(itemName, -1, true) + num; } public static int GetItemsInCloseContainers(string itemName) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (CraftFromContainersRunning) { int num = 0; { foreach (Container nearbyContainer in BepInExPlugin.GetNearbyContainers(((Component)Player.m_localPlayer).transform.position)) { num += nearbyContainer.GetInventory().CountItems(itemName, -1, true); } return num; } } return ((Humanoid)Player.m_localPlayer).GetInventory().CountItems(itemName, -1, true); } } [HarmonyPatch(typeof(Menu), "Start", new Type[] { })] public static class MainMenuShow_Patch { private static void Postfix() { Helper.CheckAvailabilityForCraftFromContainersPlugin(); } } [BepInPlugin("maximods.valheim.multicraft", "MultiCraft", "1.3.0")] [BepInProcess("valheim.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class MultiCraftPlugin : BaseUnityPlugin { public const string pluginGuid = "maximods.valheim.multicraft"; public const string pluginName = "MultiCraft"; public const string pluginVersion = "1.3.0"; public static ConfigEntry<bool> CapMaximumCrafts; private Harmony _harmony; public static bool CraftFromContainersInstalledAndActive; private static List<Container> cachedContainers; public void Awake() { CapMaximumCrafts = ((BaseUnityPlugin)this).Config.Bind<bool>("MultiCraft", "CapMaximumCrafts", false, "Caps the maximum amount to craft to the maximum possible to craft."); Helper.Logger = ((BaseUnityPlugin)this).Logger; _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { CraftGUI_Patch.Update(); } private void LateUpdate() { if (CraftFromContainersInstalledAndActive && cachedContainers != null) { cachedContainers.Clear(); cachedContainers = null; } } } public class MultiCraft_Logic { private static MultiCraft_Logic _instance; public static bool Started; private int _CurrentCraftAmount = 1; public int value = 5; private bool WasCrafting; private int WaitUpdates; public static MultiCraft_Logic instance { get { if (_instance == null) { _instance = new MultiCraft_Logic(); } return _instance; } } public int CurrentCraftAmount { get { return _CurrentCraftAmount; } set { _CurrentCraftAmount = value; MultiCraft_UI.instance.UpdateAmountLabel(_CurrentCraftAmount); } } public void Start() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown Started = true; CurrentCraftAmount = 1; CurrentRecipeInformation.OnRecipeChanged.AddListener(new UnityAction(OnRecipeChanged)); } public void OnRecipeChanged() { ResetMultiCrafting(); } public void ResetMultiCrafting() { CurrentCraftAmount = 1; CancelMultiCrafting(); } public void CancelMultiCrafting() { WasCrafting = false; if (Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.instance.InCraftTab()) { MultiCraft_UI.instance.UnblockCustomButtons(); } } public void StartCraftingLogic() { WasCrafting = true; WaitUpdates = 5; } public void SetCraftAmount(int value) { CurrentCraftAmount = value; } public void AddToCraftAmount(int delta) { CurrentCraftAmount += delta; if (MultiCraftPlugin.CapMaximumCrafts.Value) { CurrentCraftAmount = Math.Min(CurrentCraftAmount, CurrentRecipeInformation.instance.GetCurrentMaxCraftable()); } if (CurrentCraftAmount < 1) { CurrentCraftAmount = 1; } } public bool IsCrafting() { return ((Component)InventoryGui.instance.m_craftProgressBar).gameObject.activeInHierarchy; } public void Update() { if (WaitUpdates-- <= 0 && WasCrafting && !IsCrafting()) { if (CurrentCraftAmount <= 1) { CancelMultiCrafting(); } else { TryNextCraft(); } } } public void TryNextCraft() { WasCrafting = false; if (CurrentCraftAmount > 1) { int currentCraftAmount = CurrentCraftAmount - 1; CurrentCraftAmount = currentCraftAmount; if (!instance.CanCraft()) { CancelMultiCrafting(); } else { ((UnityEvent)((Component)InventoryGui.instance.m_craftButton).GetComponent<Button>().onClick).Invoke(); } } } public bool CanCraft() { return MultiCraft_UI.instance.IsCraftButtonEnabled(); } } public class MultiCraft_UI { private class UI_Names { public static string PLUS_BUTTON = "plus"; public static string MINUS_BUTTON = "minus"; public static string AMOUNT_TEXT = "amountText"; } private static MultiCraft_UI _instance; public static bool Started; private RectTransform plusButton; private RectTransform minusButton; private RectTransform amountText; public static MultiCraft_UI instance { get { if (_instance == null) { _instance = new MultiCraft_UI(); } return _instance; } } public void Start() { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown InventoryGui val = InventoryGui.instance; CreateSpaceFromCraftButton(val); plusButton = FindUiComponent(UI_Names.PLUS_BUTTON); if (!Object.op_Implicit((Object)(object)plusButton)) { Helper.Logger.LogMessage((object)"Creating new plus button"); Started = false; plusButton = CreateMultiCraftButton(val, UI_Names.PLUS_BUTTON, "+"); AttachButtonsToRight((Transform)(object)plusButton, 0.8f); ((UnityEvent)((Component)plusButton).GetComponent<Button>().onClick).AddListener(new UnityAction(OnPlusButtonPressed)); } minusButton = FindUiComponent(UI_Names.MINUS_BUTTON); if (!Object.op_Implicit((Object)(object)minusButton)) { Helper.Logger.LogMessage((object)"Creating new minus button"); Started = false; minusButton = CreateMultiCraftButton(val, UI_Names.MINUS_BUTTON, "-"); AttachButtonsToRight((Transform)(object)minusButton, 0.1f); ((UnityEvent)((Component)minusButton).GetComponent<Button>().onClick).AddListener(new UnityAction(OnMinusButtonPressed)); } amountText = FindUiComponent(UI_Names.AMOUNT_TEXT); if (!Object.op_Implicit((Object)(object)amountText)) { Helper.Logger.LogMessage((object)"CreatingNewAmountText"); Started = false; CreateAmountLabel(); } if (!Started) { ((UnityEvent)val.m_craftButton.onClick).AddListener(new UnityAction(OnCraftButtonPressed)); ((UnityEvent)val.m_craftCancelButton.onClick).AddListener(new UnityAction(OnCraftCancelledButtonPressed)); ((UnityEvent)val.m_tabCraft.onClick).AddListener(new UnityAction(TabCraftPressed)); ((UnityEvent)val.m_tabUpgrade.onClick).AddListener(new UnityAction(UpgradeTabPressed)); } Started = true; } public RectTransform FindUiComponent(string name) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown return (RectTransform)((Component)((Component)InventoryGui.instance.m_craftButton).transform.parent).transform.Find(name); } public void TabCraftPressed() { UnblockCustomButtons(); ChangedTab(); } public void UpgradeTabPressed() { BlockCustomButtons(); ChangedTab(); } public bool IsCraftButtonEnabled() { return ((Selectable)((Component)InventoryGui.instance.m_craftButton).GetComponent<Button>()).interactable; } public void ChangedTab() { MultiCraft_Logic.instance.ResetMultiCrafting(); } public void BlockCustomButtons() { if ((Object)(object)plusButton != (Object)null && (Object)(object)((Component)plusButton).GetComponent<Button>() != (Object)null) { ((Behaviour)((Component)plusButton).GetComponent<Button>()).enabled = false; } if ((Object)(object)minusButton != (Object)null && (Object)(object)((Component)minusButton).GetComponent<Button>() != (Object)null) { ((Behaviour)((Component)minusButton).GetComponent<Button>()).enabled = false; } } public void UnblockCustomButtons() { if ((Object)(object)plusButton != (Object)null && (Object)(object)((Component)plusButton).GetComponent<Button>() != (Object)null) { ((Behaviour)((Component)plusButton).GetComponent<Button>()).enabled = true; } if ((Object)(object)minusButton != (Object)null && (Object)(object)((Component)minusButton).GetComponent<Button>() != (Object)null) { ((Behaviour)((Component)minusButton).GetComponent<Button>()).enabled = true; } } public void OnCraftCancelledButtonPressed() { MultiCraft_Logic.instance.CancelMultiCrafting(); } public void OnCraftButtonPressed() { MultiCraft_Logic.instance.StartCraftingLogic(); BlockCustomButtons(); } public void CreateAmountLabel() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)InventoryGui.instance.m_craftButton).transform.Find("Text"); amountText = (RectTransform)((Component)Object.Instantiate<Transform>(val, ((Component)InventoryGui.instance.m_craftButton).transform.parent)).transform; ((Object)amountText).name = UI_Names.AMOUNT_TEXT; ((TMP_Text)((Component)amountText).GetComponent<TextMeshProUGUI>()).text = $"{MultiCraft_Logic.instance.CurrentCraftAmount}"; amountText.SetSizeWithCurrentAnchors((Axis)0, 50f); amountText.SetSizeWithCurrentAnchors((Axis)1, 50f); amountText.pivot = new Vector2(1.15f, 0.3f); } public void OnRecipeSelected() { MultiCraft_Logic.instance.ResetMultiCrafting(); } public void UpdateAmountLabel(int value) { if (Object.op_Implicit((Object)(object)amountText)) { ((TMP_Text)((Component)amountText).GetComponent<TextMeshProUGUI>()).text = $"{value}"; } } private void OnPlusButtonPressed() { int delta = 1; if (Input.GetKey((KeyCode)306)) { delta = 99; } else if (Input.GetKey((KeyCode)304)) { delta = 10; } MultiCraft_Logic.instance.AddToCraftAmount(delta); } private void OnMinusButtonPressed() { if (Input.GetKey((KeyCode)306)) { MultiCraft_Logic.instance.SetCraftAmount(1); return; } int delta = -1; if (Input.GetKey((KeyCode)304)) { delta = -10; } MultiCraft_Logic.instance.AddToCraftAmount(delta); } private void CreateSpaceFromCraftButton(InventoryGui instance) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown RectTransform transform = (RectTransform)((Component)instance.m_craftButton).transform.parent; AttachButtonsToLeft((Transform)(object)transform); } private void AttachButtonsToLeft(Transform transform) { //IL_0010: 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_0021: Expected O, but got Unknown //IL_0034: 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) transform.localScale = new Vector3(0.8f, 1f, 1f); RectTransform val = (RectTransform)transform; if (Object.op_Implicit((Object)(object)val)) { val.anchorMin = new Vector2(0f, 0f); val.pivot = new Vector2(0f, 0.5f); } } private void AttachButtonsToRight(Transform transform, float verticalAllignment) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)transform; if (Object.op_Implicit((Object)(object)val)) { val.pivot = new Vector2(1.3f, verticalAllignment); } } private RectTransform CreateMultiCraftButton(InventoryGui __instance, string name, string text) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) Debug.Log((object)("Start of CreateButton: " + name)); RectTransform val = (RectTransform)((Component)__instance).transform.parent.Find(name); if ((Object)(object)val == (Object)null) { Transform transform = ((Component)__instance.m_craftButton).transform; Transform obj = Object.Instantiate<Transform>(transform, ((Component)transform).transform.parent); ((Object)obj).name = name; ((Component)obj).transform.SetAsFirstSibling(); val = (RectTransform)((Component)obj).transform; val.SetSizeWithCurrentAnchors((Axis)0, 45f); val.SetSizeWithCurrentAnchors((Axis)1, 30f); RectTransform val2 = (RectTransform)((Component)val).transform.Find("Text"); val2.SetSizeWithCurrentAnchors((Axis)0, 45f); val2.SetSizeWithCurrentAnchors((Axis)1, 30f); ((TMP_Text)((Component)val2).gameObject.GetComponent<TextMeshProUGUI>()).text = text; } return val; } } public class RequirementInformation { public string name; public int RequiredAmount; public RequirementInformation(int reqAmount, string itemName) { RequiredAmount = reqAmount; name = itemName; } public int GetMaxByCurrentRequirement() { return Helper.GetAvailableItems(name) / RequiredAmount; } } public class CurrentRecipeInformation { private static CurrentRecipeInformation _instance; public static UnityEvent OnRecipeChanged = new UnityEvent(); private Dictionary<string, RequirementInformation> requirements; private string _name = ""; public static CurrentRecipeInformation instance { get { if (_instance == null) { _instance = new CurrentRecipeInformation(); } return _instance; } } public static bool Started { get; private set; } public bool IsRecipeReady { get; private set; } public string name { get { return _name; } set { if (!IsRecipe(value)) { _name = value; UnityEvent onRecipeChanged = OnRecipeChanged; if (onRecipeChanged != null) { onRecipeChanged.Invoke(); } ClearRequirements(); } } } private CurrentRecipeInformation() { requirements = new Dictionary<string, RequirementInformation>(); IsRecipeReady = false; } public void Start() { Started = true; } public bool IsRecipe(string otherName) { return name == otherName; } public void ClearRequirements() { IsRecipeReady = false; requirements.Clear(); } public void AddRequirement(string name, int requiredAmount) { if (requirements.ContainsKey(name)) { IsRecipeReady = true; return; } RequirementInformation value = new RequirementInformation(requiredAmount, name); requirements[name] = value; } public int GetCurrentMaxCraftable() { int num = 99; foreach (KeyValuePair<string, RequirementInformation> requirement in requirements) { num = Math.Min(num, requirement.Value.GetMaxByCurrentRequirement()); } return num; } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirement", new Type[] { typeof(Transform), typeof(Requirement), typeof(Player), typeof(bool), typeof(int) })] public static class SetupRequirement_Patch { private static void Postfix(Transform elementRoot, Requirement req, Player player, bool craft, int quality) { string name = req.m_resItem.m_itemData.m_shared.m_name; CurrentRecipeInformation.instance.name = InventoryGui.instance.m_recipeName.text; if (!CurrentRecipeInformation.instance.IsRecipeReady && req.m_amount != 0) { CurrentRecipeInformation.instance?.AddRequirement(name, req.GetAmount(quality)); } UpdateRequirementLabels(elementRoot, req, quality); } private static void UpdateRequirementLabels(Transform elementRoot, Requirement req, int quality) { TextMeshProUGUI component = ((Component)((Component)elementRoot).transform.Find("res_amount")).GetComponent<TextMeshProUGUI>(); int availableItems = Helper.GetAvailableItems(req.m_resItem.m_itemData.m_shared.m_name); int num = req.GetAmount(quality) * MultiCraft_Logic.instance.CurrentCraftAmount; ((TMP_Text)component).text = $"{num}/{availableItems}"; } }
Plugins/MultiUserChest/MultiUserChest.dll
Decompiled 2 years 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.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using MultiUserChest.Patches; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("MultiUserChest")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("MultiUserChest")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: InternalsVisibleTo("UnitTests")] [assembly: InternalsVisibleTo("Tests")] [assembly: ComVisible(false)] [assembly: Guid("FE8B42E3-7082-4DFF-A5CC-6B62B0315ACA")] [assembly: AssemblyFileVersion("0.5.10")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.5.10.0")] [module: UnverifiableCode] namespace MultiUserChest { public static class CodeMatcherExtensions { public static CodeMatcher GetPosition(this CodeMatcher codeMatcher, out int position) { position = codeMatcher.Pos; return codeMatcher; } public static CodeMatcher AddLabel(this CodeMatcher codeMatcher, out Label label) { label = default(Label); codeMatcher.AddLabels((IEnumerable<Label>)new Label[1] { label }); return codeMatcher; } public static CodeMatcher GetOperand(this CodeMatcher codeMatcher, out object operand) { operand = codeMatcher.Operand; return codeMatcher; } internal static CodeMatcher Print(this CodeMatcher codeMatcher, int before, int after) { for (int i = -before; i <= after; i++) { int num = i; int num2 = codeMatcher.Pos + num; if (num2 > 0) { if (num2 >= codeMatcher.Length) { break; } try { CodeInstruction val = codeMatcher.InstructionAt(num); Log.LogCodeInstruction($"[{num}] " + ((object)val).ToString()); } catch (Exception ex) { Log.LogCodeInstruction(ex.Message); } } } return codeMatcher; } public static bool IsVirtCall(this CodeInstruction i, string declaringType, string name) { if (i.opcode == OpCodes.Callvirt && i.operand is MethodInfo methodInfo && methodInfo.DeclaringType?.Name == declaringType) { return methodInfo.Name == name; } return false; } } public static class Compatibility { private static bool IsExtendedInventory(this Inventory inventory, out List<Inventory> inventories) { if (inventory.IsType("ExtendedInventory") && inventory.HasField("_inventories")) { inventories = inventory.GetField<List<Inventory>>("_inventories"); return true; } inventories = null; return false; } public static List<Inventory> GetInventories(this Inventory inventory) { if (inventory.IsExtendedInventory(out var inventories)) { return inventories; } return new List<Inventory> { inventory }; } } public class ContainerExtend : MonoBehaviour { private static readonly ConditionalWeakTable<Inventory, ContainerInventoryOwner> Containers = new ConditionalWeakTable<Inventory, ContainerInventoryOwner>(); private Inventory inventory; private void Awake() { Container container = default(Container); if (!((Component)this).TryGetComponent<Container>(ref container)) { return; } inventory = container.GetInventory(); if (inventory != null) { Containers.TryAdd(inventory, (Inventory i) => new ContainerInventoryOwner(container)); } } private void OnDestroy() { if (inventory != null) { Containers.Remove(inventory); } } public static bool GetContainer(Inventory inventory, out ContainerInventoryOwner container) { return Containers.TryGetValue(inventory, out container); } } public static class ContainerHandler { public static RequestChestAdd AddItemToChest(this Container container, ItemData item, Inventory sourceInventory, Vector2i to, ZDOID sender, int dragAmount = -1) { //IL_0022: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_00b1: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner()) { return new RequestChestAdd(Vector2i.zero, 0, null, null, null); } dragAmount = PossibleDragAmount(container.GetInventory(), item, to, dragAmount); ItemData itemAt = container.GetInventory().GetItemAt(to.x, to.y); bool flag = itemAt != null && dragAmount != item.m_stack && !InventoryHelper.CanStack(itemAt, item); if (dragAmount <= 0 || flag || !sourceInventory.ContainsItem(item)) { return new RequestChestAdd(Vector2i.zero, 0, null, null, null); } RequestChestAdd requestChestAdd = new RequestChestAdd(to, dragAmount, item, sourceInventory, container.GetInventory()); InventoryBlock.Get(sourceInventory).BlockSlot(item.m_gridPos); InventoryPreview.AddPackage(requestChestAdd); sourceInventory.RemoveItem(item, dragAmount); if (container.m_nview.IsOwner()) { RequestChestAddResponse response = container.GetInventory().RequestItemAdd(requestChestAdd); InventoryHandler.RPC_RequestItemAddResponse(sourceInventory, response); return null; } GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemAdd", requestChestAdd); return requestChestAdd; } internal static int PossibleDragAmount(Inventory inventoryTo, ItemData dragItem, Vector2i to, int dragAmount) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) dragAmount = ((dragAmount >= 0) ? Mathf.Min(dragAmount, dragItem.m_stack) : dragItem.m_stack); if (to.x >= 0 && to.y >= 0) { ItemData itemAt = inventoryTo.GetItemAt(to.x, to.y); if (itemAt != null && dragAmount < dragItem.m_stack) { if (InventoryHelper.CanStack(itemAt, dragItem)) { return Mathf.Min(dragAmount, itemAt.m_shared.m_maxStackSize - itemAt.m_stack); } return 0; } } else if (!inventoryTo.HaveEmptySlot()) { int num = inventoryTo.FindFreeStackSpace(dragItem.m_shared.m_name, (float)dragItem.m_worldLevel); return Mathf.Min(dragAmount, num); } return dragAmount; } public static RequestChestRemove RemoveItemFromChest(this Container container, ItemData item, Inventory destinationInventory, Vector2i to, ZDOID sender, int dragAmount = -1, ItemData switchItem = null) { //IL_0022: 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) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner()) { return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory); } dragAmount = PossibleDragAmount(destinationInventory, item, to, dragAmount); if (dragAmount <= 0 || InventoryBlock.Get(destinationInventory).IsSlotBlocked(to)) { return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory); } RequestChestRemove requestChestRemove = new RequestChestRemove(item.m_gridPos, to, dragAmount, switchItem, container.GetInventory(), destinationInventory); if (switchItem != null && !InventoryHelper.CanStack(item, switchItem)) { if (dragAmount != item.m_stack) { return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory); } destinationInventory.RemoveItem(switchItem); } InventoryBlock.Get(destinationInventory).BlockSlot(requestChestRemove.toPos); InventoryPreview.AddPackage(requestChestRemove); if (container.m_nview.IsOwner()) { RequestChestRemoveResponse response = container.GetInventory().RequestItemRemove(requestChestRemove); InventoryHandler.RPC_RequestItemRemoveResponse(destinationInventory, response); return null; } GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemRemove", requestChestRemove); return requestChestRemove; } public static void MoveItemInChest(this Container container, ItemData item, Vector2i toPos, int dragAmount) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) RequestMove package = new RequestMove(item, toPos, dragAmount, container.GetInventory()); InventoryPreview.AddPackage(package); GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemMove", package); } } public static class ContainerRPCHandler { public static void RPC_RequestItemAdd(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "MUC_RequestItemAddResponse", RequestItemAdd, new RequestChestAdd(package)); } public static void RPC_RequestItemRemove(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "MUC_RequestItemRemoveResponse", RequestItemRemove, new RequestChestRemove(package)); } public static void RPC_RequestItemConsume(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "MUC_RequestItemConsumeResponse", RequestItemConsume, new RequestConsume(package)); } public static void RPC_RequestItemMove(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "MUC_RequestItemMoveResponse", RequestItemMove, new RequestMove(package)); } public static void RPC_RequestDrop(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "MUC_RequestItemDropResponse", RequestDrop, new RequestDrop(package)); } private static void HandleRPC<TResponse, TInput>(ZDOID containerId, long target, string rpcInvoke, Func<Inventory, TInput, TResponse> message, TInput input) where TResponse : IResponse, new() where TInput : IPackage { //IL_0005: 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) ZDO zDO = ZDOMan.instance.GetZDO(containerId); ZNetView val = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null); TResponse val2; if (!Object.op_Implicit((Object)(object)val) || !val.IsOwner()) { val2 = FallbackResponse<TResponse>(input as IRequest); } else { Container componentInChildren = ((Component)val).GetComponentInChildren<Container>(); if (Object.op_Implicit((Object)(object)componentInChildren)) { val2 = message(componentInChildren.GetInventory(), input); } else { Log.LogWarning(input.GetType().Name + ": not handling RPC, Container component not found on " + ((Object)val).name); val2 = FallbackResponse<TResponse>(input as IRequest); } } ZRoutedRpc.instance.InvokeRoutedRPC(target, rpcInvoke, new object[2] { containerId, val2.WriteToPackage() }); } private static TResponse FallbackResponse<TResponse>(IRequest request) where TResponse : IResponse, new() { //IL_0058: 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_005d: Unknown result type (might be due to invalid IL or missing references) TResponse val = new TResponse { SourceID = (request?.RequestID ?? 0) }; if (request is RequestChestAdd requestChestAdd && (object)val is RequestChestAddResponse requestChestAddResponse) { requestChestAddResponse.switchItem = requestChestAdd.dragItem; requestChestAddResponse.inventoryPos = requestChestAdd.dragItem?.m_gridPos ?? Vector2i.zero; } else if (request is RequestChestRemove requestChestRemove && (object)val is RequestChestRemoveResponse requestChestRemoveResponse) { requestChestRemoveResponse.responseItem = requestChestRemove.switchItem; } return val; } public static RequestChestAddResponse RequestItemAdd(this Inventory inventory, RequestChestAdd request) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (request.dragItem == null) { return new RequestChestAddResponse(request.RequestID, success: false, Vector2i.zero, 0, request.dragItem); } if (request.toPos.x < 0 || request.toPos.y < 0) { return AddToAnySlot(inventory, request); } return AddToSlot(inventory, request); } private static RequestChestAddResponse AddToSlot(Inventory inventory, RequestChestAdd request) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (!CanStack(inventory, request, out var stackSpace, out var removedItem)) { return new RequestChestAddResponse(request.RequestID, success: false, request.dragItem.m_gridPos, 0, request.dragItem); } bool flag = inventory.AddItemToInventory(request.dragItem, stackSpace, request.toPos); if (!flag) { stackSpace = 0; } if (!flag || stackSpace != request.dragItem.m_stack) { removedItem = request.dragItem; removedItem.m_stack = request.dragItem.m_stack - stackSpace; } if (removedItem != null) { removedItem.m_gridPos = request.dragItem.m_gridPos; } return new RequestChestAddResponse(request.RequestID, flag, request.dragItem.m_gridPos, stackSpace, removedItem); } private static bool CanStack(Inventory inventory, RequestChestAdd request, out int stackSpace, out ItemData removedItem) { ItemData itemAt = inventory.GetItemAt(request.toPos.x, request.toPos.y); removedItem = null; if (itemAt == null) { stackSpace = request.dragItem.m_stack; return true; } if (InventoryHelper.CanStack(itemAt, request.dragItem)) { stackSpace = Mathf.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, request.dragItem.m_stack); return true; } if (request.allowSwitch) { inventory.RemoveItem(itemAt, itemAt.m_stack); removedItem = itemAt; stackSpace = request.dragItem.m_stack; return true; } stackSpace = 0; return false; } private static RequestChestAddResponse AddToAnySlot(Inventory inventory, RequestChestAdd request) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) Inventory val = new Inventory("tmp", (Sprite)null, 1, 1); val.AddItem(request.dragItem.Clone(), request.dragItem.m_stack, 0, 0); inventory.MoveItemToThis(val, val.GetItemAt(0, 0)); ItemData itemAt = val.GetItemAt(0, 0); if (itemAt == null) { return new RequestChestAddResponse(request.RequestID, success: true, request.dragItem.m_gridPos, request.dragItem.m_stack, null); } ItemData val2 = request.dragItem.Clone(); int num = request.dragItem.m_stack - itemAt.m_stack; val2.m_stack -= num; bool success = itemAt.m_stack != request.dragItem.m_stack; return new RequestChestAddResponse(request.RequestID, success, request.dragItem.m_gridPos, num, val2); } public static RequestChestRemoveResponse RequestItemRemove(this Inventory inventory, RequestChestRemove request) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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) Vector2i fromPos = request.fromPos; int dragAmount = request.dragAmount; ItemData switchItem = request.switchItem; ItemData itemAt = inventory.GetItemAt(request.fromPos.x, request.fromPos.y); if (itemAt == null) { Log.LogDebug("from is null"); return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } int num = 0; bool flag = false; bool flag2 = false; if (switchItem == null) { num = Mathf.Min(itemAt.m_stack, dragAmount); flag = inventory.RemoveItem(itemAt, num); } else if (InventoryHelper.CanStack(itemAt, switchItem)) { num = Mathf.Min(switchItem.m_shared.m_maxStackSize - switchItem.m_stack, dragAmount); flag = inventory.RemoveItem(itemAt, num); } else { if (dragAmount < itemAt.m_stack) { return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, request.switchItem); } flag = inventory.RemoveItem(itemAt, dragAmount); num = Mathf.Min(itemAt.m_stack, dragAmount); flag2 = inventory.AddItemToInventory(switchItem, switchItem.m_stack, fromPos); if (!flag2) { Log.LogWarning("Could not switch item in Remove Request"); InventoryHandler.DropItem(switchItem, switchItem.m_stack); } } ItemData val = itemAt.Clone(); val.m_stack = num; return new RequestChestRemoveResponse(request.RequestID, flag, num, flag2, val); } public static RequestConsumeResponse RequestItemConsume(this Inventory inventory, RequestConsume request) { ItemData itemAt = inventory.GetItemAt(request.itemPosX, request.itemPosY); if (itemAt == null || itemAt.m_stack <= 0) { return new RequestConsumeResponse(null, success: false, 0); } inventory.RemoveOneItem(itemAt); ItemData val = itemAt.Clone(); val.m_stack = 1; return new RequestConsumeResponse(val, success: true, 1); } public static RequestMoveResponse RequestItemMove(this Inventory inventory, RequestMove request) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_001c: 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) Vector2i fromPos = request.fromPos; Vector2i toPos = request.toPos; int dragAmount = request.dragAmount; ItemData itemAt = inventory.GetItemAt(fromPos.x, fromPos.y); if (itemAt == null) { return new RequestMoveResponse(request.RequestID, success: false, 0); } if (StringExtensionMethods.GetStableHashCode(itemAt.PrefabName()) != request.itemHash) { return new RequestMoveResponse(request.RequestID, success: false, 0); } int movedAmount; bool success = InventoryHelper.MoveItem(inventory, itemAt, dragAmount, toPos, out movedAmount); return new RequestMoveResponse(request.RequestID, success, movedAmount); } public static RequestDropResponse RequestDrop(this Inventory inventory, RequestDrop request) { //IL_0022: 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_004f: Unknown result type (might be due to invalid IL or missing references) ItemData itemAt = inventory.GetItemAt(request.targetContainerSlot.x, request.targetContainerSlot.y); if (itemAt == null) { return new RequestDropResponse(null, request.sender, success: false, 0); } int num = Mathf.Min(itemAt.m_stack, request.amount); inventory.RemoveItem(itemAt, num); if (num == 0) { return new RequestDropResponse(null, request.sender, success: false, 0); } ItemData val = itemAt.Clone(); val.m_stack = num; return new RequestDropResponse(val, request.sender, success: true, num); } } public interface IPackage { ZPackage WriteToPackage(); } public interface IRequest : IPackage { int RequestID { get; set; } Inventory SourceInventory { get; } Inventory TargetInventory { get; } } public interface IResponse : IPackage { int SourceID { get; set; } bool Success { get; set; } int Amount { get; set; } } public class RequestChestAdd : IRequest, IPackage { public readonly Vector2i toPos; public readonly ItemData dragItem; public readonly bool allowSwitch; public int RequestID { get; set; } public Inventory SourceInventory { get; } public Inventory TargetInventory { get; } public RequestChestAdd(Vector2i toPos, int dragAmount, ItemData dragItem, Inventory sourceInventory, Inventory targetInventory) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) this.toPos = toPos; if (dragItem != null) { this.dragItem = dragItem.Clone(); this.dragItem.m_stack = Mathf.Min(dragAmount, this.dragItem.m_stack); allowSwitch = dragAmount == dragItem.m_stack; } SourceInventory = sourceInventory; TargetInventory = targetInventory; } public RequestChestAdd(ZPackage package) { //IL_0014: 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) RequestID = package.ReadInt(); toPos = package.ReadVector2i(); dragItem = InventoryHelper.LoadItemFromPackage(package); allowSwitch = package.ReadBool(); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(RequestID); val.Write(toPos); InventoryHelper.WriteItemToPackage(dragItem, val); val.Write(allowSwitch); return val; } } public class RequestChestAddResponse : IPackage, IResponse { public Vector2i inventoryPos; public ItemData switchItem; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestChestAddResponse(int sourceID, bool success, Vector2i inventoryPos, int amount, ItemData switchItem) { //IL_001d: 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) SourceID = sourceID; Success = success; Amount = amount; this.inventoryPos = inventoryPos; this.switchItem = switchItem.ClampStackSize(); } public RequestChestAddResponse(ZPackage package) { //IL_0014: 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) SourceID = package.ReadInt(); inventoryPos = package.ReadVector2i(); Success = package.ReadBool(); Amount = package.ReadInt(); switchItem = InventoryHelper.LoadItemFromPackage(package); } public RequestChestAddResponse() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) SourceID = 0; Success = false; inventoryPos = new Vector2i(-1, -1); Amount = 0; switchItem = null; } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(SourceID); val.Write(inventoryPos); val.Write(Success); val.Write(Amount); InventoryHelper.WriteItemToPackage(switchItem, val); return val; } } public class RequestConsume : IPackage { public readonly int itemPosX; public readonly int itemPosY; public RequestConsume(ItemData item) { itemPosX = item.m_gridPos.x; itemPosY = item.m_gridPos.y; } public RequestConsume(ZPackage package) { itemPosX = package.ReadInt(); itemPosY = package.ReadInt(); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(itemPosX); val.Write(itemPosY); return val; } } public class RequestConsumeResponse : IPackage, IResponse { public readonly ItemData item; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestConsumeResponse(ZPackage package) { item = InventoryHelper.LoadItemFromPackage(package); Success = package.ReadBool(); Amount = package.ReadInt(); } public RequestConsumeResponse(ItemData item, bool success, int amount) { this.item = item.ClampStackSize(); Success = success; Amount = amount; } public RequestConsumeResponse() { item = null; } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); InventoryHelper.WriteItemToPackage(item, val); val.Write(Success); val.Write(Amount); return val; } } public class RequestDrop : IPackage { public readonly Vector2i targetContainerSlot; public readonly int amount; public readonly ZDOID sender; public RequestDrop(Vector2i targetContainerSlot, int amount, ZDOID sender) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_0016: Unknown result type (might be due to invalid IL or missing references) this.targetContainerSlot = targetContainerSlot; this.amount = amount; this.sender = sender; } public RequestDrop(ZPackage package) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) targetContainerSlot = package.ReadVector2i(); amount = package.ReadInt(); sender = package.ReadZDOID(); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(targetContainerSlot); val.Write(amount); val.Write(sender); return val; } } public class RequestDropResponse : IPackage, IResponse { public readonly ItemData responseItem; public readonly ZDOID sender; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestDropResponse(ItemData responseItem, ZDOID sender, bool success, int amount) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) this.responseItem = responseItem.ClampStackSize(); this.sender = sender; Success = success; Amount = amount; } public RequestDropResponse(ZPackage package) { //IL_0014: 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) responseItem = InventoryHelper.LoadItemFromPackage(package); sender = package.ReadZDOID(); Success = package.ReadBool(); Amount = package.ReadInt(); } public RequestDropResponse() { responseItem = null; } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); InventoryHelper.WriteItemToPackage(responseItem, val); val.Write(sender); val.Write(Success); val.Write(Amount); return val; } } public class RequestMove : IRequest, IPackage { public readonly Vector2i fromPos; public readonly Vector2i toPos; public readonly int itemHash; public readonly int dragAmount; public readonly ItemData item; public int RequestID { get; set; } public Inventory SourceInventory { get; } public Inventory TargetInventory { get; } public RequestMove(ItemData itemToMove, Vector2i toPos, int dragAmount, Inventory inventory) { //IL_004e: 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) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (itemToMove == null) { Log.LogWarning("Item is null"); fromPos = new Vector2i(-1, -1); this.toPos = new Vector2i(-1, -1); itemHash = 0; this.dragAmount = 0; } else { SourceInventory = inventory; TargetInventory = inventory; fromPos = itemToMove.m_gridPos; this.toPos = toPos; itemHash = StringExtensionMethods.GetStableHashCode(itemToMove.PrefabName()); item = itemToMove.Clone(); this.dragAmount = dragAmount; } } public RequestMove(ZPackage package) { //IL_0014: 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) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) RequestID = package.ReadInt(); fromPos = package.ReadVector2i(); toPos = package.ReadVector2i(); itemHash = package.ReadInt(); dragAmount = package.ReadInt(); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(RequestID); val.Write(fromPos); val.Write(toPos); val.Write(itemHash); val.Write(dragAmount); return val; } } public class RequestChestRemove : IRequest, IPackage { public readonly Vector2i fromPos; public readonly Vector2i toPos; public readonly int dragAmount; public readonly ItemData switchItem; public readonly ItemData item; public int RequestID { get; set; } public Inventory SourceInventory { get; } public Inventory TargetInventory { get; } public RequestChestRemove(Vector2i fromPos, Vector2i toPos, int dragAmount, ItemData switchItem, Inventory sourceInventory, Inventory targetInventory) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_004f: Unknown result type (might be due to invalid IL or missing references) this.fromPos = fromPos; this.toPos = toPos; this.dragAmount = dragAmount; this.switchItem = ((switchItem != null) ? switchItem.Clone() : null); SourceInventory = sourceInventory; TargetInventory = targetInventory; object obj; if (sourceInventory == null) { obj = null; } else { ItemData itemAt = sourceInventory.GetItemAt(fromPos.x, fromPos.y); obj = ((itemAt != null) ? itemAt.Clone() : null); } item = (ItemData)obj; } public RequestChestRemove(ZPackage package) { //IL_0014: 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) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) RequestID = package.ReadInt(); fromPos = package.ReadVector2i(); toPos = package.ReadVector2i(); dragAmount = package.ReadInt(); switchItem = InventoryHelper.LoadItemFromPackage(package); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(RequestID); val.Write(fromPos); val.Write(toPos); val.Write(dragAmount); InventoryHelper.WriteItemToPackage(switchItem, val); return val; } } public class RequestChestRemoveResponse : IPackage, IResponse { public ItemData responseItem; public bool hasSwitched; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestChestRemoveResponse(int sourceID, bool success, int amount, bool hasSwitched, ItemData responseItem) { SourceID = sourceID; Success = success; Amount = amount; this.hasSwitched = hasSwitched; this.responseItem = responseItem.ClampStackSize(); } public RequestChestRemoveResponse(ZPackage package) { SourceID = package.ReadInt(); Success = package.ReadBool(); Amount = package.ReadInt(); hasSwitched = package.ReadBool(); responseItem = InventoryHelper.LoadItemFromPackage(package); } public RequestChestRemoveResponse() { Success = false; Amount = 0; hasSwitched = false; responseItem = null; } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(SourceID); val.Write(Success); val.Write(Amount); val.Write(hasSwitched); InventoryHelper.WriteItemToPackage(responseItem, val); return val; } } public class RequestMoveResponse : IPackage, IResponse { public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestMoveResponse(int sourceID, bool success, int amount) { SourceID = sourceID; Success = success; Amount = amount; } public RequestMoveResponse() { SourceID = 0; Success = false; Amount = 0; } public RequestMoveResponse(ZPackage package) { SourceID = package.ReadInt(); Success = package.ReadBool(); Amount = package.ReadInt(); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(SourceID); val.Write(Success); val.Write(Amount); return val; } } public class SlotPreview { private Inventory originalInventory; private Inventory inventory; private bool hasChanges; public SlotPreview(Inventory inventory) { originalInventory = inventory; this.inventory = InventoryHelper.CopyInventory(inventory); } public void Add(Vector2i pos, ItemData item, int amount) { //IL_0015: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (item != null && amount != 0) { ItemData val = item.Clone(); val.m_stack = amount; if (pos.x >= 0 && pos.y >= 0) { inventory.AddItem(val, amount, pos.x, pos.y); } else { inventory.AddItem(val); } hasChanges = true; } } public void Add(Vector2i pos, ItemData item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Add(pos, item, item?.m_stack ?? 0); } public void Remove(Vector2i pos, ItemData item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Remove(pos, item, item?.m_stack ?? 0); } public void Remove(Vector2i pos, ItemData item, int amount) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0035: Unknown result type (might be due to invalid IL or missing references) if (item != null && amount != 0) { ItemData itemAt = inventory.GetItemAt(pos.x, pos.y); if (itemAt != null) { inventory.RemoveItem(inventory.GetItemAt(pos.x, pos.y), amount); hasChanges = true; } } } public bool GetSlot(Vector2i pos, out ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) ItemData itemAt = originalInventory.GetItemAt(pos.x, pos.y); item = inventory.GetItemAt(pos.x, pos.y); if (itemAt == null && item == null) { return false; } if (itemAt == null || item == null) { return true; } if (!(itemAt.m_shared.m_name != item.m_shared.m_name)) { return itemAt.m_stack != item.m_stack; } return true; } public bool HasChanges() { return hasChanges; } } public static class ConditionalWeakTableExtension { public static void TryAdd<TKey, TValue>(this ConditionalWeakTable<TKey, TValue> table, TKey key, ConditionalWeakTable<TKey, TValue>.CreateValueCallback createCallback) where TKey : class where TValue : class { table.GetValue(key, createCallback); } } public static class InventoryHelper { public delegate void MoveAction(Inventory from, Inventory to); private static MethodBase memberwiseCloneMethod = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null); public static ItemData LoadItemFromPackage(ZPackage pkg) { //IL_0022: 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) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00b3: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) if (!pkg.ReadBool()) { return null; } string text = pkg.ReadString(); int num = pkg.ReadInt(); float num2 = pkg.ReadSingle(); Vector2i val = pkg.ReadVector2i(); int num3 = pkg.ReadInt(); int num4 = pkg.ReadInt(); long num5 = pkg.ReadLong(); string text2 = pkg.ReadString(); int num6 = pkg.ReadInt(); bool flag = pkg.ReadBool(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); int num7 = pkg.ReadInt(); for (int i = 0; i < num7; i++) { string key = pkg.ReadString(); string value = pkg.ReadString(); dictionary[key] = value; } Inventory val2 = new Inventory("tmp", (Sprite)null, val.x + 1, val.y + 1); val2.AddItem(text, num, num2, val, false, num3, num4, num5, text2, dictionary, num6, flag); ItemData itemAt = val2.GetItemAt(val.x, val.y); val2.RemoveItem(itemAt); return itemAt; } public static void WriteItemToPackage(ItemData itemData, ZPackage pkg) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) pkg.Write(itemData != null); if (itemData == null) { return; } pkg.Write(itemData.PrefabName()); pkg.Write(itemData.m_stack); pkg.Write(itemData.m_durability); pkg.Write(itemData.m_gridPos); pkg.Write(itemData.m_quality); pkg.Write(itemData.m_variant); pkg.Write(itemData.m_crafterID); pkg.Write(itemData.m_crafterName); pkg.Write(itemData.m_worldLevel); pkg.Write(itemData.m_pickedUp); pkg.Write(itemData.m_customData.Count); foreach (KeyValuePair<string, string> customDatum in itemData.m_customData) { pkg.Write(customDatum.Key); pkg.Write(customDatum.Value); } } public static ItemData ClampStackSize(this ItemData item) { if (item == null) { return null; } ItemDrop prefab = Cache.GetPrefab<ItemDrop>(item.PrefabName()); item.m_shared.m_maxStackSize = prefab.m_itemData.m_shared.m_maxStackSize; return item; } public static string PrefabName(this ItemData item) { if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name; } Log.LogWarning("Item missing prefab " + item.m_shared.m_name); return item.m_shared.m_name; } public static bool MoveItem(Inventory inventory, ItemData item, int amount, Vector2i toPos, out int movedAmount) { //IL_000a: 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_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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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) movedAmount = 0; if (item == null) { return false; } ItemData itemAt = inventory.GetItemAt(toPos.x, toPos.y); if (itemAt == item) { return true; } if (itemAt == null) { movedAmount = amount; return inventory.MoveItemToThis(inventory, item, amount, toPos.x, toPos.y); } if (CanStack(itemAt, item)) { movedAmount = Mathf.Min(amount, itemAt.m_shared.m_maxStackSize - itemAt.m_stack); return inventory.MoveItemToThis(inventory, item, movedAmount, toPos.x, toPos.y); } if (item.m_stack != amount) { return false; } inventory.RemoveItem(item); inventory.MoveItemToThis(inventory, itemAt, itemAt.m_stack, item.m_gridPos.x, item.m_gridPos.y); inventory.MoveItemToThis(inventory, item, amount, toPos.x, toPos.y); movedAmount = amount; return true; } public static bool CanStack(ItemData itemA, ItemData itemB) { if (itemA.m_shared.m_name == itemB.m_shared.m_name && (itemA.m_shared.m_maxQuality <= 1 || itemB.m_quality == itemA.m_quality)) { return itemA.m_shared.m_maxStackSize != 1; } return false; } public static Vector2i FindEmptySlot(Inventory inventory, List<Vector2i> blockedSlots) { //IL_0045: 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_0023: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < inventory.m_height; i++) { for (int j = 0; j < inventory.m_width; j++) { if (inventory.GetItemAt(j, i) == null && !blockedSlots.Contains(new Vector2i(j, i))) { return new Vector2i(j, i); } } } return new Vector2i(-1, -1); } public static List<ItemData> GetAllMoveableItems(Inventory from, Inventory to, MoveAction moveAction) { Inventory val = CopyInventory(from); Inventory to2 = CopyInventory(to); moveAction(val, to2); return CountMoved(from, val); } public static List<ItemData> GetAllMoveableItems(Inventory from, Inventory to) { return GetAllMoveableItems(from, to, MoveAll); } public static void MoveAll(Inventory from, Inventory to) { to.MoveAll(from); } private static List<ItemData> CountMoved(Inventory from, Inventory fromCopy) { List<ItemData> list = new List<ItemData>(); foreach (ItemData item in from.m_inventory) { ItemData itemAt = fromCopy.GetItemAt(item.m_gridPos.x, item.m_gridPos.y); if (itemAt == null) { list.Add(item); } else if (item.m_stack > itemAt.m_stack) { ItemData val = item.Clone(); val.m_stack = item.m_stack - itemAt.m_stack; list.Add(val); } } return list; } public static Inventory CopyInventory(Inventory target) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown return new Inventory(target.m_name, target.m_bkg, target.m_width, target.m_height) { m_inventory = new List<ItemData>(from x in target.GetAllItems() select x.Clone()) }; } public static bool AddItemToInventory(this Inventory target, ItemData item, int amount, Vector2i pos) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (amount == 0) { return false; } ItemData itemAt = target.GetItemAt(pos.x, pos.y); if (itemAt != null) { if (!CanStack(itemAt, item)) { return false; } if (itemAt.m_stack + amount > itemAt.m_shared.m_maxStackSize) { return false; } } ItemData val = item.CloneDeeper(); val.m_stack = amount; return target.AddItem(val, amount, pos.x, pos.y); } public static ItemData CloneDeeper(this ItemData itemDrop) { ItemData val = itemDrop.Clone(); ref SharedData shared = ref val.m_shared; object? obj = memberwiseCloneMethod.Invoke(itemDrop.m_shared, null); shared = (SharedData)((obj is SharedData) ? obj : null); return val; } public static void PrintItem(string title, ItemData itemData) { } } public static class Log { private static ManualLogSource logSource; internal static void Init(ManualLogSource manualLogSource) { logSource = manualLogSource; } public static void LogCodeInstruction(object data) { } public static void LogDebug(string data) { } public static void LogError(string data) { if (logSource != null) { logSource.LogError((object)data); } else { Debug.LogError((object)data); } } public static void LogFatal(string data) { if (logSource != null) { logSource.LogFatal((object)data); } else { Debug.LogError((object)data); } } public static void LogInfo(string data) { if (logSource != null) { logSource.LogInfo((object)data); } else { Debug.Log((object)data); } } public static void LogWarning(string data) { if (logSource != null) { logSource.LogWarning((object)data); } else { Debug.LogWarning((object)data); } } } public static class ReflectionHelper { private const BindingFlags allFlags = (BindingFlags)(-1); public static bool IsType(this object target, string name) { return target.GetType().Name == name; } public static bool HasField(this object target, string name) { return target.GetType().GetField(name, (BindingFlags)(-1)) != null; } public static T GetField<T>(this object target, string name) { return (T)(target.GetType().GetField(name, (BindingFlags)(-1))?.GetValue(target)); } public static T InvokeMethod<T>(this object target, string name, params object[] parameter) { parameter = ((parameter.Length == 0) ? null : parameter); return (T)(target.GetType().GetMethod(name, (BindingFlags)(-1))?.Invoke(target, parameter)); } public static T InvokeStaticMethod<T>(string type, string name, params object[] parameter) { parameter = ((parameter.Length == 0) ? null : parameter); return (T)(Type.GetType(type)?.GetMethod(name, (BindingFlags)(-1))?.Invoke(null, parameter)); } } public class HumanoidExtend : MonoBehaviour { private static readonly ConditionalWeakTable<Inventory, HumanoidInventoryOwner> Humanoids = new ConditionalWeakTable<Inventory, HumanoidInventoryOwner>(); private Inventory inventory; private void Awake() { UpdateInventory(); } private void Start() { UpdateInventory(); } private void UpdateInventory() { Humanoid humanoid = default(Humanoid); if (!((Component)this).TryGetComponent<Humanoid>(ref humanoid)) { return; } inventory = humanoid.GetInventory(); if (inventory == null) { return; } foreach (Inventory inventory in inventory.GetInventories()) { Humanoids.TryAdd(inventory, (Inventory i) => new HumanoidInventoryOwner(humanoid, i)); } } private void OnDestroy() { if (inventory == null) { return; } foreach (Inventory inventory in inventory.GetInventories()) { Humanoids.Remove(inventory); } } public static bool GetHumanoid(Inventory inventory, out HumanoidInventoryOwner humanoid) { return Humanoids.TryGetValue(inventory, out humanoid); } } public class InventoryBlock { private static readonly Dictionary<Inventory, InventoryBlock> Inventories = new Dictionary<Inventory, InventoryBlock>(); public bool BlockAllSlots { get; set; } public bool BlockConsume { get; set; } public Dictionary<Vector2i, int> BlockedSlots { get; } = new Dictionary<Vector2i, int>(); public static InventoryBlock Get(Inventory inventory) { if (Inventories.TryGetValue(inventory, out var value)) { return value; } InventoryBlock inventoryBlock = new InventoryBlock(); Inventories.Add(inventory, inventoryBlock); return inventoryBlock; } public void BlockSlot(Vector2i slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0020: 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) if (CanBlockSlot(slot)) { if (BlockedSlots.ContainsKey(slot)) { BlockedSlots[slot]++; } else { BlockedSlots[slot] = 1; } } } public void ReleaseSlot(Vector2i slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (CanBlockSlot(slot) && BlockedSlots.ContainsKey(slot)) { BlockedSlots[slot]--; if (BlockedSlots[slot] <= 0) { BlockedSlots.Remove(slot); } } } public void ReleaseBlockedSlots() { BlockedSlots.Clear(); BlockAllSlots = false; BlockConsume = false; } public bool IsSlotBlocked(Vector2i slot) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!BlockConsume && !BlockAllSlots) { return BlockedSlots.ContainsKey(slot); } return true; } public bool IsAnySlotBlocked() { if (!BlockConsume && !BlockAllSlots) { return BlockedSlots.Count > 0; } return true; } private static bool CanBlockSlot(Vector2i slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (slot.x >= 0) { return slot.y >= 0; } return false; } } public static class InventoryHandler { public static void RPC_RequestItemAddResponse(long sender, ZDOID containerId, ZPackage package) { HandleRPC(new RequestChestAddResponse(package), (RequestChestAddResponse p) => GetSourceInventory(p.SourceID), RPC_RequestItemAddResponse); } public static void RPC_RequestItemRemoveResponse(long sender, ZDOID containerId, ZPackage package) { HandleRPC(new RequestChestRemoveResponse(package), (RequestChestRemoveResponse p) => GetTargetInventory(p.SourceID), RPC_RequestItemRemoveResponse); } public static void RPC_RequestDropResponse(long sender, ZDOID containerId, ZPackage package) { HandleRPC(new RequestDropResponse(package), RPC_RequestDropResponse); } public static void RPC_RequestItemConsumeResponse(long sender, ZDOID containerId, ZPackage package) { HandleRPC(new RequestConsumeResponse(package), RPC_RequestItemConsumeResponse); } public static void RPC_RequestItemMoveResponse(long sender, ZDOID containerId, ZPackage package) { HandleRPC(new RequestMoveResponse(package), RPC_RequestItemMoveResponse); } private static void HandleRPC<T>(T package, Func<T, Inventory> inventory, Container container, Action<Inventory, Container, T> handle) where T : IPackage { CallRPC(handle.Method.Name, package, delegate { handle(inventory(package), container, package); }); } private static void HandleRPC<T>(T package, Func<T, Inventory> inventory, Action<Inventory, T> handle) where T : IPackage { CallRPC(handle.Method.Name, package, delegate { handle(inventory(package), package); }); } private static void HandleRPC<T>(T package, Action<T> handle) where T : IPackage { CallRPC(handle.Method.Name, package, delegate { handle(package); }); } private static void CallRPC(string timerName, IPackage package, Action action) { action?.Invoke(); } public static void RPC_RequestItemRemoveResponse(Inventory inventory, RequestChestRemoveResponse response) { //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_0017: 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) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_003a: 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) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) Vector2i toPos = PackageHandler.GetPackage<RequestChestRemove>(response.SourceID).toPos; InventoryBlock.Get(inventory).ReleaseSlot(toPos); InventoryPreview.RemovePackage(response); if (response.Success && toPos.x >= 0 && toPos.y >= 0) { if (!inventory.AddItemToInventory(response.responseItem, response.Amount, toPos)) { int num = response.Amount; ItemData itemAt = inventory.GetItemAt(toPos.x, toPos.y); if (itemAt != null && InventoryHelper.CanStack(response.responseItem, itemAt)) { int maxStackSize = itemAt.m_shared.m_maxStackSize; int stack = itemAt.m_stack; int num2 = maxStackSize - stack; itemAt.m_stack += num2; num -= num2; } DropItem(response.responseItem, num); } } else if (response.responseItem != null) { Inventory val = new Inventory("tmp", (Sprite)null, 1, 1); val.AddItem(response.responseItem); inventory.MoveItemToThis(val, response.responseItem); ItemData itemAt2 = val.GetItemAt(0, 0); if (itemAt2 != null) { DropItem(itemAt2, itemAt2.m_stack); } } UpdateGUIAfterPlayerMove(GetTargetInventory(response.SourceID)); } private static void RPC_RequestDropResponse(RequestDropResponse response) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) DropItem(response.responseItem, response.responseItem?.m_stack ?? 0); UpdateGUIAfterPlayerMove(response.sender); } private static void UpdateGUIAfterPlayerMove(ZDOID sender) { //IL_0018: 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) if (Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && sender == ((Character)Player.m_localPlayer).GetZDOID()) { InventoryGui.instance.UpdateCraftingPanel(false); } } private static void UpdateGUIAfterPlayerMove(Inventory inventory) { if (Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Humanoid)Player.m_localPlayer).GetInventory().GetInventories().Contains(inventory)) { InventoryGui.instance.UpdateCraftingPanel(false); } } public static void DropItem(ItemData item, int amount) { if (amount > 0 && item != null) { DropItem(Player.m_localPlayer, item, amount); } } private static void DropItem(Player player, ItemData item, int amount) { //IL_000a: 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_0015: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) Transform transform = ((Component)player).transform; ItemDrop val = ItemDrop.DropItem(item, amount, transform.position + transform.forward + transform.up, transform.rotation); val.OnPlayerDrop(); ((Component)val).GetComponent<Rigidbody>().velocity = (transform.forward + Vector3.up) * 5f; ((Character)player).m_zanim.SetTrigger("interact"); ((Humanoid)player).m_dropEffects.Create(transform.position, Quaternion.identity, (Transform)null, 1f, -1); ItemData itemData = val.m_itemData; ((Character)player).Message((MessageType)1, "$msg_dropped " + itemData.m_shared.m_name, itemData.m_stack, itemData.GetIcon()); } public static void RPC_RequestItemAddResponse(Inventory inventory, RequestChestAddResponse response) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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) Vector2i inventoryPos = response.inventoryPos; ItemData switchItem = response.switchItem; InventoryBlock.Get(inventory).ReleaseSlot(inventoryPos); InventoryPreview.RemovePackage(response); if (switchItem != null && !inventory.AddItemToInventory(switchItem, switchItem.m_stack, inventoryPos)) { DropItem(switchItem, switchItem.m_stack); } UpdateGUIAfterPlayerMove(GetSourceInventory(response.SourceID)); } public static void RPC_RequestItemConsumeResponse(RequestConsumeResponse response) { Player localPlayer = Player.m_localPlayer; InventoryBlock.Get(((Humanoid)localPlayer).GetInventory()).BlockConsume = false; if (response.item != null && ((Humanoid)localPlayer).CanConsumeItem(response.item, false)) { if (Object.op_Implicit((Object)(object)response.item.m_shared.m_consumeStatusEffect)) { ((Character)localPlayer).m_seman.AddStatusEffect(response.item.m_shared.m_consumeStatusEffect, true, 0, 0f); } if ((double)response.item.m_shared.m_food > 0.0) { localPlayer.EatFood(response.item); } } } public static void RPC_RequestItemMoveResponse(RequestMoveResponse response) { InventoryPreview.RemovePackage(response); } internal static Inventory GetSourceInventory(int id) { return PackageHandler.GetPackage<IRequest>(id)?.SourceInventory; } internal static Inventory GetTargetInventory(int id) { return PackageHandler.GetPackage<IRequest>(id)?.TargetInventory; } } public abstract class InventoryOwner { public abstract ZNetView ZNetView { get; } public abstract Inventory Inventory { get; } public virtual bool IsValid() { if (Object.op_Implicit((Object)(object)ZNetView) && ZNetView.HasOwner()) { return Inventory != null; } return false; } public static InventoryOwner GetOwner(Inventory inventory) { if (HumanoidExtend.GetHumanoid(inventory, out var humanoid)) { return humanoid; } if (ContainerExtend.GetContainer(inventory, out var container)) { return container; } return null; } public static InventoryOwner GetOwner(ItemData item) { if (InventoryPatch.InventoryOfItem.TryGetValue(item, out var value)) { return GetOwner(value); } return null; } public string GetDescription() { if (!IsValid()) { return "-"; } return $"{Inventory.GetName()} ({GetType().Name}), is owner: {ZNetView.IsOwner()}"; } } public class ContainerInventoryOwner : InventoryOwner { public Container Container { get; } public bool IsItemDrawer { get; } public override ZNetView ZNetView => Container.m_nview; public override Inventory Inventory => Container.GetInventory(); public ContainerInventoryOwner(Container container) { Container = container; IsItemDrawer = ItemDrawerCompat.IsItemDrawer(Container); } } public class HumanoidInventoryOwner : InventoryOwner { private readonly Inventory inventory; public Humanoid Humanoid { get; } public override ZNetView ZNetView => ((Character)Humanoid).m_nview; public override Inventory Inventory => inventory; public HumanoidInventoryOwner(Humanoid humanoid, Inventory inventory) { Humanoid = humanoid; this.inventory = inventory; } } public static class InventoryPreview { public static readonly ConditionalWeakTable<Inventory, List<IRequest>> PackageChanges = new ConditionalWeakTable<Inventory, List<IRequest>>(); public static readonly ConditionalWeakTable<Inventory, List<IRequest>> ToRemovePackages = new ConditionalWeakTable<Inventory, List<IRequest>>(); private static WaitForSeconds removeQueuedPackagesDelay = new WaitForSeconds(0.2f); public static void AddPackage(IRequest package) { package.RequestID = PackageHandler.AddPackage(package); AppendPackage(package.SourceInventory, package); AppendPackage(package.TargetInventory, package); } private static void AppendPackage(Inventory inventory, IRequest package) { if (PackageChanges.TryGetValue(inventory, out var value)) { if (!value.Contains(package)) { value.Add(package); } Log.LogDebug($"InventoryPreview: Appended package {package.RequestID} to inventory {inventory.m_name}, total packages: {value.Count}"); return; } PackageChanges.Add(inventory, new List<IRequest> { package }); Inventory obj = inventory; obj.m_onChanged = (Action)Delegate.Combine(obj.m_onChanged, (Action)delegate { RemoveQueuedPackages(inventory); }); Log.LogDebug($"InventoryPreview: Added package {package.RequestID} to inventory {inventory.m_name}, total packages: 1 (new)"); } public static void RemovePackage(IResponse package) { RemovePackage(InventoryHandler.GetSourceInventory(package.SourceID), package); RemovePackage(InventoryHandler.GetTargetInventory(package.SourceID), package); PackageHandler.RemovePackage(package.SourceID); } private static void RemovePackage(Inventory inventory, IResponse package) { if (inventory == null) { return; } InventoryOwner owner = InventoryOwner.GetOwner(inventory); IRequest request = null; if (PackageChanges.TryGetValue(inventory, out var value)) { request = value.Find((IRequest p) => p.RequestID == package.SourceID); } if (request != null) { if (ToRemovePackages.TryGetValue(inventory, out var value2)) { value2.Add(request); } else { ToRemovePackages.Add(inventory, new List<IRequest> { request }); } if (owner != null && owner.IsValid() && owner.ZNetView.IsOwner()) { RemoveQueuedPackages(inventory); } else if (!package.Success) { ((MonoBehaviour)ThreadingHelper.Instance).StartCoroutine(RemoveQueuedPackagesDelayed(inventory)); } } } private static void RemoveQueuedPackages(Inventory inventory) { if (!ToRemovePackages.TryGetValue(inventory, out var value) || value.Count <= 0) { return; } foreach (IRequest item in new List<IRequest>(value)) { if (PackageChanges.TryGetValue(inventory, out var value2)) { value2.Remove(item); } value.Remove(item); Log.LogDebug($"InventoryPreview: Removed package {item.RequestID} from inventory {inventory.m_name}, total packages: {value.Count}"); } } private static IEnumerator RemoveQueuedPackagesDelayed(Inventory inventory) { yield return removeQueuedPackagesDelay; RemoveQueuedPackages(inventory); } public static bool GetChanges(Inventory inventory, out SlotPreview preview) { //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) if (inventory == null) { preview = null; return false; } if (PackageChanges.TryGetValue(inventory, out var value)) { preview = new SlotPreview(inventory); foreach (IRequest item3 in value) { if (item3 is RequestChestAdd requestChestAdd) { if (requestChestAdd.dragItem != null) { ItemData item = null; if (requestChestAdd.allowSwitch) { item = item3.TargetInventory.GetItemAt(requestChestAdd.toPos.x, requestChestAdd.toPos.y); } if (inventory == item3.SourceInventory) { preview.Add(requestChestAdd.dragItem.m_gridPos, item); } if (inventory == item3.TargetInventory) { preview.Remove(requestChestAdd.toPos, item); preview.Add(requestChestAdd.toPos, requestChestAdd.dragItem); } } } else if (item3 is RequestChestRemove requestChestRemove) { Vector2i fromPos = requestChestRemove.fromPos; Vector2i toPos = requestChestRemove.toPos; if (inventory == item3.SourceInventory) { preview.Remove(fromPos, requestChestRemove.item, requestChestRemove.dragAmount); preview.Add(fromPos, requestChestRemove.switchItem); } if (inventory == item3.TargetInventory) { preview.Add(toPos, requestChestRemove.item, requestChestRemove.dragAmount); } } else { if (!(item3 is RequestMove requestMove) || (preview.GetSlot(requestMove.fromPos, out var item2) && requestMove.itemHash != ((item2 != null) ? new int?(StringExtensionMethods.GetStableHashCode(item2.PrefabName())) : null))) { continue; } ItemData itemAt = requestMove.TargetInventory.GetItemAt(requestMove.toPos.x, requestMove.toPos.y); if (itemAt != null && !InventoryHelper.CanStack(requestMove.item, itemAt)) { if (requestMove.dragAmount == requestMove.item.m_stack) { preview.Remove(requestMove.fromPos, requestMove.item, requestMove.dragAmount); preview.Remove(requestMove.toPos, itemAt, itemAt.m_stack); preview.Add(requestMove.fromPos, itemAt, itemAt.m_stack); preview.Add(requestMove.toPos, requestMove.item, requestMove.dragAmount); } } else { int amount = Mathf.Max(0, requestMove.dragAmount); if (itemAt != null) { amount = Mathf.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, requestMove.dragAmount); } preview.Remove(requestMove.fromPos, requestMove.item, amount); preview.Add(requestMove.toPos, requestMove.item, amount); } } } return preview.HasChanges(); } preview = null; return false; } } public static class ItemDrawerCompat { private static Type drawerContainerType; private static FieldRef<object, ItemData> drawerField_item; static ItemDrawerCompat() { if (Chainloader.PluginInfos.ContainsKey("mkz.itemdrawers")) { drawerContainerType = AccessTools.TypeByName("DrawerContainer, itemdrawers"); drawerField_item = AccessTools.FieldRefAccess<ItemData>(drawerContainerType, "_item"); } } public static bool IsItemDrawer(Container container) { if (drawerContainerType != null) { return Object.op_Implicit((Object)(object)((Component)container).GetComponent(drawerContainerType)); } return false; } [HarmonyPatch("DrawerContainer, itemdrawers", "OnInventoryChanged")] [HarmonyPrefix] public static void UpdateItemOfDrawer(Container __instance) { if (__instance.m_inventory.m_inventory.Count != 0 && __instance.m_inventory.m_inventory[0] != null) { drawerField_item.Invoke((object)__instance) = __instance.m_inventory.m_inventory[0].Clone(); } } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int) })] [HarmonyPriority(700)] public static bool PreventItemAdd(Inventory __instance, ItemData item) { if (InventoryOwner.GetOwner(__instance) is ContainerInventoryOwner containerInventoryOwner && containerInventoryOwner.IsItemDrawer) { ItemData val = drawerField_item.Invoke((object)containerInventoryOwner.Container); if (val != null && val.PrefabName() != item?.PrefabName()) { Log.LogInfo("PreventItemAdd: " + val.PrefabName() + " != " + item?.PrefabName()); return false; } } return true; } [HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[] { typeof(ItemData), typeof(int) })] [HarmonyPostfix] public static void CanAddItem(Inventory __instance, ref bool __result, ItemData item) { if (__result && InventoryOwner.GetOwner(__instance) is ContainerInventoryOwner containerInventoryOwner && containerInventoryOwner.IsItemDrawer) { ItemData val = drawerField_item.Invoke((object)containerInventoryOwner.Container); __result = val == null || val.PrefabName() == item?.PrefabName(); } } [HarmonyPatch("DrawerContainer, itemdrawers", "AddItem")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> CloneItemBeforeAssignmentTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0002: 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_0035: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(ItemDrop), "m_itemData"), (string)null), new CodeMatch((OpCode?)OpCodes.Stfld, (object)AccessTools.Field(drawerContainerType, "_item"), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(InventoryHelper), "CloneDeeper", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } } public static class OdinShip { public static bool IsOdinShipInstalled() { if (!Chainloader.PluginInfos.ContainsKey("marlthon.OdinShipPlus")) { return Chainloader.PluginInfos.ContainsKey("marlthon.OdinShip"); } return true; } public static bool IsOdinShipContainer(this Container container) { return ((object)container).GetType().FullName == "OdinShip.ShipContainer"; } } public static class QuickStackPatch { [HarmonyPatch("QuickStack.QuickStackPlugin, QuickStack", "StackToMany")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> QuickStackPatchTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null), new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.IsVirtCall("ZNetView", "ClaimOwnership")), (string)null) }).RemoveInstructions(9).InstructionEnumeration(); } } [BepInPlugin("com.maxsch.valheim.MultiUserChest", "MultiUserChest", "0.5.10")] [BepInIncompatibility("aedenthorn.QuickStore")] [BepInIncompatibility("aedenthorn.SimpleSort")] [BepInIncompatibility("org.bepinex.plugins.valheim.quick_stack")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string ModName = "MultiUserChest"; public const string ModGuid = "com.maxsch.valheim.MultiUserChest"; public const string ModVersion = "0.5.10"; private static Harmony harmony = new Harmony("com.maxsch.valheim.MultiUserChest"); public static Plugin Instance { get; private set; } private void Awake() { Instance = this; Log.Init(((BaseUnityPlugin)this).Logger); harmony.PatchAll(); ((MonoBehaviour)this).InvokeRepeating("UpdateAccessedContainer", 0f, 0.1f); } private void Start() { ApplyModPatches(); } internal static void ApplyModPatches() { if (Chainloader.PluginInfos.ContainsKey("mkz.itemdrawers")) { harmony.PatchAll(typeof(ItemDrawerCompat)); } } private void UpdateAccessedContainer() { //IL_0088: 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) if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Character)Player.m_localPlayer).m_nview.IsValid() && Object.op_Implicit((Object)(object)InventoryGui.instance)) { Container currentContainer = InventoryGui.instance.m_currentContainer; if (Object.op_Implicit((Object)(object)currentContainer) && currentContainer.m_nview.IsValid()) { ((Character)Player.m_localPlayer).m_nview.GetZDO().Set("accessed-container", currentContainer.m_nview.GetZDO().m_uid); } else { ((Character)Player.m_localPlayer).m_nview.GetZDO().Set("accessed-container", ZDOID.None); } } } } public static class PackageHandler { private static readonly Dictionary<int, IPackage> Packages = new Dictionary<int, IPackage>(); private static readonly Random Random = new Random(); private static int total; public static int AddPackage(IPackage package) { int randomId = GetRandomId(); Packages.Add(randomId, package); return randomId; } public static void RemovePackage(int id) { Packages.Remove(id); } private static int GetRandomId() { return Random.Next(int.MinValue, int.MaxValue); } public static bool GetPackage<T>(int id, out T package) where T : IPackage { if (Packages.TryGetValue(id, out var value)) { package = (T)value; return true; } package = default(T); return false; } public static T GetPackage<T>(int id) where T : IPackage { if (Packages.TryGetValue(id, out var value)) { return (T)value; } return default(T); } } } namespace MultiUserChest.Patches { [HarmonyPatch] public static class ContainerPatch { public const string ItemMoveRPC = "MUC_RequestItemMove"; public const string ItemMoveResponseRPC = "MUC_RequestItemMoveResponse"; public const string ItemAddRPC = "MUC_RequestItemAdd"; public const string ItemAddResponseRPC = "MUC_RequestItemAddResponse"; public const string ItemRemoveRPC = "MUC_RequestItemRemove"; public const string ItemRemoveResponseRPC = "MUC_RequestItemRemoveResponse"; public const string ItemConsumeRPC = "MUC_RequestItemConsume"; public const string ItemConsumeResponseRPC = "MUC_RequestItemConsumeResponse"; public const string ItemDropRPC = "MUC_RequestItemDrop"; public const string ItemDropResponseRPC = "MUC_RequestItemDropResponse"; [HarmonyPatch(typeof(Container), "Awake")] [HarmonyPostfix] public static void ContainerAwakePatch(Container __instance) { ((Component)__instance).gameObject.AddComponent<ContainerExtend>(); if (!__instance.IsOdinShipContainer() && !Object.op_Implicit((Object)(object)__instance.m_nview)) { __instance.m_nview = (Object.op_Implicit((Object)(object)__instance.m_rootObjectOverride) ? ((Component)__instance.m_rootObjectOverride).GetComponent<ZNetView>() : ((Component)__instance).GetComponent<ZNetView>()); } } [HarmonyPatch(typeof(Container), "RPC_RequestOpen")] [HarmonyPrefix] public static bool ContainerRPC_RequestOpenPatch(Container __instance, long uid, long playerID) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (__instance.IsOdinShipContainer() || !__instance.m_nview.IsOwner()) { return true; } if (!__instance.CheckAccess(playerID)) { __instance.m_nview.InvokeRPC(uid, "OpenRespons", new object[1] { false }); return false; } if (IsContainerInUse(__instance, uid)) { __instance.m_nview.InvokeRPC(uid, "OpenRespons", new object[1] { true }); return false; } ZDOMan.instance.ForceSendZDO(uid, __instance.m_nview.GetZDO().m_uid); __instance.m_nview.GetZDO().SetOwner(uid); __instance.m_nview.InvokeRPC(uid, "OpenRespons", new object[1] { true }); return false; } [HarmonyPatch(typeof(Container), "RPC_RequestStack")] [HarmonyPrefix] public static bool ContainerRPC_RequestStackPatch(Container __instance, long uid, long playerID) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (__instance.IsOdinShipContainer() || !__instance.m_nview.IsOwner()) { return true; } if (!__instance.CheckAccess(playerID)) { __instance.m_nview.InvokeRPC(uid, "RPC_StackResponse", new object[1] { false }); return false; } if (IsContainerInUse(__instance, uid)) { __instance.m_nview.InvokeRPC(uid, "RPC_StackResponse", new object[1] { true }); return false; } ZDOMan.instance.ForceSendZDO(uid, __instance.m_nview.GetZDO().m_uid); __instance.m_nview.GetZDO().SetOwner(uid); __instance.m_nview.InvokeRPC(uid, "RPC_StackResponse", new object[1] { true }); return false; } private static bool IsContainerInUse(Container container, long playerId) { bool flag = container.IsInUse(); bool flag2 = Object.op_Implicit((Object)(object)container.m_wagon) && container.m_wagon.InUse(); bool flag3 = playerId == ZNet.GetUID(); if (flag || flag2) { return !flag3; } return false; } [HarmonyPatch(typeof(Container), "UpdateUseVisual")] [HarmonyPostfix] public static void ContainerUpdateUseVisualPatch(Container __instance) { if (!__instance.IsOdinShipContainer() && __instance.m_nview.IsValid() && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)InventoryGui.instance)) { bool flag = (Object)(object)__instance == (Object)(object)InventoryGui.instance.m_currentContainer || IsContainerInUse(__instance); if (Object.op_Implicit((Object)(object)__instance.m_open)) { __instance.m_open.SetActive(flag); } if (Object.op_Implicit((Object)(object)__instance.m_closed)) { __instance.m_closed.SetActive(!flag); } } } private static bool IsContainerInUse(Container container) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) ZDOID containerId = container.m_nview.GetZDO().m_uid; return Player.GetAllPlayers().Any((Player p) => (Object)(object)p != (Object)(object)Player.m_localPlayer && ((Character)p).m_nview.IsValid() && ((Character)p).m_nview.GetZDO().GetZDOID("accessed-container") == containerId); } } [HarmonyPatch] public static class GamePatches { [HarmonyPatch(typeof(Game), "Start")] [HarmonyPostfix] public static void GameStartPatch() { RegisterRPCs(); } public static void RegisterRPCs() { ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemMove", (Action<long, ZDOID, ZPackage>)ContainerRPCHandler.RPC_RequestItemMove); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemAdd", (Action<long, ZDOID, ZPackage>)ContainerRPCHandler.RPC_RequestItemAdd); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemRemove", (Action<long, ZDOID, ZPackage>)ContainerRPCHandler.RPC_RequestItemRemove); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemConsume", (Action<long, ZDOID, ZPackage>)ContainerRPCHandler.RPC_RequestItemConsume); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemDrop", (Action<long, ZDOID, ZPackage>)ContainerRPCHandler.RPC_RequestDrop); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemMoveResponse", (Action<long, ZDOID, ZPackage>)InventoryHandler.RPC_RequestItemMoveResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemAddResponse", (Action<long, ZDOID, ZPackage>)InventoryHandler.RPC_RequestItemAddResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemRemoveResponse", (Action<long, ZDOID, ZPackage>)InventoryHandler.RPC_RequestItemRemoveResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemConsumeResponse", (Action<long, ZDOID, ZPackage>)InventoryHandler.RPC_RequestItemConsumeResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemDropResponse", (Action<long, ZDOID, ZPackage>)InventoryHandler.RPC_RequestDropResponse); } public static void InvokeRPC(ZNetView netView, string rpc, IPackage package) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) ZRoutedRpc.instance.InvokeRoutedRPC(netView.m_zdo.GetOwner(), rpc, new object[2] { netView.m_zdo.m_uid, package.WriteToPackage() }); } } [HarmonyPatch] public static class HumanoidPatch { [HarmonyPatch(typeof(Humanoid), "Awake")] [HarmonyPostfix] public static void HumanoidAwakePatch(Humanoid __instance) { ((Component)__instance).gameObject.AddComponent<HumanoidExtend>(); } } [HarmonyPatch] public static class InventoryGuiPatch { [HarmonyPatch(typeof(InventoryGui), "Update")] [HarmonyPostfix] public static void InventoryGuiUpdatePatch(InventoryGui __instance) { if (Object.op_Implicit((Object)(object)__instance.m_currentContainer) && Object.op_Implicit((Object)(object)__instance.m_currentContainer.m_nview) && __instance.m_currentContainer.m_nview.IsValid()) { __instance.m_currentContainer.CheckForChanges(); } } [HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")] [HarmonyPrefix] public static bool InventoryGuiOnRightClickItemPatch(InventoryGui __instance, InventoryGrid grid, ItemData item) { Player localPlayer = Player.m_localPlayer; if (item == null || !Object.op_Implicit((Object)(object)localPlayer)) { return true; } if (grid.GetInventory() == ((Humanoid)localPlayer).GetInventory()) { return true; } if (!Object.op_Implicit((Object)(object)__instance.m_currentContainer) || __instance.m_currentContainer.IsOwner()) { return true; } if (InventoryBlock.Get(((Humanoid)localPlayer).GetInventory()).BlockConsume) { return false; } if (((Humanoid)localPlayer).CanConsumeItem(item, false)) { InventoryBlock.Get(((Humanoid)localPlayer).GetInventory()).BlockConsume = true; RequestConsume package = new RequestConsume(item); GamePatches.InvokeRPC(__instance.m_currentContainer.m_nview, "MUC_RequestItemConsume", package); } return false; } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> ChangeOwnerCheck(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(true, (CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "m_currentContainer"), (string)null), new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "IsOwner"), (string)null) }).RemoveInstructions(1).Insert((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(InventoryGuiPatch), "CanOpenContainer", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } public static bool CanOpenContainer(Container container) { if (container.IsOdinShipContainer()) { return container.IsOwner(); } return true; } [HarmonyPatch(typeof(InventoryGui), "OnDropOutside")] [HarmonyPrefix] public static void InventoryGuiOnDropOutsidePatch(InventoryGui __instance, ref bool __runOriginal) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (!__runOriginal || !Object.op_Implicit((Object)(object)__instance.m_dragGo)) { return; } if (((Humanoid)Player.m_localPlayer).GetInventory().GetInventories().Contains(__instance.m_dragInventory)) { Log.LogDebug("Drop item from own inventory"); return; } bool flag = Object.op_Implicit((Object)(object)__instance.m_currentContainer) && __instance.m_currentContainer.IsOwner(); if (!(!Object.op_Implicit((Object)(object)__instance.m_currentContainer) || flag)) { RequestDrop package = new RequestDrop(__instance.m_dragItem.m_gridPos, __instance.m_dragAmount, ((Character)Player.m_localPlayer).GetZDOID()); GamePatches.InvokeRPC(__instance.m_currentContainer.m_nview, "MUC_RequestItemDrop", package); __instance.SetupDragItem((ItemData)null, (Inventory)null, 1); __runOriginal = false; } } [HarmonyPatch(typeof(Inventory), "Load")] [HarmonyPostfix] public static void InventorySelectSameItemAfterLoad(Inventory __instance) { if (Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.instance.m_dragItem != null && Object.op_Implicit((Object)(object)InventoryGui.instance.m_currentContainer) && InventoryGui.instance.m_currentContainer.GetInventory() == __instance && InventoryGui.instance.m_dragInventory != null && InventoryGui.instance.m_dragInventory == __instance) { ItemData dragItem = InventoryGui.instance.m_dragItem; ItemData itemAt = __instance.GetItemAt(dragItem.m_gridPos.x, dragItem.m_gridPos.y); if (itemAt == null) { InventoryGui.instance.SetupDragItem((ItemData)null, (Inventory)null, 1); return; } int dragAmount = Mathf.Min(itemAt.m_stack, InventoryGui.instance.m_dragAmount); InventoryGui.instance.m_dragAmount = dragAmount; InventoryGui.instance.m_dragItem = itemAt; } } [HarmonyPatch(typeof(InventoryGrid), "UpdateInventory")] [HarmonyPostfix] public static void InventoryGridUpdateInventoryPatch(InventoryGrid __instance) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!InventoryPreview.GetChanges(__instance.m_inventory, out var preview)) { return; } foreach (Element element in __instance.m_elements) { if (preview.GetSlot(element.m_pos, out var item)) { if (item == null) { ShowNoItem(element); } else { ShowItem(__instance, element, item); } } } } private static void ShowItem(InventoryGrid inventoryGrid, Element element, ItemData item) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Invalid comparison between Unknown and I4 //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) if (item?.m_shared == null) { return; } int stack = item.m_stack; int maxStackSize = item.m_shared.m_maxStackSize; ((Behaviour)element.m_icon).enabled = stack > 0; element.m_icon.sprite = item.GetIcon(); ((Graphic)element.m_icon).color = Color.white; ((Behaviour)element.m_amount).enabled = stack > 0 && maxStackSize > 1; element.m_amount.text = $"{stack}/{maxStackSize}"; bool flag = item.m_shared.m_useDurability && item.m_durability < item.GetMaxDurability(); ((Component)element.m_durability).gameObject.SetActive(flag); if (flag) { if ((double)item.m_durability <= 0.0) { element.m_durability.SetValue(1f); element.m_durability.SetColor((Color)(((double)Mathf.Sin(Time.time * 10f) > 0.0) ? Color.red : new Color(0f, 0f, 0f, 0f))); } else { element.m_durability.SetValue(item.GetDurabilityPercentage()); element.m_durability.ResetColor(); } } ((Behaviour)element.m_equiped).enabled = false; ((Behaviour)element.m_queued).enabled = false; ((Behaviour)element.m_noteleport).enabled = !item.m_shared.m_teleportable && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)29); if ((int)item.m_shared.m_itemType == 2 && ((double)item.m_shared.m_food > 0.0 || (double)item.m_shared.m_foodStamina > 0.0 || (double)item.m_shared.m_foodEitr > 0.0)) { ((Behaviour)element.m_food).enabled = true; if ((double)item.m_shared.m_food < (double)item.m_shared.m_foodEitr / 2.0 && (double)item.m_shared.m_foodStamina < (double)item.m_shared.m_foodEitr / 2.0) { ((Graphic)element.m_food).color = inventoryGrid.m_foodEitrColor; } else if ((double)item.m_shared.m_foodStamina < (double)item.m_shared.m_food / 2.0) { ((Graphic)element.m_food).color = inventoryGrid.m_foodHealthColor; } else if ((double)item.m_shared.m_food < (double)item.m_shared.m_foodStamina / 2.0) { ((Graphic)element.m_food).color = inventoryGrid.m_foodStaminaColor; } else { ((Graphic)element.m_food).color = Color.white; } } else { ((Behaviour)element.m_food).enabled = false; } ((Behaviour)element.m_quality).enabled = item.m_shared.m_maxQuality > 1; if (item.m_shared.m_maxQuality > 1) { element.m_quality.text = item.m_quality.ToString(); } } private static void ShowNoItem(Element element) { ((Component)element.m_durability).gameObject.SetActive(false); ((Behaviour)element.m_icon).enabled = false; ((Behaviour)element.m_amount).enabled = false; ((Behaviour)element.m_quality).enabled = false; ((Behaviour)element.m_equiped).enabled = false; ((Behaviour)element.m_queued).enabled = false; ((Behaviour)element.m_noteleport).enabled = false; ((Behaviour)element.m_food).enabled = false; element.m_tooltip.m_text = ""; element.m_tooltip.m_topic = ""; } } [HarmonyPatch] public static class InventoryPatch { public static readonly ConditionalWeakTable<ItemData, Inventory> InventoryOfItem = new ConditionalWeakTable<ItemData, Inventory>(); private static readonly WeakReference<ItemData> LastRemovedItem = new WeakReference<ItemData>(null); private static bool allowItemSwap = true; [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int) })] [HarmonyPrefix] [HarmonyPriority(100)] public static void AddItem1Prefix(Inventory __instance, ref bool __runOriginal, ItemData item, int amount, int x, int y, ref bool __result) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (__runOriginal && InterceptAddItem(__instance, item, amount, new Vector2i(x, y), out var successfulAdded)) { __result = successfulAdded; __runOriginal = false; } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] [HarmonyPrefix] [HarmonyPriority(100)] public static void AddItem2Prefix(Inventory __instance, ref bool __runOriginal, ItemData item, ref bool __result) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (__runOriginal && InterceptAddItem(__instance, item, item.m_stack, new Vector2i(-1, -1), out var successfulAdded)) { __result = successfulAdded; __runOriginal = false; } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData) })] [HarmonyPrefix] [HarmonyPriority(100)] public static void RemoveItemPrefix(Inventory __instance, ref bool __runOriginal, ref bool __result) { if (__runOriginal) { InventoryOwner owner = InventoryOwner.GetOwner(__instance); if (owner != null && owner.IsValid() && !owner.ZNetView.IsOwner()) { __result = false; __runOriginal = false; } } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData) })] [HarmonyPostfix] public static void RemoveItemPostfix(Inventory __instance, ItemData item, ref bool __result) { if (__result) { LastRemovedItem.SetTarget(item); } else { LastRemovedItem.SetTarget(null); } } [HarmonyPatch(typeof(Inventory), "MoveAll")] [HarmonyPrefix] [HarmonyPriority(800)] public static void MoveAllPrefix() { allowItemSwap = false; } [HarmonyPatch(typeof(Inventory), "MoveAll")] [HarmonyPostfix] [HarmonyPriority(0)] public static void MoveAllPostfix() { allowItemSwap = true; } [HarmonyPatch(typeof(Inventory), "Changed")] [HarmonyPostfix] public static void AddItemPostfix(Inventory __instance) { foreach (Inventory inventory in __instance.GetInventories()) { AssignItemsOfInventory(inventory); } if (LastRemovedItem.TryGetTarget(out var target) && InventoryOwner.GetOwner(target)?.Inventory == __inst
Plugins/NoRainDamage.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("NoRainDamage")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("NoRainDamage")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("65825995-ebff-4e7e-81c3-6254d9832f19")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace NoRainDamage; [BepInPlugin("uk.co.oliapps.valheim.noraindamage", "No Rain Damage", "1.2.2")] public class NoRainDamage : BaseUnityPlugin { private enum DamageFilter { ALL, INCLUSIVE, EXCLUSIVE } private static ConfigEntry<float> damagePerMinute; private static ConfigEntry<float> maxRainDamagePercentage; private static ConfigEntry<DamageFilter> damageFilter; private static ConfigEntry<string> damageFilterValues; private static ConfigEntry<bool> modEnabled; private static Dictionary<int, float> minHealths; private static float minHealthPercentage; public void Awake() { modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Set whether the mod is enabled"); maxRainDamagePercentage = ((BaseUnityPlugin)this).Config.Bind<float>("Rain Damage", "Max Damage", 0f, "Maximum damage rain can do to uncovered structures between 0.0 and 1.0"); damagePerMinute = ((BaseUnityPlugin)this).Config.Bind<float>("Rain Damage", "Damage Per Minute", 5f, "Damage per minute rain deals to uncovered structures"); damageFilter = ((BaseUnityPlugin)this).Config.Bind<DamageFilter>("Damage Filter", "Filter Type", DamageFilter.ALL, "Set whether everything should be protected (ALL), certain things should be protected (INCLUSIVE) or certain things should not be protected (EXCLUSIVE)"); damageFilterValues = ((BaseUnityPlugin)this).Config.Bind<string>("Damage Filter", "Filter List", "", "If Filter type is INCLUSIVE or EXCLUSIVE, this list of comma-separated values will be used as a filter (will protect or damage if piece name contains value). Piece list included in mod download."); ((BaseUnityPlugin)this).Config.Save(); if (modEnabled.Value) { Harmony.CreateAndPatchAll(typeof(NoRainDamage), (string)null); minHealths = new Dictionary<int, float>(); } } [HarmonyPatch(typeof(WearNTear), "Awake")] [HarmonyPostfix] public static void WearNTear_Awake(ref WearNTear __instance) { minHealthPercentage = 1f - Mathf.Clamp(maxRainDamagePercentage.Value, 0f, 1f); minHealths.Add(((Object)__instance).GetInstanceID(), __instance.m_health * minHealthPercentage); } [HarmonyPatch(typeof(WearNTear), "UpdateWear")] [HarmonyPrefix] [HarmonyPriority(0)] public static bool WearNTear_UpdateWear(ref WearNTear __instance) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (OverrideWearNTear(ref __instance)) { ZNetView val = (ZNetView)AccessTools.Field(typeof(WearNTear), "m_nview").GetValue(__instance); if ((Object)(object)val == (Object)null || !val.IsValid()) { return false; } bool flag = (bool)AccessTools.Method(typeof(WearNTear), "ShouldUpdate", (Type[])null, (Type[])null).Invoke(__instance, new object[0]); if (val.IsOwner() && flag) { if (ZNetScene.instance.OutsideActiveArea(((Component)__instance).transform.position)) { float num = (float)AccessTools.Method(typeof(WearNTear), "GetMaxSupport", (Type[])null, (Type[])null).Invoke(__instance, new object[0]); AccessTools.Field(typeof(WearNTear), "m_support").SetValue(__instance, num); val.GetZDO().Set("support", num); return false; } float num2 = 0f; bool flag2 = (bool)AccessTools.Method(typeof(WearNTear), "HaveRoof", (Type[])null, (Type[])null).Invoke(__instance, new object[0]); bool flag3 = EnvMan.IsWet() && !flag2; if (Object.op_Implicit((Object)(object)__instance.m_wet)) { __instance.m_wet.SetActive(flag3); } if (__instance.m_noRoofWear && (double)__instance.GetHealthPercentage() > (double)minHealthPercentage) { bool flag4 = (bool)AccessTools.Method(typeof(WearNTear), "IsUnderWater", (Type[])null, (Type[])null).Invoke(__instance, new object[0]); float num3 = (float)AccessTools.Field(typeof(WearNTear), "m_rainTimer").GetValue(__instance); float @float = val.GetZDO().GetFloat("health", __instance.m_health); if (flag3 || flag4) { if ((double)num3 == 0.0) { num3 = Time.time; } else if ((double)Time.time - (double)num3 > 60.0) { num3 = Time.time; num2 += damagePerMinute.Value; if (IsTooMuchDamage(ref __instance, @float, num2)) { float num4 = HowMuchIsTooMuch(ref __instance, @float, num2); num2 -= num4; } } } else { num3 = 0f; } AccessTools.Field(typeof(WearNTear), "m_rainTimer").SetValue(__instance, num3); } if (__instance.m_noSupportWear) { AccessTools.Method(typeof(WearNTear), "UpdateSupport", (Type[])null, (Type[])null).Invoke(__instance, new object[0]); if (!(bool)AccessTools.Method(typeof(WearNTear), "HaveSupport", (Type[])null, (Type[])null).Invoke(__instance, new object[0])) { num2 = 100f; } } bool flag5 = (bool)AccessTools.Method(typeof(WearNTear), "CanBeRemoved", (Type[])null, (Type[])null).Invoke(__instance, new object[0]); if ((double)num2 > 0.0 && !flag5) { num2 = 0f; } if ((double)num2 > 0.0) { __instance.ApplyDamage(num2 / 100f * __instance.m_health, (HitData)null); } } AccessTools.Method(typeof(WearNTear), "UpdateVisual", (Type[])null, (Type[])null).Invoke(__instance, new object[1] { true }); return false; } return true; } private static bool OverrideWearNTear(ref WearNTear instance) { if (DamageFilter.ALL.Equals(damageFilter.Value)) { return true; } string[] array = damageFilterValues.Value.Split(new char[1] { ',' }); foreach (string value in array) { if (((Object)((Component)instance).gameObject).name.Contains(value)) { return damageFilter.Value switch { DamageFilter.INCLUSIVE => true, DamageFilter.EXCLUSIVE => false, _ => true, }; } } return DamageFilter.EXCLUSIVE.Equals(damageFilter.Value); } private static bool IsTooMuchDamage(ref WearNTear instance, float health, float damage) { return health - damage / 100f * instance.m_health < minHealths[((Object)instance).GetInstanceID()]; } private static float HowMuchIsTooMuch(ref WearNTear instance, float health, float damage) { float num = health - damage / 100f * instance.m_health; return Mathf.Abs(minHealths[((Object)instance).GetInstanceID()] - num) / instance.m_health * 100f; } private static void Log(string message) { ZLog.Log((object)("[No Rain Damage] " + message)); } [HarmonyPatch(typeof(WearNTear), "OnDestroy")] [HarmonyPostfix] public static void WearNTear_OnDestroy(ref WearNTear __instance) { minHealths.Remove(((Object)__instance).GetInstanceID()); } }
Plugins/SmartContainers.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("SmartContainers")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SmartContainers")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("6b695573-f20c-49d7-99c3-26f3bd0c12c1")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace SmartContainers; internal sealed class ConfigurationManagerAttributes { public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func<object, string> ObjToStr; public Func<string, object> StrToObj; } public static class ContainersTracker { public static ICollection<Container> containerList = new List<Container>(); public static bool isRearrangingItem = false; public static bool teleportingInProgress = false; public static List<Container> GetNearbyContainers(Vector3 center, bool all = false) { //IL_0066: 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) List<Container> list = new List<Container>(); foreach (Container container in containerList) { int num = (all ? (Mod.range.Value * 2) : Mod.range.Value); if ((Object)(object)container != (Object)null && (Object)(object)((Component)container).transform != (Object)null && container.GetInventory() != null && (Object)(object)((Component)container).GetComponentInParent<Piece>() != (Object)null) { float num2 = Vector3.Distance(center, ((Component)container).transform.position); if ((num <= 0 || num2 < (float)num) && container.CheckAccess(Player.m_localPlayer.GetPlayerID())) { list.Add(container); } } } return list; } public static void Init() { Container[] array = Object.FindObjectsOfType<Container>(); Mod.log.LogDebug((object)$"tracking {array.Length} discovered containers."); Container[] array2 = array; foreach (Container val in array2) { if (!((Object)val).name.StartsWith("Treasure") && val.GetInventory() != null && val.m_nview.IsValid() && val.m_nview.GetZDO().GetLong(StringExtensionMethods.GetStableHashCode("creator"), 0L) != 0L) { containerList.Add(val); } } } public static void CleanupContainersList() { Mod.log.LogDebug((object)$"cleanup containerList. size before: {containerList.Count}"); foreach (Container item in containerList.ToList()) { if (!((Object)(object)item != (Object)null) || !((Object)(object)((Component)item).transform != (Object)null) || item.GetInventory() == null) { containerList.Remove(item); } } Mod.log.LogDebug((object)$"cleanup containerList. size after: {containerList.Count}"); } } [HarmonyPatch(typeof(Container), "Awake")] internal static class Container_Awake_Patch { private static void Postfix(Container __instance) { if (Mod.modEnabled.Value && !((Object)__instance).name.StartsWith("Treasure") && __instance.GetInventory() != null && __instance.m_nview.IsValid() && (__instance.m_nview.GetZDO().GetLong(StringExtensionMethods.GetStableHashCode("creator"), 0L) != 0L || __instance.m_nview.GetZDO().GetOwner() != 0L)) { ContainersTracker.containerList.Add(__instance); } } } [HarmonyPatch(typeof(Container), "OnDestroyed")] internal static class Container_OnDestroyed_Patch { private static void Prefix(Container __instance) { if (Mod.modEnabled.Value) { ContainersTracker.containerList.Remove(__instance); } } } [HarmonyPatch(typeof(Inventory), "StackAll")] internal static class Container_OnStackAll_Patch { private static void Postfix(Inventory __instance, Inventory fromInventory, bool message) { if (Mod.unloadAllEnabled.Value && Mod.unloadAllInsteadStackBtn.Value) { InventoryGui instance = InventoryGui.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_playerGrid == (Object)null) && !((Object)(object)instance.m_containerGrid == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting()) { UnloadItems.UnloadAllItems(((Humanoid)Player.m_localPlayer).GetInventory()); } } } } [HarmonyPatch(typeof(Player), "UpdateTeleport")] public static class PlayerUpdateTeleport_Patch_Cleanup_Containers { public static void Prefix(float dt) { if (Mod.modEnabled.Value) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && localPlayer.m_teleporting && !ContainersTracker.teleportingInProgress) { ContainersTracker.teleportingInProgress = true; } } } } [HarmonyPatch(typeof(Player), "UpdateTeleport")] public static class PlayerUpdateTeleport_Postfix { public static void Postfix(float dt) { if (Mod.modEnabled.Value) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && ContainersTracker.teleportingInProgress && !localPlayer.m_teleporting) { ContainersTracker.CleanupContainersList(); ContainersTracker.teleportingInProgress = false; } } } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] public static class Inventory_Patch { public static void Postfix(Inventory __instance, ItemData item, ref bool __result) { //IL_00a5: 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) //IL_00b9: 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) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) if (!Mod.modEnabled.Value || __instance == null || (Object)(object)Player.m_localPlayer == (Object)null || ((Character)Player.m_localPlayer).IsTeleporting() || ((object)__instance).Equals((object?)((Humanoid)Player.m_localPlayer).GetInventory()) || !((Humanoid)Player.m_localPlayer).GetInventory().ContainsItem(item) || (Mod.onlyStackableItems.Value && item.m_shared.m_maxStackSize == 1) || ContainersTracker.isRearrangingItem) { return; } if (Input.GetKey((KeyCode)108)) { Console.instance.Print("SmartContainers tracked item [" + item.m_shared.m_name + "]"); } KeyboardShortcut value = Mod.keyModifier.Value; if (!((KeyboardShortcut)(ref value)).IsPressed()) { value = Mod.groupingKeyModifier.Value; if (!((KeyboardShortcut)(ref value)).IsPressed() && (!Mod.gamepadKey2.Value.MainPressed() || !ZInput.GetButton(Mod.gamepadKey1.Value))) { return; } } if ((Object)(object)InventoryGui.instance == (Object)null || !InventoryGui.instance.IsContainerOpen()) { return; } ContainersTracker.isRearrangingItem = true; if (!__result) { if (TryAddToNearBy(item)) { __result = true; Mod.PlayEffect(Mod.audioFeedbackEnabled.Value, "sfx_lootspawn", ((Character)Player.m_localPlayer).GetCenterPoint()); } } else if (__instance.CountItems(item.m_shared.m_name, -1, true) == item.m_stack && TryAddToNearBy(item)) { __instance.RemoveItem(item); Mod.PlayEffect(Mod.audioFeedbackEnabled.Value, "sfx_lootspawn", ((Character)Player.m_localPlayer).GetCenterPoint()); } ContainersTracker.isRearrangingItem = false; } public static bool TryAddToNearBy(ItemData item, bool allowCurrent = false, bool forceGrouping = false) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) try { Container openedContainer = InventoryGui.instance.m_currentContainer; if (Mod.concurrencyWorkaround.Value.BlockIfAnyOtherOpened() && ContainersTracker.GetNearbyContainers(((Component)Player.m_localPlayer).transform.position, all: true).Any((Container c) => ((object)openedContainer).GetHashCode() != ((object)c).GetHashCode() && c.m_nview.GetZDO().GetInt("InUse", 0) == 1)) { ((Character)Player.m_localPlayer).Message((MessageType)2, "Cant distribute items: other Player is using containers nearby.", 0, (Sprite)null); return false; } List<Container> list = (from c in ContainersTracker.GetNearbyContainers(((Component)Player.m_localPlayer).transform.position) where ((object)openedContainer).GetHashCode() == ((object)c).GetHashCode() || (Mod.concurrencyWorkaround.Value.Ignore() && ((object)openedContainer).GetHashCode() != ((object)c).GetHashCode()) || ((Mod.concurrencyWorkaround.Value.SkipOpenedOthers() || Mod.concurrencyWorkaround.Value.BlockIfAnyOtherOpened()) && c.m_nview.GetZDO().GetInt("InUse", 0) == 0) select c).ToList(); foreach (Container item2 in list) { if (item2.GetInventory().CanAddItem(item, -1) && (allowCurrent || ((object)openedContainer).GetHashCode() != ((object)item2).GetHashCode()) && item2.GetInventory().HaveItem(item.m_shared.m_name, true)) { Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has same item stack"); return AddItemToContainer(item, item2, allowCurrent); } } KeyboardShortcut value; if (Mod.groupingEnabled.Value) { if (!forceGrouping) { value = Mod.groupingKeyModifier.Value; if (!((KeyboardShortcut)(ref value)).IsPressed() && !ZInput.IsGamepadActive()) { goto IL_03ef; } } List<Tuple<string, Container>> list2 = new List<Tuple<string, Container>>(); foreach (Container item3 in list) { if (item3.GetInventory().CanAddItem(item, -1)) { string text = ItemGroups.FindMatchingUserGroup(item3, item); if (text != null) { list2.Add(Tuple.Create<string, Container>(text, item3)); } } } if (list2.Any()) { Tuple<string, Container> tuple = list2.OrderByDescending((Tuple<string, Container> t) => t.Item1).First(); if (list2.Count > 1) { Mod.log.LogWarning((object)("Ambiguous item-groups [" + string.Join(",", list2) + "] found for " + ((Object)item.m_dropPrefab).name + " item. Using " + tuple.Item1)); } Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item from group " + tuple.Item1 + " : [" + string.Join(",", ItemGroups.Groups[tuple.Item1]) + "]"); return AddItemToContainer(item, tuple.Item2, allowCurrent); } foreach (Container item4 in list) { if (item4.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSame_SystemGroupItems(item4, item)) { return AddItemToContainer(item, item4, allowCurrent); } } foreach (Container item5 in list) { if (item5.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSame_NamePatternItems(item5, item)) { return AddItemToContainer(item, item5, allowCurrent); } } if (Mod.itemTypeGroupsEnabled.Value) { foreach (Container item6 in list) { if (item6.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSameItemType(item6, item)) { return AddItemToContainer(item, item6, allowCurrent); } } } goto IL_03ef; } goto IL_046b; IL_03ef: if (Mod.fuzzyGroupingEnabled.Value) { if (!forceGrouping) { value = Mod.groupingKeyModifier.Value; if (!((KeyboardShortcut)(ref value)).IsPressed() && !ZInput.IsGamepadActive()) { goto IL_046b; } } foreach (Container item7 in list) { if (item7.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSimilarGroupItems(item7, item)) { return AddItemToContainer(item, item7, allowCurrent); } } } goto IL_046b; IL_046b: return false; } catch (Exception ex) { Mod.log.LogError((object)("Failed to rearrange container items: " + ex)); } return false; } private static bool AddItemToContainer(ItemData item, Container targetContainer, bool allowCurrent = false) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) Container currentContainer = InventoryGui.instance.m_currentContainer; if (allowCurrent || ((object)currentContainer).GetHashCode() != ((object)targetContainer).GetHashCode()) { bool num = targetContainer.GetInventory().AddItem(item); if (num) { targetContainer.Save(); targetContainer.GetInventory().Changed(); if (Mod.hudMessageEnabled.Value && !((object)InventoryGui.instance.m_currentContainer).Equals((object?)targetContainer)) { MessageHud.instance.QueueUnlockMsg(item.GetIcon(), item.m_shared.m_name, Mod.hudMessageText.Value); } Mod.PlayEffect(Mod.effectFeedbackEnabled.Value, "vfx_Potion_health_medium", ((Component)targetContainer).transform.position); } return num; } return false; } } public static class GuiFactory { public static void CreateMrgDialog(out GameObject dialogObj, string dlgUid, string label1, string label2, string label3, UnityAction onFirst, UnityAction onSecond, UnityAction onThird) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Expected O, but got Unknown //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Expected O, but got Unknown //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Expected O, but got Unknown //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Unknown result type (might be due to invalid IL or missing references) //IL_0472: Unknown result type (might be due to invalid IL or missing references) //IL_04a8: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Unknown result type (might be due to invalid IL or missing references) //IL_0504: Unknown result type (might be due to invalid IL or missing references) //IL_0527: Unknown result type (might be due to invalid IL or missing references) //IL_0531: Expected O, but got Unknown //IL_0533: Unknown result type (might be due to invalid IL or missing references) //IL_0547: Expected O, but got Unknown //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_0585: Unknown result type (might be due to invalid IL or missing references) //IL_0590: Unknown result type (might be due to invalid IL or missing references) //IL_05a1: Unknown result type (might be due to invalid IL or missing references) //IL_05cb: Unknown result type (might be due to invalid IL or missing references) //IL_05da: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)InventoryGui.instance).gameObject.transform.Find("root/SplitDialog"); Transform val2 = Object.Instantiate<Transform>(val, val.parent); ((Object)val2).name = dlgUid; Transform winWrap = val2.Find("win_bkg"); ((RectTransform)winWrap).SetSizeWithCurrentAnchors((Axis)0, 500f); dialogObj = ((Component)val2).gameObject; Object.Destroy((Object)(object)((Component)winWrap.Find("Icon_bkg")).gameObject); Object.Destroy((Object)(object)((Component)winWrap.Find("Slider")).gameObject); Object.Destroy((Object)(object)((Component)winWrap.Find("Text")).gameObject); Object.Destroy((Object)(object)((Component)winWrap.Find("amount")).gameObject); ((Component)winWrap.Find("Button_cancel")).gameObject.AddComponent(typeof(UIGamePad)); ((Component)winWrap.Find("Button_ok")).gameObject.AddComponent(typeof(UIGamePad)); Transform val3 = winWrap.Find("Button_cancel"); Transform val4 = winWrap.Find("Button_ok"); Transform val5 = Object.Instantiate<Transform>(val4, ((Component)winWrap).transform); ((Object)val5).name = "Button_3"; ((TMP_Text)((Component)val3.Find("Text")).GetComponent<TextMeshProUGUI>()).text = label1; ((TMP_Text)((Component)val4.Find("Text")).GetComponent<TextMeshProUGUI>()).text = label2; ((TMP_Text)((Component)val5.Find("Text")).GetComponent<TextMeshProUGUI>()).text = label3; RectTransform val6 = (RectTransform)((Component)val3).transform; val6.pivot += new Vector2(0.5f, 0.7f); RectTransform val7 = (RectTransform)((Component)val4).transform; val7.pivot += new Vector2(0.57f, 0.7f); RectTransform val8 = (RectTransform)((Component)val5).transform; val8.pivot += new Vector2(-0.48f, 0.7f); ((RectTransform)((Component)val3).transform).SetSizeWithCurrentAnchors((Axis)1, 40f); ((RectTransform)((Component)val4).transform).SetSizeWithCurrentAnchors((Axis)1, 40f); ((RectTransform)((Component)val5).transform).SetSizeWithCurrentAnchors((Axis)1, 40f); InitJoyKey((Transform)(RectTransform)val3, "JoyTabLeft", "(LB)"); InitJoyKey((Transform)(RectTransform)val4, "JoyTabRight", "(RB)"); InitJoyKey((Transform)(RectTransform)val5, "", ""); Transform obj = Object.Instantiate<Transform>(((Component)InventoryGui.instance).gameObject.transform.Find("root/Texts/Texts_frame/TextArea"), winWrap); ((Object)obj).name = "TextArea"; ((Component)obj).gameObject.SetActive(true); ((Graphic)((Component)obj).GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.4f); RectTransform val9 = (RectTransform)obj; ((Transform)val9).position = ((Transform)(RectTransform)((Component)val.Find("win_bkg/bkg")).transform).position; ((Transform)val9).localScale = ((Transform)(RectTransform)((Component)val.Find("win_bkg/bkg")).transform).localScale; val9.sizeDelta = ((RectTransform)((Component)val.Find("win_bkg/bkg")).transform).sizeDelta; val9.SetSizeWithCurrentAnchors((Axis)1, 190f); val9.SetSizeWithCurrentAnchors((Axis)0, 515f); val9.pivot = new Vector2(0.51f, 0.33f); ((RectTransform)obj.Find("ScrollArea/Content/Name")).SetSizeWithCurrentAnchors((Axis)0, 515f); ((RectTransform)obj.Find("ScrollArea/Content/Description")).SetSizeWithCurrentAnchors((Axis)0, 515f); TextMeshProUGUI component = ((Component)obj.Find("ScrollArea/Content/Name")).GetComponent<TextMeshProUGUI>(); TextMeshProUGUI component2 = ((Component)obj.Find("ScrollArea/Content/Description")).GetComponent<TextMeshProUGUI>(); ((TMP_Text)component).fontSize = 18f; ((Graphic)component).color = new Color(0.79f, 0.75f, 0.28f, 1f); ((TMP_Text)component2).fontSize = 18f; ((Graphic)component2).color = new Color(0.8f, 0.8f, 0.8f, 1f); Transform val10 = CreateButton("Selector", "--select--", winWrap.Find("TextArea"), new Vector2(380f, 24f), new Vector2(-0.23f, 11.4f)); GameObject val11 = Object.Instantiate<GameObject>(Find("RecipeList"), winWrap); ((Object)val11).name = "SelectorDlg"; ((RectTransform)val11.transform).pivot = new Vector2(-0.55f, 1.7f); Transform val12 = val11.transform.Find("Recipes/ListRoot"); for (int i = 0; i < val12.childCount; i++) { Object.Destroy((Object)(object)((Component)val12.GetChild(i)).gameObject); } ((RectTransform)val11.transform).SetSizeWithCurrentAnchors((Axis)1, 150f); ((UnityEvent)((Component)val10).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { GameObject gameObject = ((Component)winWrap.Find("SelectorDlg")).gameObject; gameObject.SetActive(!gameObject.activeSelf); }); InitJoyKey((Transform)(RectTransform)val10, "", ""); Transform obj2 = Object.Instantiate<Transform>(((Component)InventoryGui.instance.m_takeAllButton).transform.Find("Text"), winWrap.Find("TextArea")); ((RectTransform)obj2).pivot = new Vector2(-0.05f, -0.13f); ((RectTransform)obj2).SetSizeWithCurrentAnchors((Axis)1, 24f); ((RectTransform)obj2).SetSizeWithCurrentAnchors((Axis)0, 150f); ((TMP_Text)((Component)obj2).GetComponent<TextMeshProUGUI>()).text = "Target group:"; ((RectTransform)((Component)winWrap).transform).pivot = new Vector2(-0.7f, 1f); ((UnityEvent)((Component)val3).GetComponent<Button>().onClick).AddListener(onFirst); ((UnityEvent)((Component)val4).GetComponent<Button>().onClick).AddListener(onSecond); ((UnityEvent)((Component)val5).GetComponent<Button>().onClick).AddListener(onThird); } public static Transform AddContainerGuiButton(string btnObjName, string text, Vector2 size, Vector2 pos) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) return CreateButton(btnObjName, text, ((Component)InventoryGui.instance.m_takeAllButton).transform.parent, size, pos); } public static Transform CreateButton(string btnObjName, string text, Transform parent, Vector2 size, Vector2 pos) { //IL_0007: 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) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_004d: 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_0062: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown _ = (RectTransform)parent.Find(btnObjName); Transform obj = Object.Instantiate<Transform>(((Component)InventoryGui.instance.m_takeAllButton).transform, parent); ((Object)obj).name = btnObjName; RectTransform val = (RectTransform)((Component)obj).transform; val.SetSizeWithCurrentAnchors((Axis)0, size.x); val.SetSizeWithCurrentAnchors((Axis)1, size.y); RectTransform val2 = (RectTransform)((Component)val).transform.Find("Text"); val2.SetSizeWithCurrentAnchors((Axis)0, size.x); val2.SetSizeWithCurrentAnchors((Axis)1, size.y); ((TMP_Text)((Component)val2).GetComponent<TextMeshProUGUI>()).text = text; val.pivot = pos; return (Transform)val; } public static void InitJoyKey(Transform btnComponent, string joyKeyCode, string tooltip) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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) UIGamePad component = ((Component)btnComponent).GetComponent<UIGamePad>(); Transform val = Object.Instantiate<Transform>(((Component)btnComponent).transform.Find("Text"), ((Component)component).transform); ((TMP_Text)((Component)val).GetComponent<TextMeshProUGUI>()).text = tooltip; ((Graphic)((Component)val).GetComponent<TextMeshProUGUI>()).color = new Color(0.8f, 0.8f, 0.8f, 1f); Transform transform = ((Component)val).transform; transform.position += new Vector3(0f, 13f, 0f); if ((Object)(object)component.m_hint != (Object)null) { Object.Destroy((Object)(object)component.m_hint); } component.m_hint = ((Component)val).gameObject; component.m_zinputKey = joyKeyCode; ((Behaviour)((Component)val).GetComponent<TextMeshProUGUI>()).enabled = ZInput.IsGamepadActive(); } public static void FillResList(RectTransform parent, ICollection<string> names, ICollection<Object> m_resObjects, Action<string> cb) { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) foreach (Object m_resObject in m_resObjects) { Object.Destroy(m_resObject); } m_resObjects.Clear(); float num = 0f; GameObject val = Find("RecipeList/Recipes/RecipeElement"); foreach (string groupName in names) { GameObject val2 = Object.Instantiate<GameObject>(val, ((Component)parent).transform); Object.Destroy((Object)(object)((Component)val2.transform.Find("icon")).gameObject); Object.Destroy((Object)(object)((Component)val2.transform.Find("Durability")).gameObject); Object.Destroy((Object)(object)((Component)val2.transform.Find("QualityLevel")).gameObject); val2.SetActive(true); ((UnityEvent)val2.GetComponentInChildren<Button>().onClick).AddListener((UnityAction)delegate { cb(groupName); }); Transform transform = val2.transform; ((RectTransform)((transform is RectTransform) ? transform : null)).anchoredPosition = new Vector2(0f, num * -20f); ((TMP_Text)val2.GetComponentInChildren<TextMeshProUGUI>()).text = groupName; m_resObjects.Add((Object)(object)val2); num += 1f; } Rect rect = parent.rect; parent.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(((Rect)(ref rect)).height, num * 20f)); } private static GameObject Find(string name) { GameObject val = GameObject.Find("_GameMain/LoadingGUI/PixelFix/IngameGui/Inventory_screen/root/Crafting/" + name); if ((Object)(object)val == (Object)null) { Mod.log.LogWarning((object)("Failed to locate '" + name + "' GameObject - fallback to IngameGui(Clone) lookup..")); val = ((Component)GameObject.Find("IngameGui").transform.Find("Inventory_screen/root/Crafting/" + name)).gameObject; } return val; } } [HarmonyPatch(typeof(InventoryGui), "Show")] public static class Gui_Patch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<Tuple<string, List<string>>, string> <>9__8_3; public static UnityAction <>9__8_0; public static Func<Tuple<string, List<string>>, string> <>9__8_4; public static UnityAction <>9__8_1; public static Func<Tuple<string, List<string>>, string> <>9__8_5; public static UnityAction <>9__8_2; public static Func<Tuple<string, List<string>>, string> <>9__10_0; public static Func<Tuple<string, List<string>>, IEnumerable<string>> <>9__10_1; public static Func<ItemData, bool> <>9__10_5; public static Func<ItemData, string> <>9__10_6; public static Func<Tuple<string, List<string>>, string> <>9__10_8; public static Func<Tuple<string, List<string>>, string> <>9__10_3; internal void <InitButtons>b__8_0() { if (containersUniqueItems != null && intersectedGroups != null) { ItemGroupUtils.ExtendGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems); } groupsDialogObj.gameObject.SetActive(false); } internal string <InitButtons>b__8_3(Tuple<string, List<string>> _) { return _.Item1; } internal void <InitButtons>b__8_1() { if (containersUniqueItems != null) { ItemGroupUtils.ExtendAndMerge(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems); } groupsDialogObj.gameObject.SetActive(false); } internal string <InitButtons>b__8_4(Tuple<string, List<string>> _) { return _.Item1; } internal void <InitButtons>b__8_2() { if (containersUniqueItems != null && intersectedGroups != null) { ItemGroupUtils.MergeAllToSingleGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems); } groupsDialogObj.gameObject.SetActive(false); } internal string <InitButtons>b__8_5(Tuple<string, List<string>> _) { return _.Item1; } internal string <InitMergePromptDlg>b__10_0(Tuple<string, List<string>> _) { return _.Item1; } internal IEnumerable<string> <InitMergePromptDlg>b__10_1(Tuple<string, List<string>> _) { return _.Item2; } internal bool <InitMergePromptDlg>b__10_5(ItemData i) { return intersectedGroups[0].Item2.Contains(i.SCName()); } internal string <InitMergePromptDlg>b__10_6(ItemData _) { return Localization.instance.Localize(_.m_shared.m_name); } internal string <InitMergePromptDlg>b__10_8(Tuple<string, List<string>> _) { return _.Item1; } internal string <InitMergePromptDlg>b__10_3(Tuple<string, List<string>> _) { return _.Item1; } } public static bool initialized = false; private static Transform createGroupButton; private static Transform storeAllButton; public static GameObject groupsDialogObj; private static readonly ICollection<Object> groupSelectorItems = new List<Object>(); private static List<Tuple<string, List<string>>> intersectedGroups; private static List<string> containersUniqueItems; private static void Postfix(InventoryGui __instance) { if (Mod.modEnabled.Value && Mod.groupingEnabled.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !initialized && __instance.IsContainerOpen()) { InitButtons(__instance); } } private static void InitButtons(InventoryGui __instance) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00a5: 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) //IL_00b0: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown if (!Mod.modEnabled.Value) { return; } try { if ((Mod.groupingEnabled.Value || Mod.unloadAllEnabled.Value) && Mod.createGroupBtnEnabled.Value) { AddCreateGroupBtn(__instance); if (Mod.groupingEnabled.Value && Mod.mergePromptEnabled.Value) { object obj = <>c.<>9__8_0; if (obj == null) { UnityAction val = delegate { if (containersUniqueItems != null && intersectedGroups != null) { ItemGroupUtils.ExtendGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems); } groupsDialogObj.gameObject.SetActive(false); }; <>c.<>9__8_0 = val; obj = (object)val; } object obj2 = <>c.<>9__8_1; if (obj2 == null) { UnityAction val2 = delegate { if (containersUniqueItems != null) { ItemGroupUtils.ExtendAndMerge(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems); } groupsDialogObj.gameObject.SetActive(false); }; <>c.<>9__8_1 = val2; obj2 = (object)val2; } object obj3 = <>c.<>9__8_2; if (obj3 == null) { UnityAction val3 = delegate { if (containersUniqueItems != null && intersectedGroups != null) { ItemGroupUtils.MergeAllToSingleGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems); } groupsDialogObj.gameObject.SetActive(false); }; <>c.<>9__8_2 = val3; obj3 = (object)val3; } GuiFactory.CreateMrgDialog(out groupsDialogObj, "mrgToGroupDialog", "Extend", "Extend&Merge", "Merge All", (UnityAction)obj, (UnityAction)obj2, (UnityAction)obj3); } } if (Mod.unloadAllEnabled.Value && !Mod.unloadAllInsteadStackBtn.Value) { AddStoreAllBtn(__instance); } initialized = true; } catch (Exception ex) { Mod.log.LogError((object)("Failed to properly patch GUI with additional buttons: " + ex)); Clean(); } finally { Mod.log.LogInfo((object)"Initialized UI extensions."); } } private static void AddCreateGroupBtn(InventoryGui __instance) { //IL_0021: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown createGroupButton = GuiFactory.AddContainerGuiButton("createGroupBtn", "+æ+", new Vector2(45f, 30f), Mod.createGroupBtnPos.Value); GuiFactory.InitJoyKey(createGroupButton, "JoyMap", "(Гг)"); ((UnityEvent)((Component)createGroupButton).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { //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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance.m_playerGrid == (Object)null) && !((Object)(object)__instance.m_containerGrid == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting()) { Inventory inventory = __instance.m_containerGrid.GetInventory(); KeyboardShortcut value; if (Mod.unloadAllEnabled.Value) { value = Mod.unloadAllItemsGroupKeyModifier.Value; if (((KeyboardShortcut)(ref value)).IsPressed() || ZInput.GetButton("JoyRTrigger")) { UnloadItems.AddToUnloadAllItemsFilter(inventory); return; } } if (Mod.unloadAllEnabled.Value) { value = Mod.unloadAllSkipItemsGroupKeyModifier.Value; if (((KeyboardShortcut)(ref value)).IsPressed() || ZInput.GetButton("JoyLTrigger")) { UnloadItems.AddToUnloadAllItemsSkipList(inventory); return; } } if (Mod.groupingEnabled.Value) { containersUniqueItems = ItemGroupUtils.ExtractUniqueItemNames(inventory); if (containersUniqueItems.Count >= 2) { if (Mod.mergePromptEnabled.Value) { InitMergePromptDlg(inventory); } else { ItemGroupUtils.RegisterNewGroup(inventory); } } } } }); } private static void InitMergePromptDlg(Inventory inventory) { //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Expected O, but got Unknown //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Expected O, but got Unknown intersectedGroups = ItemGroupUtils.FindIntersections(containersUniqueItems); if (!intersectedGroups.Any()) { ItemGroupUtils.RegisterNewGroup(inventory); return; } List<string> second = intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(); HashSet<string> intersectedItemNames = intersectedGroups.FlatMap((Tuple<string, List<string>> _) => _.Item2).ToHashSet(); List<string> nonGroupedItems = containersUniqueItems.Filter((string _) => !intersectedItemNames.Contains(_)).ToList(); TextMeshProUGUI component = ((Component)groupsDialogObj.transform.Find("win_bkg/TextArea/ScrollArea/Content/Name")).GetComponent<TextMeshProUGUI>(); TextMeshProUGUI component2 = ((Component)groupsDialogObj.transform.Find("win_bkg/TextArea/ScrollArea/Content/Description")).GetComponent<TextMeshProUGUI>(); if (intersectedGroups.Count == 1) { if (!nonGroupedItems.Any()) { ((Character)Player.m_localPlayer).Message((MessageType)2, "Group " + intersectedGroups[0].Item1 + " already contains these items", 0, (Sprite)null); return; } List<string> list = inventory.m_inventory.Filter((ItemData i) => intersectedGroups[0].Item2.Contains(i.SCName())).Map((ItemData _) => Localization.instance.Localize(_.m_shared.m_name)).Distinct() .ToList(); ((TMP_Text)component).text = string.Join(",", list.Take(3)) + " " + ((list.Count > 3) ? "and others " : "") + ((list.Count > 1) ? "are already members" : "is already a member") + $" of an existing group of {ItemGroups.Groups[intersectedGroups[0].Item1].Count} items. "; } else { ((TMP_Text)component).text = $"Items from {intersectedGroups.Count} different groups are already presented in this container."; } ((TMP_Text)component2).text = " Please review info bellow, select target-group & action.\n You can: \n • <color=#FFA13CB7>'Extend'</color>: add previously non-grouped items \n(colored in <color=green>green</color>) to a selected target-group.\n"; ((TMP_Text)component2).text = ((TMP_Text)component2).text + " • <color=#FFA13CB7>'Extend & merge'</color>: add all items from this container to a selected target-group. All conflicting items (colored in <color=red>red</color>) would be removed from their current groups.\n"; ((TMP_Text)component2).text = ((TMP_Text)component2).text + " • <color=#FFA13CB7>'Merge all'</color>: (Not recommended) move all items (from this container) & all conflicting group items to a target group.All members of all listed bellow groups will be moved to a target group. \n<color=grey>(target-group could be a new or an existing group)</color>\n"; List<string> list2 = UnloadItems.unloadAllGroupsList.Intersect(second).ToList(); if (Mod.unloadAllEnabled.Value && list2.Any()) { ((TMP_Text)component2).text = ((TMP_Text)component2).text + " \n<color=orange> ! Please note that groups [" + string.Join(",", list2) + "] are used for 'Unloading' filtering. Changing them will affect it's behaviour.</color>\n"; } ((TMP_Text)component2).text = ((TMP_Text)component2).text + "\n Items in the container: " + GeneralExtensions.Join<string>(containersUniqueItems.Map((string itemName) => "<color=" + (nonGroupedItems.Contains(itemName) ? "green" : "red") + ">" + itemName + "</color>"), (Func<string, string>)null, ",") + ".\n"; ((TMP_Text)component2).text = ((TMP_Text)component2).text + "\n Detected groups: \n"; ((TMP_Text)component2).text = ((TMP_Text)component2).text + GeneralExtensions.Join<string>(intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).Map(delegate(string gKey) { IEnumerable<string> values = ItemGroups.Groups[gKey].Map((string _) => (!intersectedItemNames.Contains(_)) ? _ : ("<color=red>" + _ + "</color>")); return "<color=yellow>" + gKey + "</color>: [" + string.Join(", ", values) + "] \n"; }), (Func<string, string>)null, ""); RectTransform selectorBtn = (RectTransform)groupsDialogObj.transform.Find("win_bkg/TextArea/Selector"); RectTransform val = (RectTransform)groupsDialogObj.transform.Find("win_bkg/SelectorDlg/Recipes/ListRoot"); List<string> names = intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).Prepend("--new Group--").ToList(); GuiFactory.FillResList(val, names, groupSelectorItems, delegate(string selection) { ((TMP_Text)((Component)selectorBtn).GetComponentInChildren<TextMeshProUGUI>()).text = selection; ((Component)groupsDialogObj.transform.Find("win_bkg/SelectorDlg")).gameObject.SetActive(false); }); ((TMP_Text)((Component)selectorBtn).GetComponentInChildren<TextMeshProUGUI>()).text = ((intersectedGroups.Count == 1) ? intersectedGroups[0].Item1 : "--new Group--"); ((Component)groupsDialogObj.transform.Find("win_bkg/SelectorDlg/RecipeScroll")).GetComponent<Scrollbar>().value = 1f; ((Component)groupsDialogObj.transform.Find("win_bkg/SelectorDlg")).gameObject.SetActive(false); groupsDialogObj.SetActive(true); } private static string SelectedTargetGroupId() { return ((TMP_Text)((Component)groupsDialogObj.transform.Find("win_bkg/TextArea/Selector")).GetComponentInChildren<TextMeshProUGUI>()).text; } private static void AddStoreAllBtn(InventoryGui __instance) { //IL_0021: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown storeAllButton = GuiFactory.AddContainerGuiButton("storeAllButton", "\\||/", new Vector2(45f, 36f), Mod.unloadAllBtnPos.Value); GuiFactory.InitJoyKey(storeAllButton, "JoyMenu", "(≡)"); ((UnityEvent)((Component)storeAllButton).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { if (!((Object)(object)__instance.m_playerGrid == (Object)null) && !((Object)(object)__instance.m_containerGrid == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting()) { UnloadItems.UnloadAllItems(((Humanoid)Player.m_localPlayer).GetInventory()); } }); } public static void Init() { if ((Object)(object)InventoryGui.instance != (Object)null) { InitButtons(InventoryGui.instance); } } public static void Clean() { if ((Object)(object)createGroupButton != (Object)null) { Object.Destroy((Object)(object)((Component)createGroupButton).gameObject); } if ((Object)(object)storeAllButton != (Object)null) { Object.Destroy((Object)(object)((Component)storeAllButton).gameObject); } if ((Object)(object)groupsDialogObj != (Object)null) { Object.Destroy((Object)(object)groupsDialogObj); } initialized = false; Mod.log.LogInfo((object)"Cleaned up UI extensions."); } } [HarmonyPatch(typeof(Game), "Start")] public static class Game_Start_Patch { private static void Postfix(Game __instance) { Gui_Patch.Clean(); } } [HarmonyPatch(typeof(InventoryGui), "Hide")] public static class Gui_Hide_Patch { private static void Postfix(InventoryGui __instance) { if (Gui_Patch.initialized) { GameObject groupsDialogObj = Gui_Patch.groupsDialogObj; if (groupsDialogObj != null) { groupsDialogObj.SetActive(false); } } } } public static class ItemGroups { private static ICollection<string> prefixItemGroups = new HashSet<string>(); private static ICollection<string> postfixItemGroups = new HashSet<string>(); public static readonly IDictionary<string, ISet<string>> Groups = new Dictionary<string, ISet<string>>(); public static void ParseConfig() { foreach (KeyValuePair<ConfigDefinition, string> item in Mod.ConfigOrphanedEntries().ToList()) { if (item.Key.Section.Equals("ItemGroup")) { Mod.config.Bind<string>(item.Key.Section, item.Key.Key, item.Value.ToLower().Replace("_", ""), Mod.groupDescr("user-added items-group based on item-names list")); } } ConfigEntry<string> val = default(ConfigEntry<string>); if (Mod.config.TryGetEntry<string>("PrefixedItemGroups", "prefixes", ref val) && val.Value.Length > 0) { prefixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(val); Mod.log.LogInfo((object)string.Format("parsed PrefixedItemGroups : [{0}] ({1})", string.Join(",", prefixItemGroups), prefixItemGroups.Count)); } ConfigEntry<string> val2 = default(ConfigEntry<string>); if (Mod.config.TryGetEntry<string>("PostfixedItemGroups", "posfixes", ref val2) && val2.Value.Length > 0) { postfixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(val2); Mod.log.LogInfo((object)string.Format("parsed PostfixedItemGroups: [{0}] ({1})", string.Join(",", postfixItemGroups), postfixItemGroups.Count)); } ConfigEntry<string> val3 = default(ConfigEntry<string>); foreach (ConfigDefinition item2 in from itemKey in Mod.config.Keys where itemKey.Section.Equals("ItemGroup") select itemKey into _ orderby _.Key select _) { if (Mod.config.TryGetEntry<string>(item2.Section, item2.Key, ref val3) && val3.Value.Length > 0) { ISet<string> set = ItemGroupUtils.ParseGroupConfigEntry(val3); Groups.Add(item2.Key, set); Mod.log.LogInfo((object)string.Format("parsed items group '{0}': [{1}] ({2})", item2.Key, string.Join(",", set), set.Count)); } } } public static string FindMatchingUserGroup(Container container, ItemData item) { if (item.m_shared.m_name.Length < 7) { Mod.log.LogWarning((object)("Cant process Unexpected Item " + item.m_shared.m_name)); return null; } ICollection<string> collection = FindMatchingGroups(container, item.SCName(), item, Groups.Keys.Except(Mod.systemGroupKeys).ToList()); if (collection.Count > 1) { Mod.log.LogWarning((object)("Ambiguous item-groups [" + string.Join(",", collection) + "] found for " + ((Object)item.m_dropPrefab).name + " item in single container.")); } if (!collection.Any()) { return null; } return collection.Max((string _) => _); } public static bool ContainerHasSame_SystemGroupItems(Container container, ItemData item) { if (item.m_shared.m_name.Length < 7) { Mod.log.LogWarning((object)("Cant process Unexpected Item " + item.m_shared.m_name)); return false; } return TestConfiguredGroups(container, item.SCName(), item, Mod.systemGroupKeys); } public static bool ContainerHasSame_NamePatternItems(Container container, ItemData item) { if (item.m_shared.m_name.Length < 7) { Mod.log.LogWarning((object)("Cant process Unexpected Item " + item.m_shared.m_name)); return false; } string shortItemName = item.SCName(); if (!TestItemNamePrefix(container, shortItemName, item)) { return TestItemNamePostfix(container, shortItemName, item); } return true; } public static bool ContainerHasSameItemType(Container container, ItemData item) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) if (item.m_shared.m_name.Length < 7) { return false; } ItemType itemType = item.m_shared.m_itemType; string shortItemName = item.SCName(); int num; if ((!IsTrophie(itemType) || !HaveMatchingItem(container, (ItemData _) => IsTrophie(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))) && (!IsTool(itemType) || !HaveMatchingItem(container, (ItemData _) => IsTool(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))) && (!IsAmmo(itemType) || !HaveMatchingItem(container, (ItemData _) => IsAmmo(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))) && (!IsArmor(itemType) || !HaveMatchingItem(container, (ItemData _) => IsArmor(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName)))) { if (IsWeapon(itemType)) { num = (HaveMatchingItem(container, (ItemData _) => IsWeapon(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName)) ? 1 : 0); if (num != 0) { goto IL_00c6; } } else { num = 0; } goto IL_00ff; } num = 1; goto IL_00c6; IL_00ff: return (byte)num != 0; IL_00c6: Console.instance.Print($"{Localization.instance.Localize(item.m_shared.m_name)} routed because target container has same item type {item.m_shared.m_itemType}"); goto IL_00ff; } public static bool ContainerHasSimilarGroupItems(Container container, ItemData item) { //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_0043: 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) if (item.m_shared.m_name.Length < 7) { return false; } string shortItemName = item.m_shared.m_name.SCName(); ItemType itemType = item.m_shared.m_itemType; int num; if ((int)itemType != 0) { num = (HaveMatchingItem(container, (ItemData _) => _.m_shared.m_itemType == itemType && !_.SCName().Equals(shortItemName)) ? 1 : 0); if (num != 0) { Console.instance.Print($"{Localization.instance.Localize(item.m_shared.m_name)} routed because target container has same item type (fuzzy) {item.m_shared.m_itemType}"); } } else { num = 0; } return (byte)num != 0; } private static bool TestItemNamePrefix(Container container, string shortItemName, ItemData item) { foreach (string prefix in prefixItemGroups) { if (shortItemName.StartsWith(prefix) && HaveMatchingItem(container, (ItemData _) => _.m_shared.m_name.StartsWith("$item_" + prefix) && !_.SCName().Equals(shortItemName))) { Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item with Prefix " + prefix); return true; } } return false; } private static bool TestItemNamePostfix(Container container, string shortItemName, ItemData item) { foreach (string postfix in postfixItemGroups) { if (shortItemName.EndsWith(postfix) && HaveMatchingItem(container, (ItemData _) => _.m_shared.m_name.EndsWith(postfix) && !_.SCName().Equals(shortItemName))) { Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item with Postfix " + postfix); return true; } } return false; } private static bool TestConfiguredGroups(Container container, string shortItemName, ItemData item, ICollection<string> grKeys = null) { foreach (string item2 in grKeys ?? Groups.Keys) { if (Groups.ContainsKey(item2)) { ISet<string> set = Groups[item2]; if (TestGroup(shortItemName, container, set)) { Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item from group " + item2 + " : [" + string.Join(",", set) + "]"); return true; } } } return false; } private static ICollection<string> FindMatchingGroups(Container container, string shortItemName, ItemData item, ICollection<string> grKeys = null) { ICollection<string> obj = grKeys ?? Groups.Keys; List<string> list = new List<string>(); foreach (string item2 in obj) { if (Groups.ContainsKey(item2)) { ISet<string> group = Groups[item2]; if (TestGroup(shortItemName, container, group)) { list.Add(item2); } } } return list; } private static bool TestGroup(string shortItemName, Container container, ICollection<string> group) { if (group.Contains(shortItemName)) { foreach (string iname in group) { if (!iname.Equals(shortItemName) && HaveMatchingItem(container, (ItemData _) => _.SCName().Equals(iname))) { return true; } } } return false; } private static bool HaveMatchingItem(Container container, Func<ItemData, bool> predicate) { foreach (ItemData item in container.GetInventory().m_inventory) { if (predicate(item)) { return true; } } return false; } private static bool IsArmor(ItemType _) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 if ((int)_ != 6 && (int)_ != 7 && (int)_ != 11 && (int)_ != 17) { return (int)_ == 18; } return true; } private static bool IsWeapon(ItemType _) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 if ((int)_ != 3 && (int)_ != 4 && (int)_ != 14) { return (int)_ == 5; } return true; } private static bool IsTrophie(ItemType _) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 return (int)_ == 13; } private static bool IsTool(ItemType _) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 return (int)_ == 19; } private static bool IsAmmo(ItemType _) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 return (int)_ == 9; } public static void Clear() { prefixItemGroups.Clear(); postfixItemGroups.Clear(); Groups.Clear(); } } public static class ItemGroupUtils { private static readonly Predicate<string> IsItemSupported = (string itemName) => itemName.StartsWith("$item_") || itemName.StartsWith("$mod_"); public static void RegisterNewGroup(Inventory inventory) { List<string> list = ExtractUniqueItemNames(inventory); if (list.Count > 1) { RegisterNewGroup((ICollection<string>)list); } } public static void RegisterNewGroup(ICollection<string> names) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown if (!names.Any()) { ((Character)Player.m_localPlayer).Message((MessageType)2, "No new items to create a group from.", 0, (Sprite)null); return; } Mod.ignoreUpdate = true; ConfigDefinition val = new ConfigDefinition("ItemGroup", "userGroup" + DateTimeOffset.UtcNow.ToUnixTimeSeconds()); Mod.config.Bind<string>(val, string.Join(",", names), Mod.groupDescr("user-added items-group based on item-names list")); ConfigEntry<string> val2 = default(ConfigEntry<string>); if (Mod.config.TryGetEntry<string>(val, ref val2) && val2.Value.Length > 0) { ISet<string> set = ParseGroupConfigEntry(val2); ItemGroups.Groups.Add(val.Key, set); ManualLogSource log = Mod.log; if (log != null) { log.LogInfo((object)string.Format("parsed items group '{0}': [{1}] ({2})", val.Key, string.Join(",", set), set.Count)); } NotifyPlayer(set.Count, "Registered new group of {0} items."); } } public static void MergeAllToSingleGroup(string targetGroupId, List<string> groupIds, List<string> newItems) { HashSet<string> hashSet = groupIds.Filter((string _) => !_.Equals(targetGroupId)).FlatMap((string _) => ItemGroups.Groups[_]).ToList() .Concat(newItems) .ToHashSet(); if (!ItemGroups.Groups.ContainsKey(targetGroupId)) { RegisterNewGroup((ICollection<string>)hashSet); } else { hashSet = hashSet.Except(ItemGroups.Groups[targetGroupId]).ToHashSet(); if (!hashSet.Any()) { ((Character)Player.m_localPlayer).Message((MessageType)2, "Existing group already contained all items", 0, (Sprite)null); } else { AddToItemsGroup(targetGroupId, hashSet); NotifyPlayer(hashSet.Count, "Added {0} new items to existing group."); } } foreach (string item in groupIds.Filter((string _) => !_.Equals(targetGroupId))) { Mod.log.LogInfo((object)("flattened group : " + item)); ClearItemsGroup(item); } } public static void ExtendGroup(string targetGroupId, List<string> groupIds, List<string> newItems) { List<string> second = groupIds.FlatMap((string _) => ItemGroups.Groups[_]).Intersect(newItems).ToList(); HashSet<string> hashSet = newItems.Except(second).ToHashSet(); if (!ItemGroups.Groups.ContainsKey(targetGroupId)) { RegisterNewGroup((ICollection<string>)hashSet); return; } if (!hashSet.Any()) { ((Character)Player.m_localPlayer).Message((MessageType)2, "Existing group already contained all items", 0, (Sprite)null); return; } AddToItemsGroup(targetGroupId, hashSet); NotifyPlayer(hashSet.Count, "Added {0} new items to existing group."); } public static void ExtendAndMerge(string targetGroupId, List<string> groupIds, List<string> newItems) { foreach (string item in groupIds.Filter((string _) => !_.Equals(targetGroupId))) { List<string> items = newItems.Intersect(ItemGroups.Groups[item]).ToList(); RemoveFromItemsGroup(item, items); } if (!ItemGroups.Groups.ContainsKey(targetGroupId)) { RegisterNewGroup((ICollection<string>)newItems); return; } HashSet<string> hashSet = newItems.Except(ItemGroups.Groups[targetGroupId]).ToHashSet(); if (!hashSet.Any()) { ((Character)Player.m_localPlayer).Message((MessageType)2, "Existing group already contained all items", 0, (Sprite)null); return; } AddToItemsGroup(targetGroupId, hashSet); NotifyPlayer(hashSet.Count, "Added {0} new items to existing group."); } public static ConfigEntry<string> AddToItemListConfig(ICollection<string> names, ISet<string> targetSet, ConfigEntry<string> configEntry, string uiMessage) { foreach (string name in names) { targetSet.Add(name); } Mod.ignoreUpdate = true; configEntry.Value = string.Join(",", targetSet); NotifyPlayer(names.Count, uiMessage); return configEntry; } private static void NotifyPlayer(int count, string uiMessage) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_004a: Unknown result type (might be due to invalid IL or missing references) ((Character)Player.m_localPlayer).Message((MessageType)2, string.Format(uiMessage, count), 0, (Sprite)null); if (Mod.effectFeedbackEnabled.Value) { Vector3 position = ((Component)InventoryGui.instance.m_currentContainer).gameObject.transform.position; Player.m_localPlayer.m_skillLevelupEffects.Create(position, Quaternion.identity, (Transform)null, 1f, -1); } } public static List<Tuple<string, List<string>>> FindIntersections(List<string> names) { List<Tuple<string, List<string>>> list = new List<Tuple<string, List<string>>>(); foreach (string item in ItemGroups.Groups.Keys.ToList()) { List<string> list2 = ItemGroups.Groups[item].Intersect(names).ToList(); if (list2.Any()) { list.Add(new Tuple<string, List<string>>(item, list2)); } } return list.OrderByDescending((Tuple<string, List<string>> tt) => tt.Item2.Count).ToList(); } public static List<string> ExtractUniqueItemNames(Inventory inventory) { foreach (string item in inventory.m_inventory.Map((ItemData invi) => invi.m_shared.m_name).Filter((string _) => !IsItemSupported(_)).ToList()) { Mod.log.LogWarning((object)("Unsupported item name " + item)); } return inventory.m_inventory.Map((ItemData invi) => invi.m_shared.m_name).Filter((string _) => IsItemSupported(_)).Distinct() .Map((string _) => _.SCName()) .ToList(); } public static ISet<string> ParseGroupConfigEntry(ConfigEntry<string> configEntry) { return new HashSet<string>(configEntry.Value.Split(new char[1] { ',' }).Map((string _) => _.SCName().Replace(" ", ""))); } private static void AddToItemsGroup(string groupId, ICollection<string> items) { foreach (string item in items) { ItemGroups.Groups[groupId].Add(item); } SaveItemsGroup(groupId, ItemGroups.Groups[groupId]); } private static void RemoveFromItemsGroup(string groupId, ICollection<string> items) { foreach (string item in items) { ItemGroups.Groups[groupId].Remove(item); } SaveItemsGroup(groupId, ItemGroups.Groups[groupId]); } private static void ClearItemsGroup(string flattenedGroupId) { ItemGroups.Groups[flattenedGroupId].Clear(); SaveItemsGroup(flattenedGroupId, ItemGroups.Groups[flattenedGroupId]); } private static void SaveItemsGroup(string groupId, ICollection<string> groupItems) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown ConfigEntry<string> val = default(ConfigEntry<string>); if (Mod.config.TryGetEntry<string>(new ConfigDefinition("ItemGroup", groupId), ref val)) { Mod.ignoreUpdate = true; val.Value = string.Join(",", groupItems); } } } [BepInPlugin("flueno.SmartContainers", "Smart Containers Mod", "1.7.0")] public class Mod : BaseUnityPlugin { internal readonly Harmony harmony; internal readonly Assembly assembly; public static ManualLogSource log; public static ConfigFile config; public static ConfigEntry<bool> modEnabled; public static ConfigEntry<bool> groupingEnabled; public static ConfigEntry<bool> itemTypeGroupsEnabled; public static ConfigEntry<bool> fuzzyGroupingEnabled; public static ConfigEntry<bool> onlyStackableItems; public static ConfigEntry<ConcurrentChestModificationWorkaround> concurrencyWorkaround; public static ConfigEntry<bool> hudMessageEnabled; public static ConfigEntry<bool> audioFeedbackEnabled; public static ConfigEntry<bool> effectFeedbackEnabled; public static ConfigEntry<string> hudMessageText; public static ConfigEntry<int> range; public static ConfigEntry<KeyboardShortcut> keyModifier; public static ConfigEntry<string> gamepadKey1; public static ConfigEntry<KeyboardShortcut> gamepadKey2; public static ConfigEntry<KeyboardShortcut> groupingKeyModifier; public static ConfigEntry<bool> createGroupBtnEnabled; public static ConfigEntry<bool> mergePromptEnabled; public static ConfigEntry<Vector2> createGroupBtnPos; public static ConfigEntry<bool> unloadAllEnabled; public static ConfigEntry<bool> unloadAllInsteadStackBtn; public static ConfigEntry<Vector2> unloadAllBtnPos; public static ConfigEntry<KeyboardShortcut> unloadAllItemsGroupKeyModifier; public static ConfigEntry<KeyboardShortcut> unloadAllSkipItemsGroupKeyModifier; public static ConfigEntry<bool> unloadForceGrouping; public static ConfigEntry<string> unloadAllItemsList; public static ConfigEntry<string> unloadAllSkipList; public static ConfigEntry<string> unloadAllGroupsList; public static ConfigEntry<string> unloadAllPrefixItemGroups; public static ConfigEntry<string> unloadAllPostfixItemGroups; public static ConfigEntry<bool> unloadAllMaterialsFiltering; public static ConfigEntry<bool> unloadAllTrophiesFiltering; public static ConfigEntry<bool> unloadAllConsumableFiltering; public static bool ignoreUpdate = false; public static readonly ICollection<string> systemGroupKeys = new HashSet<string> { "valuables", "ore", "rock", "ingots", "wood", "mushrooms", "berries", "vegetables", "cookedMeat", "food" }; public Mod() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown harmony = new Harmony("flueno.SmartContainers"); assembly = Assembly.GetExecutingAssembly(); config = ((BaseUnityPlugin)this).Config; log = ((BaseUnityPlugin)this).Logger; } public void Start() { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_04d3: Unknown result type (might be due to invalid IL or missing references) //IL_04fd: Unknown result type (might be due to invalid IL or missing references) //IL_054b: Unknown result type (might be due to invalid IL or missing references) ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 332, "Nexus mod ID"); modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "enabled", true, "Enables this mod"); MigrateConfig(ConfigOrphanedEntries()); onlyStackableItems = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "onlyStackableItems", true, "Rearranges only stackable items"); hudMessageEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "hudMessageEnabled", true, "Enables hud message indicating that item was routed & placed to some other chest"); hudMessageText = ((BaseUnityPlugin)this).Config.Bind<string>("General", "hudMessageText", "Routed to another Chest", "HUD message consists of Icon, item-name plus this text."); range = ((BaseUnityPlugin)this).Config.Bind<int>("General", "range", 14, new ConfigDescription("Range within which containers will participate in resources arrangement.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 99), Array.Empty<object>())); keyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "hkeyModifier", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), "Change only if you wish to have even longer than ctrl+click combination (holding ctrl is mandatory since it's a 'move-stack' ingame key)"); gamepadKey1 = ((BaseUnityPlugin)this).Config.Bind<string>("General", "gamepadKey1", "JoyLTrigger", "first part of gamepads transfer-item key-combo"); gamepadKey2 = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "gamepadKey2", new KeyboardShortcut((KeyCode)332, Array.Empty<KeyCode>()), "second part of gamepads transfer-item key-combo"); audioFeedbackEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "audioFeedbackEnabled", true, "Enables playing of sound on successful items transfer"); effectFeedbackEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "effectFeedbackEnabled", true, "Enables highlighting of end-target chests where items have been transferred."); concurrencyWorkaround = ((BaseUnityPlugin)this).Config.Bind<ConcurrentChestModificationWorkaround>("General", "concurrentChestModificationWorkaround", ConcurrentChestModificationWorkaround.ExcludeContainersOpenedByOthers, "There are rare possibility of items loss if two players simultaneously (within a ~second) modify same containers inventory. Options are: ignore possible issue; ignore 'opened' chests; block mod if any other nearby player opened a chest"); groupingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "enabled", true, "Enables distributing items to containers with 'same-kinded' items (used if no nearby containers contain 'same item')"); itemTypeGroupsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "itemTypeGroupsEnabled", true, "Enable grouping by item-types (Trophie, Tool, Ammo, Armor, Weapon)."); fuzzyGroupingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "fuzzyGroupingEnabled", false, "Enable grouping by more broad criteria."); groupingKeyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Grouping", "groupingKeyModifier", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), " Change to 'LeftControl + LeftShift' if you want to trigger grouping with a separate hotkey (ctrl+shift+click)(holding ctrl is mandatory since it's a 'move-stack' ingame key)"); createGroupBtnEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "createGroupBtnEnabled", true, "Adds to the chest UI button [☼] which creates items-group based on the current items set in the chest."); mergePromptEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "mergePromptEnabled", true, "In case when createGroupBtn clicked and chest already contains some members of one ore more groups - dialog showed with option to merge items & groups into a single group."); createGroupBtnPos = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Grouping", "createGroupBtnPos", new Vector2(1.5f, 10.7f), "Adjusts btn position on inventory ui. →x:1.5..-10 ↓y:0.4..10.7 bottom-left: (1.5f, 10.7f) top-right:(-10f, 0.4f) bottom-right:(-10f, 10.7f)"); ((BaseUnityPlugin)this).Config.Bind<string>("PrefixedItemGroups", "prefixes", "trophy,mead,arrow,armor,cape,helmet,atgeir,bow,battleaxe,knife,mace,shield,sledge,spear,sword,tankard,club,mushroom,arrow", groupDescr("If both item names start with same 'prefix' - they are considered to have same group. I.e. arrowFire & arrowFlint")); ((BaseUnityPlugin)this).Config.Bind<string>("PostfixedItemGroups", "posfixes", "cone,seeds,pelt,hide,berries", groupDescr("If both item names end with same 'postfix' - they are considered to have same group. I.e. carrotSeeds & turnipSeeds")); ((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "valuables", "ruby,coins,amber,amberpearl", groupDescr()); ((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "ore", "copperore,flametalore,ironore,silverore,tinore,ironscrap,blackmetalscrap", groupDescr()); ((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "rock", "stone,flint,obsidian", groupDescr()); ((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "ingots", "copper,bronze,flametal,iron,silver,tin,blackmetal", groupDescr()); ((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "wood", "wood,finewood,corewood,elderbark,roundlog", groupDescr()); ((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "mushrooms", "Mushroom,MushroomBlue,MushroomYellow,mushroomcommon", groupDescr()); ((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "berries", "Blueberries,raspberries,cloudberries,honey", groupDescr()); ((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "vegetables", "Carrot,Turnip", groupDescr()); ((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "cookedMeat", "CookedLoxMeat,NeckTailGrilled,MeatCooked,FishCooked,SerpentMeatCooked", groupDescr()); ((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "food", "CarrotSoup,Sausages,QueensJam,SerpentStew,TurnipStew,BloodPudding", groupDescr()); unloadAllEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "enabled", false, "Enables Unload-all option & UI button [\\||/]. Allows to batch-unload all eligible items from players inventory to their corresponding stacks & groups in nearby chests."); unloadAllInsteadStackBtn = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "nativeButton", false, "Use existing 'place-stacks' UI button for unloading. If disabled - new UI button [\\||/] will be created."); unloadAllBtnPos = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Unload", "btnPos", new Vector2(1.5f, 8.15f), (ConfigDescription)null); unloadAllItemsGroupKeyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Unload", "addToItemsFilterKeyModifier", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), "If pressed - overrides createGroupBtn behaviour by passing item-names to unload 'itemsList' instead of creating new items group"); unloadForceGrouping = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "alwaysGrouping", true, "If enabled - check for groupingKeyModifier pressed is ignored for 'unload' button"); unloadAllSkipItemsGroupKeyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Unload", "addToSkipItemsFilterKeyModifier", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), "If pressed - overrides createGroupBtn behaviour by passing item-names to unload 'itemsSkipList' instead of creating new items group"); unloadAllItemsList = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "itemsList", "", groupDescr("List of item-names allowed to be 'unloaded'")); unloadAllSkipList = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "itemsSkipList", "", groupDescr("List of item-names to exclude from being 'unloaded'")); unloadAllGroupsList = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "groupsList", "valuables,ore,wood,mushrooms", "List of items group-ids from [ItemGroup] config section allowed to be 'unloaded'"); unloadAllPrefixItemGroups = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "prefixItemGroups", "trophy", (ConfigDescription)null); unloadAllPostfixItemGroups = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "postfixItemGroups", "seeds", (ConfigDescription)null); unloadAllMaterialsFiltering = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "materialsFiltering", true, "allow all Materials to be 'unloaded'"); unloadAllTrophiesFiltering = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "trophiesFiltering", true, "allow all Trophies to be 'unloaded'"); unloadAllConsumableFiltering = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "consumableFiltering", false, "allow all Consumables to be 'unloaded'"); if (modEnabled.Value) { ItemGroups.ParseConfig(); UnloadItems.ParseConfig(); ContainersTracker.Init(); Gui_Patch.Init(); ((BaseUnityPlugin)this).Config.SettingChanged += HandleConfigUpdate; harmony.PatchAll(assembly); } } public static ConfigDescription groupDescr(string descr = "Items-group based on item-names list") { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown return new ConfigDescription(descr, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = TextAreaDrawer } }); } private static void TextAreaDrawer(ConfigEntryBase entry) { GUILayout.ExpandHeight(true); GUILayout.ExpandWidth(true); entry.BoxedValue = GUILayout.TextArea((string)entry.BoxedValue, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true) }); } private void HandleConfigUpdate(object sender, SettingChangedEventArgs e) { if (ignoreUpdate) { ignoreUpdate = false; log.LogInfo((object)$"SettingChangedEventArgs (ignored) {e.ChangedSetting.Definition}"); return; } Gui_Patch.Clean(); Gui_Patch.Init(); ItemGroups.Clear(); ItemGroups.ParseConfig(); UnloadItems.Clear(); UnloadItems.ParseConfig(); } private void OnDestroy() { harmony.UnpatchSelf(); ((BaseUnityPlugin)this).Config.Reload(); Gui_Patch.Clean(); ItemGroups.Clear(); UnloadItems.Clear(); ContainersTracker.containerList.Clear(); } public static bool isSystemGroup(string groupId) { return systemGroupKeys.Contains(groupId); } public static void PlayEffect(bool allowed, string prefabName, Vector3 pos) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (allowed) { GameObject prefab = ZNetScene.instance.GetPrefab(prefabName); if ((Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity); } else { log.LogWarning((object)("Failed to locate FeedbackEffect " + prefabName + " prefab")); } } } public static Dictionary<ConfigDefinition, string> ConfigOrphanedEntries() { return Traverse.Create((object)config).Property("OrphanedEntries", (object[])null).GetValue<Dictionary<ConfigDefinition, string>>(); } private static void MigrateConfig(Dictionary<ConfigDefinition, string> orphans) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0038: 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: Expected O, but got Unknown //IL_0051: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0075: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_0099: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_00bd: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_00e1: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (orphans.ContainsKey(new ConfigDefinition("ItemGroup", "coockedMeat"))) { orphans.Remove(new ConfigDefinition("ItemGroup", "coockedMeat")); } ChangeKey<bool>(orphans, new ConfigDefinition("General", "groupingEnabled"), new ConfigDefinition("Grouping", "enabled")); ChangeKey<bool>(orphans, new ConfigDefinition("General", "itemTypeGroupsEnabled"), new ConfigDefinition("Grouping", "itemTypeGroupsEnabled")); ChangeKey<bool>(orphans, new ConfigDefinition("General", "fuzzyGroupingEnabled"), new ConfigDefinition("Grouping", "fuzzyGroupingEnabled")); ChangeKey<bool>(orphans, new ConfigDefinition("General", "createGroupBtnEnabled"), new ConfigDefinition("Grouping", "createGroupBtnEnabled")); ChangeKey<Vector2>(orphans, new ConfigDefinition("General", "createGroupBtnPos"), new ConfigDefinition("Grouping", "createGroupBtnPos")); } private static void ChangeKey<T>(Dictionary<ConfigDefinition, string> orphans, ConfigDefinition dkey, ConfigDefinition dkeyNew) { if (orphans.ContainsKey(dkey)) { orphans.Add(dkeyNew, orphans[dkey]); orphans.Remove(dkey); } } } public enum ConcurrentChestModificationWorkaround { None, ExcludeContainersOpenedByOthers, BlockIfOtherContainersAreOpened } internal static class ConcurrentChestModificationWorkaroundMethods { public static bool SkipOpenedOthers(this ConcurrentChestModificationWorkaround option) { return option == ConcurrentChestModificationWorkaround.ExcludeContainersOpenedByOthers; } public static bool Ignore(this ConcurrentChestModificationWorkaround option) { return option == ConcurrentChestModificationWorkaround.None; } public static bool BlockIfAnyOtherOpened(this ConcurrentChestModificationWorkaround option) { return option == ConcurrentChestModificationWorkaround.BlockIfOtherContainersAreOpened; } } internal static class KeyboardShortcutMethods { public static bool IsPressedOrNone(this KeyboardShortcut shortcut) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 if (!((KeyboardShortcut)(ref shortcut)).IsPressed()) { return (int)((KeyboardShortcut)(ref shortcut)).MainKey == 0; } return true; } public static bool MainPressed(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey); } } internal static class ItemDataMethods { public static string SCName(this string itemName) { return itemName.ToLower().Replace("$item_", "").Replace("_", ""); } public static string SCName(this ItemData itemDrop) { return itemDrop.m_shared.m_name.SCName(); } } internal static class EnumerableMethods { public static IEnumerable<R> Map<T, R>(this IEnumerable<T> self, Func<T, R> selector) { return self.Select(selector); } public static T Reduce<T>(this IEnumerable<T> self, Func<T, T, T> func) { return self.Aggregate(func); } public static T Reduce<T>(this IEnumerable<T> self, T seed, Func<T, T, T> func) { return self.Aggregate(seed, func); } public static IEnumerable<R> FlatMap<T, R>(this IEnumerable<T> self, Func<T, IEnumerable<R>> func) { return self.SelectMany(func); } public static IEnumerable<T> Filter<T>(this IEnumerable<T> self, Func<T, bool> predicate) { return self.Where(predicate); } } public static class UnloadItems { private static ISet<string> unloadAllItemsList = new HashSet<string>(); private static ISet<string> unloadAllItemsSkipList = new HashSet<string>(); public static ICollection<string> unloadAllGroupsList = new HashSet<string>(); private static ICollection<string> unloadAllPrefixItemGroups = new HashSet<string>(); private static ICollection<string> unloadAllPostfixItemGroups = new HashSet<string>(); public static void ParseConfig() { if (Mod.unloadAllPrefixItemGroups.Value.Length > 0) { unloadAllPrefixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllPrefixItemGroups); } if (Mod.unloadAllPostfixItemGroups.Value.Length > 0) { unloadAllPostfixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllPostfixItemGroups); } if (Mod.unloadAllItemsList.Value.Length > 0) { unloadAllItemsList = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllItemsList); } if (Mod.unloadAllSkipList.Value.Length > 0) { unloadAllItemsSkipList = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllSkipList); } if (Mod.unloadAllGroupsList.Value.Length > 0) { unloadAllGroupsList = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllGroupsList); } } public static void UnloadAllItems(Inventory playerInv) { //IL_0127: Unknown result type (might be due to invalid IL or missing references) List<ItemData> list = playerInv.m_inventory.Filter((ItemData i) => !i.m_equipped).Map((ItemData i) => (i, i.m_shared.m_name.SCName())).Filter<(ItemData, string)>(((ItemData i, string) tuple) => !Mod.onlyStackableItems.Value || tuple.i.m_shared.m_maxStackSize > 1) .Filter<(ItemData, string)>(((ItemData i, string) tuple) => !unloadAllItemsSkipList.Contains(tuple.Item2)) .Filter<(ItemData, string)>(((ItemData i, string) tuple) => (Mod.unloadAllMaterialsFiltering.Value && (int)tuple.i.m_shared.m_itemType == 1) || (Mod.unloadAllTrophiesFiltering.Value && (int)tuple.i.m_shared.m_itemType == 13) || (Mod.unloadAllConsumableFiltering.Value && (int)tuple.i.m_shared.m_itemType == 2) || (unloadAllItemsList.Any() && unloadAllItemsList.Contains(tuple.Item2)) || (unloadAllPrefixItemGroups.Any() && TestList((string _) => tuple.Item2.StartsWith(_), unloadAllPrefixItemGroups)) || (unloadAllPostfixItemGroups.Any() && TestList((string _) => tuple.Item2.EndsWith(_), unloadAllPostfixItemGroups)) || (unloadAllGroupsList.Any() && unloadAllGroupsList.Any((string groupId) => TestList((string _) => tuple.Item2.Equals(_), ItemGroups.Groups[groupId])))) .Map<(ItemData, string), ItemData>(((ItemData i, string) tuple) => tuple.i) .ToList(); bool flag = false; foreach (ItemData item in list) { if (Inventory_Patch.TryAddToNearBy(item, allowCurrent: true, Mod.unloadForceGrouping.Value)) { playerInv.RemoveItem(item); if (!flag) { Mod.PlayEffect(Mod.audioFeedbackEnabled.Value, "sfx_lootspawn", ((Character)Player.m_localPlayer).GetCenterPoint()); flag = true; } } } } public static void AddToUnloadAllItemsFilter(Inventory inventory) { Mod.unloadAllItemsList = AddToItemListConfig(inventory, unloadAllItemsList, Mod.unloadAllItemsList, "Added {0} items to unload-items filter"); } public static void AddToUnloadAllItemsSkipList(Inventory inventory) { Mod.unloadAllSkipList = AddToItemListConfig(inventory, unloadAllItemsSkipList, Mod.unloadAllSkipList, "Added {0} items to unload-skip-items list"); } private static ConfigEntry<string> AddToItemListConfig(Inventory inventory, ISet<string> targetSet, ConfigEntry<string> configEntry, string uiMessage) { List<string> list = ItemGroupUtils.ExtractUniqueItemNames(inventory); if (list.Count < 1) { return configEntry; } return ItemGroupUtils.AddToItemListConfig(list, targetSet, configEntry, uiMessage); } private static bool TestList(Func<string, bool> predicate, ICollection<string> group) { foreach (string item in group) { if (predicate(item)) { return true; } } return false; } public static void Clear() { unloadAllItemsList.Clear(); unloadAllItemsSkipList.Clear(); unloadAllGroupsList.Clear(); unloadAllPrefixItemGroups.Clear(); unloadAllPostfixItemGroups.Clear(); } }
Plugins/SpeedyPaths.dll
Decompiled 2 years agousing System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using AuthoritativeConfig; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using SpeedyPaths.Properties; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("SpeedyPaths")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SpeedyPaths")] [assembly: AssemblyTitle("SpeedyPaths")] [assembly: AssemblyVersion("1.0.0.0")] namespace AuthoritativeConfig { public class Config { private static Config _instance; public Dictionary<string, ConfigBaseEntry> _configEntries; public BaseUnityPlugin _mod; private static ConfigEntry<bool> _ServerIsAuthoritative; private static bool _DefaultBindAuthority; public static ManualLogSource Logger; public static Config Instance { get { if (_instance == null) { _instance = new Config(); } return _instance; } set { } } public static ZNet ZNet => ZNet.instance; public static string GUID => Instance._mod.Info.Metadata.GUID; public static string RPC_SYNC_GUID => "AuthoritativeConfig_" + GUID; public void init(BaseUnityPlugin mod, bool defaultBindServerAuthority = false) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown _mod = mod; Logger = new ManualLogSource(RPC_SYNC_GUID); Logger.Sources.Add((ILogSource)(object)Logger); _configEntries = new Dictionary<string, ConfigBaseEntry>(); _DefaultBindAuthority = defaultBindServerAuthority; _ServerIsAuthoritative = _mod.Config.Bind<bool>("ServerAuthoritativeConfig", "ServerIsAuthoritative", true, "<Server Only> Forces Clients to use Server defined configs."); Harmony.CreateAndPatchAll(typeof(Config), (string)null); Logger.LogInfo((object)"Initialized Server Authoritative Config Manager."); } [HarmonyPatch(typeof(Game), "Start")] [HarmonyPostfix] private static void RegisterSyncConfigRPC() { Logger.LogInfo((object)("Authoritative Config Registered -> " + RPC_SYNC_GUID)); ZRoutedRpc.instance.Register<ZPackage>(RPC_SYNC_GUID, (Action<long, ZPackage>)RPC_SyncServerConfig); foreach (ConfigBaseEntry value in Instance._configEntries.Values) { value.ClearServerValue(); } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyPostfix] private static void RequestConfigFromServer() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown if (!ZNet.IsServer() && (int)ZNet.GetConnectionStatus() == 2) { long? num = AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", (Type[])null, (Type[])null).Invoke(ZRoutedRpc.instance, null) as long?; ZRoutedRpc.instance.InvokeRoutedRPC(num.Value, RPC_SYNC_GUID, new object[1] { (object)new ZPackage() }); Logger.LogInfo((object)("Authoritative Config Registered -> " + RPC_SYNC_GUID)); Debug.Log((object)(Instance._mod.Info.Metadata.Name + ": Authoritative Config Requested -> " + RPC_SYNC_GUID)); } else if (!ZNet.IsServer()) { Logger.LogWarning((object)"Failed to Request Configs. Bad Peer? Too Early?"); } } public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, ConfigDescription configDescription = null, bool? serverAuthoritative = null) { ConfigEntry<T> configEntry = new ConfigEntry<T>(_mod.Config.Bind<T>(section, key, defaultValue, configDescription), serverAuthoritative.HasValue ? serverAuthoritative.Value : _DefaultBindAuthority); _configEntries[((object)configEntry.BaseEntry.Definition).ToString()] = configEntry; return configEntry; } public ConfigEntry<T> Bind<T>(ConfigDefinition configDefinition, T defaultValue, ConfigDescription configDescription = null, bool? serverAuthoritative = null) { ConfigEntry<T> configEntry = new ConfigEntry<T>(_mod.Config.Bind<T>(configDefinition, defaultValue, configDescription), serverAuthoritative.HasValue ? serverAuthoritative.Value : _DefaultBindAuthority); _configEntries[((object)configEntry.BaseEntry.Definition).ToString()] = configEntry; return configEntry; } public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description, bool? serverAuthoritative = null) { ConfigEntry<T> configEntry = new ConfigEntry<T>(_mod.Config.Bind<T>(section, key, defaultValue, description), serverAuthoritative.HasValue ? serverAuthoritative.Value : _DefaultBindAuthority); _configEntries[((object)configEntry.BaseEntry.Definition).ToString()] = configEntry; return configEntry; } public static void SendConfigToClient(long sender) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown if (!ZNet.IsServer()) { return; } ZPackage val = new ZPackage(); int num = 0; foreach (KeyValuePair<string, ConfigBaseEntry> configEntry in Instance._configEntries) { if (configEntry.Value.ServerAuthoritative) { val.Write(configEntry.Key); val.Write(configEntry.Value.BaseEntry.GetSerializedValue()); num++; Logger.LogInfo((object)("Sending Config " + configEntry.Key + ": " + configEntry.Value.BaseEntry.GetSerializedValue())); } } ZRoutedRpc.instance.InvokeRoutedRPC(sender, RPC_SYNC_GUID, new object[1] { val }); Logger.LogInfo((object)$"Sent {num} config pairs to client {sender}"); } public static void ReadConfigPkg(ZPackage pkg) { if (ZNet.IsServer()) { return; } int num = 0; while (pkg.GetPos() != pkg.Size()) { string text = pkg.ReadString(); string text2 = pkg.ReadString(); num++; if (Instance._configEntries.ContainsKey(text)) { Instance._configEntries[text].SetSerializedValue(text2); Logger.LogInfo((object)("Applied Server Authoritative config pair => " + text + ": " + text2)); } else { Logger.LogError((object)("Recieved config key we dont have locally. Possible Version Mismatch. " + text + ": " + text2)); } } Logger.LogInfo((object)$"Applied {num} config pairs"); } public static void RPC_SyncServerConfig(long sender, ZPackage pkg) { if (ZNet.IsServer() && _ServerIsAuthoritative.Value) { SendConfigToClient(sender); } else if (!ZNet.IsServer() && pkg != null && pkg.Size() > 0 && AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", (Type[])null, (Type[])null).Invoke(ZRoutedRpc.instance, null) as long? == sender) { ReadConfigPkg(pkg); } } } public class ConfigBaseEntry { protected object _serverValue; public ConfigEntryBase BaseEntry; public bool ServerAuthoritative; protected bool _didError; internal ConfigBaseEntry(ConfigEntryBase configEntry, bool serverAuthoritative) { BaseEntry = configEntry; ServerAuthoritative = serverAuthoritative; } public void SetSerializedValue(string value) { try { _serverValue = TomlTypeConverter.ConvertToValue(value, BaseEntry.SettingType); _didError = false; } catch (Exception ex) { Config.Logger.LogWarning((object)$"Config value of setting \"{BaseEntry.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } } public void ClearServerValue() { _serverValue = null; _didError = false; } } public class ConfigEntry<T> : ConfigBaseEntry { private ConfigEntry<T> _configEntry; public T ServerValue => (T)_serverValue; public T Value { get { if (ServerAuthoritative && !Config.ZNet.IsServer()) { if (_serverValue != null) { return ServerValue; } if (!_didError) { Config.Logger.LogWarning((object)("No Recieved value for Server Authoritative Config. " + ((object)BaseEntry.Definition).ToString() + ". Falling Back to Client Config.")); _didError = true; } return _configEntry.Value; } return _configEntry.Value; } set { _configEntry.Value = value; } } internal ConfigEntry(ConfigEntry<T> configEntry, bool serverAuthoritative) : base((ConfigEntryBase)(object)configEntry, serverAuthoritative) { _configEntry = configEntry; } } } namespace SpeedyPaths { [BepInPlugin("nex.SpeedyPaths", "Speedy Paths Mod", "1.0.8")] public class SpeedyPathsClientMod : BaseUnityPlugin { public enum GroundType { Untamed, PathDirt, PathStone, Cultivated, StructureWood, StructureHardWood, StructureStone, StructureIron, StructureMarble } private static Dictionary<GroundType, ConfigEntry<float>> _speedModifiers = new Dictionary<GroundType, ConfigEntry<float>>(); private static Dictionary<GroundType, ConfigEntry<float>> _staminaModifiers = new Dictionary<GroundType, ConfigEntry<float>>(); private static Dictionary<Biome, ConfigEntry<float>> _untamedSpeedModifiers = new Dictionary<Biome, ConfigEntry<float>>(); private static Dictionary<Biome, ConfigEntry<float>> _untamedStaminaModifiers = new Dictionary<Biome, ConfigEntry<float>>(); private static ConfigEntry<bool> _showHudStatus; private static ConfigEntry<string> _hudStatusText; private static ConfigEntry<bool> _hudDynamicStatusText; private static ConfigEntry<bool> _hudShowEffectPercent; private static List<ConfigEntry<float>> _hudPosIconThresholds = new List<ConfigEntry<float>>(); private static List<ConfigEntry<float>> _hudNegIconThresholds = new List<ConfigEntry<float>>(); private static ConfigEntry<float> _groundSensorUpdateInterval; private static ConfigEntry<int> _groundSensorRadius; private static Dictionary<GroundType, ConfigEntry<string>> _groundTypeStrings = new Dictionary<GroundType, ConfigEntry<string>>(); private static Dictionary<Biome, ConfigEntry<string>> _biomeTypeStrings = new Dictionary<Biome, ConfigEntry<string>>(); private static int m_pieceLayer; private static object[] _worldToVertexArgs = new object[3] { Vector3.zero, null, null }; private static List<Sprite> _speedSprites = new List<Sprite>(); private AssetBundle _speedyassets; private static float m_sensorTime; private static GroundType m_cachedGroundType; public static ManualLogSource Logger; private static float _activeSpeedModifier = 1f; private static float _activeStaminaModifier = 1f; private static string _activeStatusText; private static Sprite _activeStatusSprite; private static StatusEffect _pathBuffSEDummy; private static float _prevModValue = 1f; public Config Config { get { return Config.Instance; } set { } } private void Awake() { //IL_0549: Unknown result type (might be due to invalid IL or missing references) //IL_054e: Unknown result type (might be due to invalid IL or missing references) //IL_0554: Unknown result type (might be due to invalid IL or missing references) //IL_05b5: Unknown result type (might be due to invalid IL or missing references) //IL_0616: Unknown result type (might be due to invalid IL or missing references) Logger = ((BaseUnityPlugin)this).Logger; _speedyassets = AssetBundle.LoadFromMemory(Resources.speedyassets); if (!Object.op_Implicit((Object)(object)_speedyassets)) { Logger.LogError((object)"Failed to read AssetBundle stream"); return; } Config.init((BaseUnityPlugin)(object)this, defaultBindServerAuthority: true); _hudDynamicStatusText = Config.Bind("Hud", "EnableDynamicStatusText", defaultValue: true, "Show surface type text as status effect name", false); _hudShowEffectPercent = Config.Bind("Hud", "ShowStatusEffectPercent", defaultValue: true, "Show the status effect buff/debuff %", false); _showHudStatus = Config.Bind("Hud", "ShowStatusIcon", defaultValue: true, "Show the speedypaths status icon in the hud", false); _hudStatusText = Config.Bind("Hud", "StatusText", "Speedy Path", "Text shown above the status icon", false); _hudPosIconThresholds.Add(Config.Bind("Hud", "BuffIcon +1", 1f, "Speed buff threshold to show lvl 1 buff icon")); _hudPosIconThresholds.Add(Config.Bind("Hud", "BuffIcon +2", 1.39f, "Speed buff threshold to show lvl 2 buff icon")); _hudNegIconThresholds.Add(Config.Bind("Hud", "DebuffIcon -1", 1f, "Speed buff threshold to show lvl 1 debuff icon")); _hudNegIconThresholds.Add(Config.Bind("Hud", "DebuffIcon -2", 0.79f, "Speed buff threshold to show lvl 2 debuff icon")); _groundSensorUpdateInterval = Config.Bind("Performance", "Ground Sensor Interval", 1f, "Interval between in seconds between ground type checks. Lower number, more accute ground detection.", true); _groundSensorRadius = Config.Bind("Performance", "Ground Sensor Radius", 1, "Radius of ground pixels to sample when checking under the player", true); _speedModifiers[GroundType.PathDirt] = Config.Bind("SpeedModifiers", "DirtPathSpeed", 1.15f, "Modifier for speed while on dirt paths"); _speedModifiers[GroundType.PathStone] = Config.Bind("SpeedModifiers", "StonePathSpeed", 1.4f, "Modifier for speed while on stone paths"); _speedModifiers[GroundType.Cultivated] = Config.Bind("SpeedModifiers", "CultivatedSpeed", 1f, "Modifier for speed while on Cultivated land"); _speedModifiers[GroundType.StructureWood] = Config.Bind("SpeedModifiers", "StructureWoodSpeed", 1.15f, "Modifier for speed while on wood structures"); _speedModifiers[GroundType.StructureHardWood] = Config.Bind("SpeedModifiers", "StructureHardWoodSpeed", 1.15f, "Modifier for speed while on core wood structures"); _speedModifiers[GroundType.StructureStone] = Config.Bind("SpeedModifiers", "StructureStoneSpeed", 1.4f, "Modifier for speed while on stone structures"); _speedModifiers[GroundType.StructureIron] = Config.Bind("SpeedModifiers", "StructureIronSpeed", 1.4f, "Modifier for speed while on ironwood structures"); _speedModifiers[GroundType.StructureMarble] = Config.Bind("SpeedModifiers", "StructureMarbleSpeed", 1.4f, "Modifier for speed while on black marble structures"); _staminaModifiers[GroundType.PathDirt] = Config.Bind("StaminaModifiers", "DirtPathStamina", 0.8f, "Modifier for stamina while on dirt paths"); _staminaModifiers[GroundType.PathStone] = Config.Bind("StaminaModifiers", "StonePathStamina", 0.7f, "Modifier for stamina while on stone paths"); _staminaModifiers[GroundType.Cultivated] = Config.Bind("StaminaModifiers", "CultivatedStamina", 1f, "Modifier for stamina while on Cultivated land"); _staminaModifiers[GroundType.StructureWood] = Config.Bind("StaminaModifiers", "StructureWoodStamina", 0.8f, "Modifier for stamina while on wood structures"); _staminaModifiers[GroundType.StructureHardWood] = Config.Bind("StaminaModifiers", "StructureHardWoodStamina", 0.8f, "Modifier for stamina while on core wood structures"); _staminaModifiers[GroundType.StructureStone] = Config.Bind("StaminaModifiers", "StructureStoneStamina", 0.7f, "Modifier for stamina while on stone structures"); _staminaModifiers[GroundType.StructureIron] = Config.Bind("StaminaModifiers", "StructureIronStamina", 0.7f, "Modifier for stamina while on ironwood structures"); _staminaModifiers[GroundType.StructureMarble] = Config.Bind("StaminaModifiers", "StructureMarbleStamina", 0.7f, "Modifier for stamina while on black marble structures"); foreach (Biome value in Enum.GetValues(typeof(Biome))) { Biome key = value; _untamedSpeedModifiers[key] = Config.Bind("SpeedModifiers_Biomes", "Untamed_" + ((object)(Biome)(ref key)).ToString() + "_Speed", 1f, "Speed modifier for uncleared ground in " + ((object)(Biome)(ref key)).ToString() + " Biomes"); _untamedStaminaModifiers[key] = Config.Bind("StaminaModifiers_Biomes", "Untamed_" + ((object)(Biome)(ref key)).ToString() + "_Stamina", 1f, "Stamina modifier for uncleared ground in " + ((object)(Biome)(ref key)).ToString() + " Biomes"); _biomeTypeStrings[key] = Config.Bind("Strings", "Biome_" + ((object)(Biome)(ref key)).ToString(), "default", "Dynamic status mapping for " + ((object)(Biome)(ref key)).ToString() + " groundcover. 'default' uses localized biome name."); } _groundTypeStrings[GroundType.PathDirt] = Config.Bind("Strings", "PathDirt", "Dirt Path", "Dynamic status mapping for dirt paths"); _groundTypeStrings[GroundType.PathStone] = Config.Bind("Strings", "PathStone", "Stone Path", "Dynamic status mapping for stone paths"); _groundTypeStrings[GroundType.Cultivated] = Config.Bind("Strings", "Cultivated", "Cultivated", "Dynamic status mapping for Cultivated land"); _groundTypeStrings[GroundType.StructureWood] = Config.Bind("Strings", "StructureWood", "Wood", "Dynamic status mapping for wood structures"); _groundTypeStrings[GroundType.StructureHardWood] = Config.Bind("Strings", "StructureHardWood", "Hardwood", "Dynamic status mapping for core wood structures"); _groundTypeStrings[GroundType.StructureStone] = Config.Bind("Strings", "StructureStone", "Stone", "MDynamic status mapping for stone structures"); _groundTypeStrings[GroundType.StructureIron] = Config.Bind("Strings", "StructureIron", "Iron", "Dynamic status mapping for ironwood structures"); _groundTypeStrings[GroundType.StructureMarble] = Config.Bind("Strings", "StructureMarble", "Marble", "Dynamic status mapping for black marble structures"); if (m_pieceLayer == 0) { m_pieceLayer = LayerMask.NameToLayer("piece"); } _speedSprites.Add(_speedyassets.LoadAsset<Sprite>("assets/nex.speedypaths/speedypaths_1.png")); _speedSprites.Add(_speedyassets.LoadAsset<Sprite>("assets/nex.speedypaths/speedypaths_2.png")); _speedSprites.Add(_speedyassets.LoadAsset<Sprite>("assets/nex.speedypaths/speedypaths_n1.png")); _speedSprites.Add(_speedyassets.LoadAsset<Sprite>("assets/nex.speedypaths/speedypaths_n2.png")); m_sensorTime = 0f; m_cachedGroundType = GroundType.Untamed; Harmony.CreateAndPatchAll(typeof(SpeedyPathsClientMod), (string)null); } [HarmonyPatch(typeof(Player), "FixedUpdate")] [HarmonyPrefix] private static void UpdateModifiers(Player __instance) { m_sensorTime -= Time.fixedDeltaTime; if (!((Object)(object)Player.m_localPlayer == (Object)(object)__instance) || ((Character)__instance).IsDead()) { return; } UpdateGroundTypeCache(__instance); _activeSpeedModifier = GetSpeedyPathModifier(__instance); _activeStaminaModifier = GetSpeedyPathStaminaModifier(__instance); if (_activeSpeedModifier > 1f) { for (int i = 0; i < _hudPosIconThresholds.Count; i++) { if (_activeSpeedModifier > _hudPosIconThresholds[i].Value) { _activeStatusSprite = _speedSprites[i]; } } return; } for (int j = 0; j < _hudNegIconThresholds.Count; j++) { if (_activeSpeedModifier < _hudNegIconThresholds[j].Value) { _activeStatusSprite = _speedSprites[_hudPosIconThresholds.Count + j]; } } } [HarmonyPatch(typeof(Player), "CheckRun")] [HarmonyPrefix] private static void CheckRunPrefixStaminaMod(Player __instance, out float __state) { __state = __instance.m_runStaminaDrain; __instance.m_runStaminaDrain *= _activeStaminaModifier; } [HarmonyPatch(typeof(Player), "CheckRun")] [HarmonyPostfix] private static void CheckRunPostfixStaminaMod(Player __instance, float __state) { __instance.m_runStaminaDrain = __state; } [HarmonyPatch(typeof(Player), "GetJogSpeedFactor")] [HarmonyPostfix] private static void JogSpeedPathFactor(Player __instance, ref float __result) { __result *= _activeSpeedModifier; } [HarmonyPatch(typeof(Player), "GetRunSpeedFactor")] [HarmonyPostfix] private static void RunSpeedPathFactor(Player __instance, ref float __result) { __result *= _activeSpeedModifier; } [HarmonyPatch(typeof(Hud), "UpdateStatusEffects")] [HarmonyPrefix] private static void UpdatePathIcon(Hud __instance, List<StatusEffect> statusEffects) { if (((Character)Player.m_localPlayer).IsDead() || !_showHudStatus.Value || _activeSpeedModifier == 1f) { return; } if ((Object)(object)_pathBuffSEDummy == (Object)null) { ScriptableObject obj = ScriptableObject.CreateInstance(typeof(StatusEffect)); _pathBuffSEDummy = (StatusEffect)(object)((obj is StatusEffect) ? obj : null); } _pathBuffSEDummy.m_name = (_hudDynamicStatusText.Value ? _activeStatusText : _hudStatusText.Value); _pathBuffSEDummy.m_icon = _activeStatusSprite; if (_activeSpeedModifier != 1f) { if (_activeSpeedModifier != _prevModValue) { _pathBuffSEDummy.m_isNew = true; } statusEffects.Add(_pathBuffSEDummy); } _prevModValue = _activeSpeedModifier; } [HarmonyPatch(typeof(StatusEffect), "GetIconText")] [HarmonyPostfix] private static void SpeedyPathsStatusEffect_GetIconText(StatusEffect __instance, ref string __result) { if ((Object)(object)__instance == (Object)(object)_pathBuffSEDummy && _hudShowEffectPercent.Value) { __result = (_activeSpeedModifier - 1f).ToString("P0"); } } private static float GetSpeedyPathModifier(Player player) { //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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) if (!((Character)player).IsSwimming() && !((Character)player).InInterior()) { if (_speedModifiers.ContainsKey(m_cachedGroundType)) { _activeStatusText = _groundTypeStrings[m_cachedGroundType].Value; return _speedModifiers[m_cachedGroundType].Value; } Biome key = player.GetCurrentBiome(); if (!_untamedSpeedModifiers.ContainsKey(key)) { Logger.LogWarning((object)("New biome " + ((object)(Biome)(ref key)).ToString() + ". Unsure how to Handle. Falling back to None.")); key = (Biome)0; } _activeStatusText = "$biome_" + ((object)(Biome)(ref key)).ToString().ToLower(); if (_biomeTypeStrings.ContainsKey(key) && _biomeTypeStrings[key].Value != "default") { _activeStatusText = _biomeTypeStrings[key].Value; } return _untamedSpeedModifiers[key].Value; } return 1f; } private static float GetSpeedyPathStaminaModifier(Player player) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (!((Character)player).IsSwimming() && !((Character)player).InInterior()) { if (_staminaModifiers.ContainsKey(m_cachedGroundType)) { return _staminaModifiers[m_cachedGroundType].Value; } Biome key = player.GetCurrentBiome(); if (!_untamedStaminaModifiers.ContainsKey(key)) { Logger.LogWarning((object)("New biome " + ((object)(Biome)(ref key)).ToString() + ". Unsure how to Handle. Falling back to None.")); key = (Biome)0; } return _untamedStaminaModifiers[key].Value; } return 1f; } private static void UpdateGroundTypeCache(Player player) { //IL_011f: 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_0055: 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_0070: Expected I4, but got Unknown //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) if (m_sensorTime > 0f) { return; } m_sensorTime = _groundSensorUpdateInterval.Value; Collider lastGroundCollider = ((Character)player).GetLastGroundCollider(); if (Object.op_Implicit((Object)(object)lastGroundCollider)) { if (((Component)lastGroundCollider).gameObject.layer == m_pieceLayer) { WearNTear componentInParent = ((Component)lastGroundCollider).GetComponentInParent<WearNTear>(); if (Object.op_Implicit((Object)(object)componentInParent)) { MaterialType materialType = componentInParent.m_materialType; switch ((int)materialType) { case 0: m_cachedGroundType = GroundType.StructureWood; return; case 1: m_cachedGroundType = GroundType.StructureStone; return; case 3: m_cachedGroundType = GroundType.StructureHardWood; return; case 2: m_cachedGroundType = GroundType.StructureIron; return; case 4: m_cachedGroundType = GroundType.StructureMarble; return; } } } Heightmap component = ((Component)lastGroundCollider).GetComponent<Heightmap>(); if ((Object)(object)component != (Object)null) { object value = Traverse.Create((object)component).Field("m_paintMask").GetValue(); Texture2D val = (Texture2D)((value is Texture2D) ? value : null); _worldToVertexArgs[0] = Traverse.Create((object)player).Field("m_lastGroundPoint").GetValue() as Vector3?; AccessTools.Method(typeof(Heightmap), "WorldToVertex", (Type[])null, (Type[])null).Invoke(component, _worldToVertexArgs); int value2 = _groundSensorRadius.Value; Color val2 = default(Color); int num = Math.Max((int)_worldToVertexArgs[1] - value2, 0); int num2 = value2 * 2; if (num2 + (int)_worldToVertexArgs[1] >= ((Texture)val).width) { num2 = ((Texture)val).width - num - 1; } int num3 = Math.Max((int)_worldToVertexArgs[2] - value2, 0); int num4 = value2 * 2; if (num4 + (int)_worldToVertexArgs[2] >= ((Texture)val).height) { num4 = ((Texture)val).height - num3 - 1; } Color[] pixels = val.GetPixels(num, num3, num2, num4, 0); Color[] array = pixels; foreach (Color val3 in array) { val2 += val3; } ((Color)(ref val2))..ctor(val2.r / (float)pixels.Length, val2.g / (float)pixels.Length, val2.b / (float)pixels.Length); if (val2.b > 0.4f) { m_cachedGroundType = GroundType.PathStone; return; } if (val2.r > 0.4f) { m_cachedGroundType = GroundType.PathDirt; return; } if (val2.g > 0.4f) { m_cachedGroundType = GroundType.Cultivated; return; } } } m_cachedGroundType = GroundType.Untamed; } } } namespace SpeedyPaths.Properties { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { resourceMan = new ResourceManager("SpeedyPaths.Properties.Resources", typeof(Resources).Assembly); } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static byte[] speedyassets => (byte[])ResourceManager.GetObject("speedyassets", resourceCulture); internal Resources() { } } }