Decompiled source of HIJOS DE FREYJA ROLEPLAY v0.0.2
Bepinex/plugins/CraftByProfession/CraftByProfession.dll
Decompiled 18 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Buffers; using System.Buffers.Binary; using System.Buffers.Text; 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.Diagnostics.Tracing; using System.Globalization; using System.IO; using System.IO.Compression; using System.IO.Pipelines; using System.Linq; using System.Numerics; using System.Numerics.Hashing; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Reflection; using System.Text.Json.Schema; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Converters; using System.Text.Json.Serialization.Metadata; using System.Text.RegularExpressions; using System.Text.Unicode; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Sources; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CraftByProfession.Loaders; using CraftByProfession.Managers; using CraftByProfession.Patches; using CraftByProfession.UISelection; using FxResources.System.Buffers; using FxResources.System.IO.Pipelines; using FxResources.System.Memory; using FxResources.System.Numerics.Vectors; using FxResources.System.Text.Encodings.Web; using FxResources.System.Text.Json; using FxResources.System.ValueTuple; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("CraftByProfession")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CraftByProfession")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9d7b5d97-1586-4682-8c7b-b1174633c18e")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace CraftByProfession { internal class ConfigurationFile { private static ConfigEntry<bool> _serverConfigLocked = null; public static ConfigEntry<bool> debug; public static string path_to_your_mod_folder; public static ConfigEntry<KeyCode> compendiumHotKey; public static ConfigEntry<bool> bypassAdmins; public static ConfigEntry<bool> showAllInCompendium; public static ConfigEntry<string> professions; public static ConfigEntry<KeyCode> professionsHotKey; public static ConfigEntry<string> profession; public static ConfigEntry<string> professionsSprites; public static ConfigEntry<bool> allowProfessionChange; public static ConfigEntry<string> beehiveProfession; public static ConfigEntry<string> beehiveUsageForbidden; public static ConfigEntry<string> fermenterProfession; public static ConfigEntry<string> fermenterUsageForbidden; public static ConfigEntry<string> smelterProfession; public static ConfigEntry<string> smelterUsageForbidden; public static ConfigEntry<string> blastfurnaceProfession; public static ConfigEntry<string> blastfurnaceUsageForbidden; public static ConfigEntry<string> eitrrefineryProfession; public static ConfigEntry<string> eitrrefineryUsageForbidden; public static ConfigEntry<string> actions; public static ConfigEntry<string> unavailablePieceMessage; public static ConfigEntry<string> unavailablePieceLevelMessage; public static ConfigEntry<string> unavailableRecipeMessage; public static ConfigEntry<string> unavailableRecipeLevelMessage; public static ConfigEntry<string> unremovablePieceMessage; public static ConfigEntry<string> unremovablePieceLevelMessage; public static ConfigFile configFile; private static readonly string ConfigFileName = "Turbero.ValheimProfessionRoleplay.cfg"; private static readonly string ConfigFileFullPath; private static readonly ConfigSync ConfigSync; internal static void LoadConfig(BaseUnityPlugin plugin) { configFile = plugin.Config; _serverConfigLocked = config("1 - General", "Lock Configuration", value: true, "If on, the configuration is locked and can be changed by server admins only."); ConfigSync.AddLockingConfigEntry<bool>(_serverConfigLocked); string text = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\professions"; path_to_your_mod_folder = text; debug = config("1 - General", "DebugMode", value: false, "Enabling/Disabling the debugging in the console (default = false)", synchronizedSetting: false); compendiumHotKey = config<KeyCode>("2 - Config", "CompendiumHotKey", (KeyCode)284, "Hot key to open the compendium (default = F3)", synchronizedSetting: false); bypassAdmins = config("2 - Config", "BypassAdmins", value: false, "Admins ignore profession conditions (default = true)"); showAllInCompendium = config("2 - Config", "ShowAllInCompendium", value: true, "Shows all objects your profession can manage in Compendium or only those you have learnt until now (default = false)"); professionsHotKey = config<KeyCode>("3 - Assignments", "ProfessionsHotKey", (KeyCode)112, "Hoy key for professions panel", synchronizedSetting: false); professions = config("3 - Assignments", "Professions", "", "Comma-separated list of professions."); professionsSprites = config("3 - Assignments", "ProfessionsSprites", "", "Comma-separated list of sprites for professions."); allowProfessionChange = config("3 - Assignments", "AllowProfessionChange", value: false, "Allow changing professions after selecting for first time (default = false)."); beehiveProfession = config("4 - Exclusive pieces", "BeehiveProfession", "", "Exclusive profession for using the beehive. Leave blank to allow to everyone to use it."); beehiveUsageForbidden = config("4 - Exclusive pieces", "BeehiveUsageForbidden", "You can't use the beehive with your current profession!", "Message to show when beehive cannot be used"); fermenterProfession = config("4 - Exclusive pieces", "FermenterProfession", "", "Exclusive profession for using the fermenter. Leave blank to allow to everyone to use it."); fermenterUsageForbidden = config("4 - Exclusive pieces", "FermenterUsageForbidden", "You can't use the fermenter with your current profession!", "Message to show when the fermenter cannot be used"); smelterProfession = config("4 - Exclusive pieces", "SmelterProfession", "", "Exclusive profession for using the smelter. Leave blank to allow to everyone to use it."); smelterUsageForbidden = config("4 - Exclusive pieces", "SmelterUsageForbidden", "You can't use the smelter with your current profession!", "Message to show when the smelter cannot be used"); blastfurnaceProfession = config("4 - Exclusive pieces", "BlastFurnaceProfession", "", "Exclusive profession for using the blast furnace. Leave blank to allow to everyone to use it."); blastfurnaceUsageForbidden = config("4 - Exclusive pieces", "BlastfurnaceUsageForbidden", "You can't use the blast furnace with your current profession!", "Message to show when the blast furnace cannot be used"); eitrrefineryProfession = config("4 - Exclusive pieces", "EitrRefineryProfession", "", "Exclusive profession for using the eitr refinery. Leave blank to allow to everyone to use it."); eitrrefineryUsageForbidden = config("4 - Exclusive pieces", "EitrRefineryUsageForbidden", "You can't use the eitr refinery with your current profession!", "Message to show when the eitr refinery cannot be used"); profession = config("5 - Language", "Profession", "Profession", "Profession."); actions = config("5 - Language", "Actions", "Actions", "Actions section in compendium."); unavailablePieceMessage = config("5 - Language", "UnavailablePieceMessage", "You don't have the profession {0} to place that object", "Message to show when piece cannot be placed ({0} = profession)"); unavailablePieceLevelMessage = config("5 - Language", "UnavailablePieceLevelMessage", "You don't have the necessary skill level {0} in {1} to place that object", "Message to show when piece cannot be placed ({0} = level, {1} = profession)"); unavailableRecipeMessage = config("5 - Language", "UnavailableRecipeMessage", "You don't have the profession {0} to create that object", "Message to show when recipe cannot be crafted ({0} = profession)"); unavailableRecipeLevelMessage = config("5 - Language", "UnavailableRecipeLevelMessage", "You don't have the necessary skill level {0} in {1} to create that object", "Message to show when recipe cannot be crafted ({0} = level, {1} = profession)"); unremovablePieceMessage = config("5 - Language", "UnremovablePieceMessage", "You don't have the profession {0} to remove that object", "Message to show when piece cannot be removed ({0} = profession)"); unremovablePieceLevelMessage = config("5 - Language", "UnremovablePieceLevelMessage", "You don't have the necessary skill level {0} in {1} to remove that object", "Message to show when piece cannot be removed ({0} = level, {1} = profession"); bypassAdmins.SettingChanged += OnSettingChanged; showAllInCompendium.SettingChanged += OnSettingChanged; professions.SettingChanged += OnSettingChanged; professionsSprites.SettingChanged += OnSettingChanged; allowProfessionChange.SettingChanged += OnSettingChanged; SetupWatcher(); } private static 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 static void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { Logger.Log("Attempting to reload configuration..."); configFile.Reload(); } catch { Logger.LogError("There was an issue loading " + ConfigFileName); } } private static void OnSettingChanged(object sender, EventArgs e) { if ((Object)(object)ZNetScene.instance != (Object)null) { LoaderPiecePatch.Postfix(ZNetScene.instance); LoaderRecipePatch.Postfix(ZNetScene.instance); } CraftStationDescriptionsPatch.updated = false; if ((Object)(object)ProfessionUI.professionUIResetButton != (Object)null) { ((Component)ProfessionUI.professionUIResetButton).gameObject.SetActive(bypassAdmins.Value || allowProfessionChange.Value); } } private static ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } private static ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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 = configFile.Bind<T>(group, name, value, val); SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val2); syncedConfigEntry.SynchronizedConfig = synchronizedSetting; return val2; } static ConfigurationFile() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; ConfigSync = new ConfigSync("Turbero.ValheimProfessionRoleplay") { DisplayName = "Valheim Profession Roleplay", CurrentVersion = "1.0.0", MinimumRequiredVersion = "1.0.0" }; } } public static class Logger { public static ManualLogSource logger = Logger.CreateLogSource("Valheim Profession Roleplay"); internal static void Log(object s) { if (ConfigurationFile.debug.Value) { logger.LogInfo((object)s?.ToString()); } } internal static void LogInfo(object s) { logger.LogInfo((object)s?.ToString()); } internal static void LogWarning(object s) { logger.LogWarning((object)s?.ToString()); } internal static void LogError(object s) { logger.LogError((object)s?.ToString()); } } public class ProfessionData { public string professionName; [JsonPropertyName("objectName")] public string ObjectName { get; set; } [JsonPropertyName("itemName")] public string ItemName { get; set; } [JsonPropertyName("skillType")] public SkillType SkillType { get; set; } = (SkillType)0; [JsonPropertyName("minSkillLevel")] public int MinSkillLevel { get; set; } = 0; public override string ToString() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) return $"[objectName: {ObjectName}, itemName: {ItemName}, professionName: {professionName}, skillType: {SkillType}, minSkillLevel: {MinSkillLevel}]"; } } public class ProfessionDataComponent : MonoBehaviour { public string objectName; public string itemName; public string professionName; public SkillType skillType = (SkillType)0; public int minSkillLevel = 0; public ProfessionData getProfessionData() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) return new ProfessionData { ObjectName = objectName, ItemName = itemName, professionName = professionName, SkillType = skillType, MinSkillLevel = minSkillLevel }; } public override string ToString() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) return $"[objectName: {objectName}, itemName: {itemName}, professionName: {professionName}, skillType: {skillType}, minSkillLevel: {minSkillLevel}]"; } } [BepInPlugin("Turbero.ValheimProfessionRoleplay", "Valheim Profession Roleplay", "1.0.0")] public class CraftByProfession : BaseUnityPlugin { public const string GUID = "Turbero.ValheimProfessionRoleplay"; public const string NAME = "Valheim Profession Roleplay"; public const string VERSION = "1.0.0"; private readonly Harmony harmony = new Harmony("Turbero.ValheimProfessionRoleplay"); private void Awake() { ConfigurationFile.LoadConfig((BaseUnityPlugin)(object)this); harmony.PatchAll(); } private void onDestroy() { ConfigurationFile.configFile.Save(); harmony.UnpatchSelf(); } public void Update() { //IL_0071: 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) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !Object.op_Implicit((Object)(object)InventoryGui.instance)) { return; } if (Input.GetKeyDown((KeyCode)27) || Input.GetKeyDown((KeyCode)9) || ((Character)Player.m_localPlayer).IsDead()) { ProfessionUI.Hide(); ((Component)InventoryGui.instance.m_textsDialog).gameObject.SetActive(false); } else if (Input.GetKeyDown(ConfigurationFile.compendiumHotKey.Value) && IsKeyActionAllowed()) { if (((Component)InventoryGui.instance.m_textsDialog).gameObject.activeSelf) { ProfessionUI.Hide(); UIManager.CloseInventoryGui(); } else { InventoryGui.instance.Show((Container)null, 1); WaitForSecondsAsync(0.15f); } } else if (Input.GetKeyDown(ConfigurationFile.professionsHotKey.Value) && IsKeyActionAllowed()) { if (ProfessionUI.IsVisible()) { ProfessionUI.Hide(); UIManager.CloseInventoryGui(); } else { InventoryGui.instance.Show((Container)null, 1); WaitForSecondsAsync(0.15f, openProfessions: true); } } } private static bool IsKeyActionAllowed() { GameObject val = GameObject.Find("_GameMain/LoadingGUI/PixelFix/IngameGui/EasySpawnerMenu(Clone)/SearchInputField"); InputField val2 = ((val != null) ? val.GetComponent<InputField>() : null); return !Chat.instance.HasFocus() && !Console.IsVisible() && Time.timeScale > 0f && ((Object)(object)val2 == (Object)null || !val2.isFocused); } private static async Task WaitForSecondsAsync(float seconds, bool openProfessions = false) { await Task.Delay((int)(Math.Max(0f, seconds) * 1000f)); InventoryGui.instance.m_textsDialog.Setup(Player.m_localPlayer); ((Component)InventoryGui.instance.m_textsDialog).gameObject.SetActive(true); if (openProfessions) { ProfessionUI.Show(); } } } [HarmonyPatch(typeof(Player), "OnSpawned")] public static class InstantiateSelectPanel { private static void Postfix(Player __instance) { if (ProfessionUI.professionsPanel == null) { ProfessionUI.professionsPanel = new ProfessionsPanel(); ProfessionUI.professionsPanel.getPanel().SetActive(false); } if (ProfessionUI.selectedProfessionPanel == null) { ProfessionUI.selectedProfessionPanel = new SelectedProfessionPanel(); ProfessionUI.selectedProfessionPanel.getPanel().SetActive(false); } } } } namespace CraftByProfession.UISelection { [HarmonyPatch] public class CompendiumPatch { private static readonly List<ProfessionData> detectedActions = new List<ProfessionData>(); private static MethodBase TargetMethod() { return AccessTools.Method(typeof(TextsDialog), "AddActiveEffects", (Type[])null, (Type[])null); } private static void Postfix(ref TextsDialog __instance) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown List<TextInfo> list = (List<TextInfo>)GameManager.GetPrivateValue(__instance, "m_texts"); string playerProfession = PlayerInfoManager.GetPlayerProfession(); detectedActions.Clear(); StringBuilder stringBuilder = new StringBuilder(256); stringBuilder.Append("<color=orange>" + ConfigurationFile.profession.Value + "</color>\n"); stringBuilder.Append(playerProfession); AddPlayerPieces(stringBuilder, playerProfession); AddPlayerRecipes(stringBuilder, playerProfession); AddPlayerActions(stringBuilder, playerProfession); list.Insert(0, new TextInfo("Valheim Profession Roleplay", stringBuilder.ToString())); ProfessionUI.createProfessionUI(); } private static void AddPlayerPieces(StringBuilder stringBuilder, string playerProfession) { string path = ConfigurationFile.path_to_your_mod_folder + "\\pieces_" + playerProfession + ".json"; if (!File.Exists(path)) { return; } Logger.Log("**Adding pieces"); string json = File.ReadAllText(path); List<ProfessionData> data = JsonSerializer.Deserialize<List<ProfessionData>>(json); SortedSet<string> items = GetItems(data); if (items.Count <= 0) { return; } string text = Localization.instance.Localize("$item_parts"); string text2 = text.ToCharArray()[0].ToString().ToUpper() + text.Substring(1); stringBuilder.Append("\n<color=orange>" + text2 + "</color>\n"); foreach (string item in items) { stringBuilder.Append(item); } } private static void AddPlayerRecipes(StringBuilder stringBuilder, string playerProfession) { string path = ConfigurationFile.path_to_your_mod_folder + "\\recipes_" + playerProfession + ".json"; if (!File.Exists(path)) { return; } Logger.Log("**Adding recipes"); string json = File.ReadAllText(path); List<ProfessionData> data = JsonSerializer.Deserialize<List<ProfessionData>>(json); SortedSet<string> items = GetItems(data); if (items.Count <= 0) { return; } stringBuilder.Append("\n<color=orange>$inventory_recipes</color>\n"); foreach (string item in items) { stringBuilder.Append(item); } } private static void AddPlayerActions(StringBuilder stringBuilder, string playerProfession) { Logger.Log("**Adding actions"); SortedSet<string> sortedSet = new SortedSet<string>(); foreach (ProfessionData detectedAction in detectedActions) { if (detectedAction.professionName == playerProfession) { sortedSet.Add(Localization.instance.Localize(detectedAction.ItemName)); } } if (sortedSet.Count <= 0) { return; } stringBuilder.Append("\n<color=orange>" + ConfigurationFile.actions.Value + "</color>"); foreach (string item in sortedSet) { stringBuilder.Append("\n" + item); } } private static SortedSet<string> GetItems(List<ProfessionData> data) { //IL_011a: 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_0142: Unknown result type (might be due to invalid IL or missing references) SortedSet<string> sortedSet = new SortedSet<string>(); HashSet<string> hashSet = (HashSet<string>)GameManager.GetPrivateValue(Player.m_localPlayer, "m_knownRecipes"); foreach (ProfessionData datum in data) { if (IsATool(datum) || datum.ObjectName == "Recipe_Bronze5") { continue; } string text = datum.ObjectName.Replace("Recipe_", "").ToLower(); if (ConfigurationFile.showAllInCompendium.Value || hashSet.Contains("$" + text) || hashSet.Contains("$piece_" + text) || hashSet.Contains("$item_" + text) || hashSet.Contains(datum.ItemName)) { string text2 = ((datum.ItemName == null) ? datum.ObjectName : ((Localization.instance.Localize(datum.ItemName) != null) ? Localization.instance.Localize(datum.ItemName) : datum.ItemName)); if ((int)datum.SkillType != 0 && datum.MinSkillLevel > 0) { SkillType skillType = datum.SkillType; sortedSet.Add($"{text2} (skill = $skill_{((object)(SkillType)(ref skillType)).ToString().ToLower()}, $msg_level >= {datum.MinSkillLevel})\n"); } else { sortedSet.Add(text2 + "\n"); } } else { Logger.Log(datum.ObjectName + " not learnt yet."); } } return sortedSet; } private static bool IsATool(ProfessionData jsonData) { if (jsonData.ObjectName == LoaderPiecePatch.TOOL_CULTIVATE) { detectedActions.Add(LoaderPiecePatch.cultivate); return true; } if (jsonData.ObjectName == LoaderPiecePatch.TOOL_REPLANT) { detectedActions.Add(LoaderPiecePatch.replant); return true; } if (jsonData.ObjectName == LoaderPiecePatch.TOOL_PAVE) { detectedActions.Add(LoaderPiecePatch.paved); return true; } if (jsonData.ObjectName == LoaderPiecePatch.TOOL_RAISE) { detectedActions.Add(LoaderPiecePatch.raise); return true; } return false; } } public class SelectedProfessionPanel { private GameObject currentProfessionPanel; private TextMeshProUGUI selectedProfessionText; private Image imageProfessionLogo; public SelectedProfessionPanel() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_018a: 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_01c9: 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_0224: 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) currentProfessionPanel = new GameObject("CurrentProfessionPanel", new Type[1] { typeof(RectTransform) }); currentProfessionPanel.SetActive(false); currentProfessionPanel.transform.SetParent(((Component)((Component)InventoryGui.instance).transform.Find("root/Texts/Texts_frame")).transform, false); RectTransform component = currentProfessionPanel.GetComponent<RectTransform>(); component.sizeDelta = new Vector2(512f, 512f); component.anchoredPosition = Vector2.zero; Image val = currentProfessionPanel.AddComponent<Image>(); val.sprite = ResourcesManager.getSprite("woodpanel_512x512"); val.type = (Type)1; TextMeshProUGUI val2 = UIManager.createUIText("Title", currentProfessionPanel.transform, new Vector2(0f, 220f), "Profesión", 36, "Valheim-Norsebold"); ((Graphic)val2).color = Color.yellow; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; Button val3 = UIManager.createUIButton("ProfessionOptionsCloseButton", ((Component)InventoryGui.instance.m_skillsDialog).transform.Find("SkillsFrame/Closebutton"), currentProfessionPanel.transform, new Vector2(0f, 40f), Localization.instance.Localize("$menu_close")); ((UnityEvent)val3.onClick).AddListener((UnityAction)delegate { currentProfessionPanel.SetActive(false); }); Sprite sprite = UIManager.LoadSpriteFromEmbedded("icons.hijos-de-freyja.png"); Image val4 = UIManager.createUIImage("LogoHDFEmbedded", currentProfessionPanel.transform, new Vector2(200f, 200f), new Vector2(0f, 110f), sprite); val4.preserveAspect = true; string playerProfession = PlayerInfoManager.GetPlayerProfession(); selectedProfessionText = UIManager.createUIText("SelectedProfessionTextGo", currentProfessionPanel.transform, Vector2.zero, playerProfession, 20); ((Graphic)selectedProfessionText).color = Color.green; ((TMP_Text)selectedProfessionText).alignment = (TextAlignmentOptions)514; Sprite professionSprite = getProfessionSprite(playerProfession); imageProfessionLogo = UIManager.createUIImage("LogoProfession", currentProfessionPanel.transform, new Vector2(150f, 150f), new Vector2(0f, -100f), professionSprite); imageProfessionLogo.preserveAspect = true; } private Sprite getProfessionSprite(string selectedProfession) { string[] array = ConfigurationFile.professions.Value.Split(new char[1] { ',' }); string[] array2 = ConfigurationFile.professionsSprites.Value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { if (array[i] == selectedProfession) { return ResourcesManager.getSprite(array2[i]); } } Logger.LogError("Sprite for Profession '" + selectedProfession + "' not found"); return null; } public GameObject getPanel() { return currentProfessionPanel; } public void refreshContent() { ((TMP_Text)selectedProfessionText).text = PlayerInfoManager.GetPlayerProfession(); imageProfessionLogo.sprite = getProfessionSprite(PlayerInfoManager.GetPlayerProfession()); } } public class ProfessionsPanel { private GameObject customProfessionsPanel; private Dictionary<string, GameObject> selectProfessionGoBtns = new Dictionary<string, GameObject>(); private Dictionary<string, TextMeshProUGUI> professionTexts = new Dictionary<string, TextMeshProUGUI>(); public ProfessionsPanel() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: 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_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_0254: 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_0280: Expected O, but got Unknown customProfessionsPanel = new GameObject("CustomProfessionsPanel", new Type[1] { typeof(RectTransform) }); customProfessionsPanel.SetActive(false); customProfessionsPanel.transform.SetParent(((Component)((Component)InventoryGui.instance).transform.Find("root/Texts/Texts_frame")).transform, false); RectTransform component = customProfessionsPanel.GetComponent<RectTransform>(); component.sizeDelta = new Vector2(512f, 512f); component.anchoredPosition = Vector2.zero; Image val = customProfessionsPanel.AddComponent<Image>(); val.sprite = ResourcesManager.getSprite("woodpanel_512x512"); val.type = (Type)1; TextMeshProUGUI val2 = UIManager.createUIText("Title", customProfessionsPanel.transform, new Vector2(0f, 223f), "Profesiones", 36, "Valheim-Norsebold"); ((Graphic)val2).color = Color.yellow; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; Button val3 = UIManager.createUIButton("ProfessionOptionsCloseButton", ((Component)InventoryGui.instance.m_skillsDialog).transform.Find("SkillsFrame/Closebutton"), customProfessionsPanel.transform, new Vector2(0f, 40f), Localization.instance.Localize("$menu_close")); ((UnityEvent)val3.onClick).AddListener((UnityAction)delegate { customProfessionsPanel.SetActive(false); }); TextMeshProUGUI val4 = UIManager.createUIText("AlertText", customProfessionsPanel.transform, new Vector2(0f, 165f), "ADVERTENCIA: Elegir profesión es permanente.\n sólo se podrá cambiar borrando el personaje\ny empezando desde cero.", 24, "Valheim-Norsebold"); ((Graphic)val4).color = Color.white; ((TMP_Text)val4).autoSizeTextContainer = true; ((TMP_Text)val4).alignment = (TextAlignmentOptions)514; string[] array = ConfigurationFile.professions.Value.Split(new char[1] { ',' }); int num = 100; int num2 = 355; string[] array2 = array; foreach (string profession in array2) { Transform copyFrom = ((Component)InventoryGui.instance.m_skillsDialog).transform.Find("SkillsFrame/Closebutton"); Button val5 = UIManager.createUIButton("ProfessionBtnGo", copyFrom, customProfessionsPanel.transform, new Vector2(0f, (float)num2), profession); ((UnityEvent)val5.onClick).AddListener((UnityAction)delegate { ((Character)Player.m_localPlayer).Message((MessageType)2, "Ya no puedes cambiar de profesión.\nA partir de ahora serás: " + profession, 0, (Sprite)null); ((Humanoid)Player.m_localPlayer).AddUniqueKey("HDF_" + profession); customProfessionsPanel.SetActive(false); UIManager.CloseInventoryGui(); CraftStationDescriptionsPatch.updated = false; ResourcesManager.TriggerLightningEffect(); }); ((Component)val5).gameObject.SetActive(true); selectProfessionGoBtns.Add(profession, ((Component)val5).gameObject); num -= 50; num2 -= 50; } } public GameObject getPanel() { return customProfessionsPanel; } } [HarmonyPatch] public class ProfessionUI { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__4_0; public static UnityAction <>9__4_1; internal void <createProfessionUI>b__4_0() { Logger.Log("ProfessionUIOpenButton clicked."); string playerProfession = PlayerInfoManager.GetPlayerProfession(); if (playerProfession == null) { professionsPanel.getPanel().SetActive(true); selectedProfessionPanel.getPanel().SetActive(false); } else { professionsPanel.getPanel().SetActive(false); selectedProfessionPanel.refreshContent(); selectedProfessionPanel.getPanel().SetActive(true); } } internal void <createProfessionUI>b__4_1() { Logger.Log("ProfessionUIResetButton clicked."); string[] array = ConfigurationFile.professions.Value.Split(new char[1] { ',' }); string[] array2 = array; foreach (string text in array2) { ((Humanoid)Player.m_localPlayer).RemoveUniqueKey("HDF_" + text); } CraftStationDescriptionsPatch.updated = false; Hide(); UIManager.CloseInventoryGui(); ResourcesManager.TriggerLightningEffect(); } } private static Button professionUIOpenButton; public static Button professionUIResetButton; public static ProfessionsPanel professionsPanel; public static SelectedProfessionPanel selectedProfessionPanel; public static void createProfessionUI() { //IL_0078: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown if (professionsPanel == null) { professionsPanel = new ProfessionsPanel(); professionsPanel.getPanel().SetActive(false); } if (selectedProfessionPanel == null) { selectedProfessionPanel = new SelectedProfessionPanel(); selectedProfessionPanel.getPanel().SetActive(false); } Transform val = ((Component)InventoryGui.instance).transform.Find("root/Texts/Texts_frame/Closebutton"); ((Component)val).GetComponent<RectTransform>().anchoredPosition = new Vector2(170f, 55f); if ((Object)(object)professionUIOpenButton == (Object)null) { professionUIOpenButton = UIManager.createUIButton("ProfessionUIOpenButton", val, val.parent, new Vector2(-95f, 55f), "Profesiones"); ButtonClickedEvent onClick = professionUIOpenButton.onClick; object obj = <>c.<>9__4_0; if (obj == null) { UnityAction val2 = delegate { Logger.Log("ProfessionUIOpenButton clicked."); string playerProfession = PlayerInfoManager.GetPlayerProfession(); if (playerProfession == null) { professionsPanel.getPanel().SetActive(true); selectedProfessionPanel.getPanel().SetActive(false); } else { professionsPanel.getPanel().SetActive(false); selectedProfessionPanel.refreshContent(); selectedProfessionPanel.getPanel().SetActive(true); } }; <>c.<>9__4_0 = val2; obj = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj); } if (!((Object)(object)professionUIResetButton == (Object)null)) { return; } professionUIResetButton = UIManager.createUIButton("ProfessionUIResetButton", val, val.parent, new Vector2(435f, 55f), "Reset profesión"); ButtonClickedEvent onClick2 = professionUIResetButton.onClick; object obj2 = <>c.<>9__4_1; if (obj2 == null) { UnityAction val3 = delegate { Logger.Log("ProfessionUIResetButton clicked."); string[] array = ConfigurationFile.professions.Value.Split(new char[1] { ',' }); string[] array2 = array; foreach (string text in array2) { ((Humanoid)Player.m_localPlayer).RemoveUniqueKey("HDF_" + text); } CraftStationDescriptionsPatch.updated = false; Hide(); UIManager.CloseInventoryGui(); ResourcesManager.TriggerLightningEffect(); }; <>c.<>9__4_1 = val3; obj2 = (object)val3; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); Logger.Log("ProfessionUIResetButton bypassAdmins: " + ConfigurationFile.bypassAdmins.Value); Logger.Log("ProfessionUIResetButton allowProfessionChange: " + ConfigurationFile.allowProfessionChange.Value); ((Component)professionUIResetButton).gameObject.SetActive(ConfigurationFile.bypassAdmins.Value || ConfigurationFile.allowProfessionChange.Value); } public static bool IsVisible() { return professionsPanel.getPanel().activeSelf || selectedProfessionPanel.getPanel().activeSelf; } public static void Hide() { professionsPanel.getPanel().SetActive(false); selectedProfessionPanel.getPanel().SetActive(false); } public static void Show() { string playerProfession = PlayerInfoManager.GetPlayerProfession(); if (playerProfession == null) { professionsPanel.getPanel().SetActive(true); selectedProfessionPanel.getPanel().SetActive(false); } else { professionsPanel.getPanel().SetActive(false); selectedProfessionPanel.refreshContent(); selectedProfessionPanel.getPanel().SetActive(true); } } } } namespace CraftByProfession.Loaders { [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class LoaderPiecePatch { public static readonly string TOOL_CULTIVATE = "cultivate_v2"; public static readonly string TOOL_REPLANT = "replant_v2"; public static readonly string TOOL_PAVE = "paved_road_v2"; public static readonly string TOOL_RAISE = "raise_v2"; public static ProfessionData cultivate; public static ProfessionData replant; public static ProfessionData paved; public static ProfessionData raise; private static void init() { cultivate = null; replant = null; paved = null; raise = null; } public static void Postfix(ZNetScene __instance) { init(); string[] array = ConfigurationFile.professions.Value.Split(new char[1] { ',' }); string[] array2 = array; foreach (string professionName in array2) { LoadFilePieces(professionName); } } private static void LoadFilePieces(string professionName) { //IL_012b: 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) string text = ConfigurationFile.path_to_your_mod_folder + "\\pieces_" + professionName + ".json"; if (!File.Exists(text)) { Logger.Log("Path " + text + " doesn't exit. Skipping."); return; } string json = File.ReadAllText(text); List<ProfessionData> list = JsonSerializer.Deserialize<List<ProfessionData>>(json); Logger.Log("** Loading Pieces for " + professionName + "..."); foreach (ProfessionData dataItem in list) { if (!foundATool(dataItem, professionName)) { GameObject val = ZNetScene.instance.m_prefabs.Find((GameObject i) => ((Object)i).name == dataItem.ObjectName); if ((Object)(object)val != (Object)null) { ProfessionDataComponent professionDataComponent = (((Object)(object)val.GetComponent<ProfessionDataComponent>() != (Object)null) ? val.GetComponent<ProfessionDataComponent>() : val.AddComponent<ProfessionDataComponent>()); professionDataComponent.objectName = dataItem.ObjectName; professionDataComponent.itemName = dataItem.ItemName; professionDataComponent.professionName = professionName; professionDataComponent.skillType = dataItem.SkillType; professionDataComponent.minSkillLevel = dataItem.MinSkillLevel; Logger.Log("Prefab profession added to " + professionDataComponent.objectName + " for profession " + professionDataComponent.professionName + "."); } else { Logger.LogWarning("Prefab not found with name " + dataItem.ObjectName + ". Skipping."); } } } } private static bool foundATool(ProfessionData dataItem, string professionName) { if (dataItem.ObjectName == TOOL_CULTIVATE) { Logger.Log(TOOL_CULTIVATE + " found"); dataItem.professionName = professionName; cultivate = dataItem; return true; } if (dataItem.ObjectName == TOOL_REPLANT) { Logger.Log(TOOL_REPLANT + " found"); dataItem.professionName = professionName; replant = dataItem; return true; } if (dataItem.ObjectName == TOOL_PAVE) { Logger.Log(TOOL_PAVE + " found"); dataItem.professionName = professionName; paved = dataItem; return true; } if (dataItem.ObjectName == TOOL_RAISE) { Logger.Log(TOOL_RAISE + " found"); dataItem.professionName = professionName; raise = dataItem; return true; } return false; } } [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class LoaderRecipePatch { public static void Postfix(ZNetScene __instance) { RecipeManager.recipesProfessionData.Clear(); string[] array = ConfigurationFile.professions.Value.Split(new char[1] { ',' }); string[] array2 = array; foreach (string professionName in array2) { loadRecipes(professionName); } } private static void loadRecipes(string professionName) { string text = ConfigurationFile.path_to_your_mod_folder + "\\recipes_" + professionName + ".json"; if (!File.Exists(text)) { Logger.Log("Path " + text + " doesn't exit. Skipping."); return; } Logger.Log("** Loading recipes for " + professionName + "..."); string json = File.ReadAllText(text); List<ProfessionData> list = JsonSerializer.Deserialize<List<ProfessionData>>(json); foreach (ProfessionData item in list) { if (!RecipeManager.recipesProfessionData.ContainsKey(item.ObjectName)) { item.professionName = professionName; RecipeManager.recipesProfessionData.Add(item.ObjectName, item); Logger.Log("Profession Data from json added: " + item.ObjectName + " for profession " + item.professionName); } else { Logger.LogWarning("Profession Data repeatedKey " + item.ObjectName); } } } } } namespace CraftByProfession.Patches { [HarmonyPatch(typeof(Player), "Interact")] public static class PlayerInteractPatch { private static bool Prefix(Player __instance, GameObject go, bool hold, bool alt) { Logger.Log("**PlayerInteractPatch Interact PREFIX"); if (ConfigurationFile.bypassAdmins.Value) { bool flag = PlayerInfoManager.IsPlayerLocalAdmin(); Logger.Log($"PlayerInteractPatch isAdmin: {flag}"); if (flag) { return true; } string steamID = PlayerInfoManager.GetSteamID(__instance); Logger.Log("steamId = " + steamID); if (steamID == null) { return true; } flag = PlayerInfoManager.IsAdmin(steamID); Logger.Log("PlayerInteractPatch " + steamID + " isAdmin: " + flag); if (flag) { return true; } } Transform parent = go.transform.parent; string text = ((parent != null) ? ((Object)((Component)parent).gameObject).name : null); if (text == null) { return true; } Logger.Log("gameObject name: " + ((Object)go).name); Logger.Log("gameObject parent name: " + text); if (text.ToLower().StartsWith("piece_beehive")) { return checkPiece(__instance, ConfigurationFile.beehiveProfession.Value, ConfigurationFile.beehiveUsageForbidden.Value); } if (text.ToLower().StartsWith("smelter")) { return checkPiece(__instance, ConfigurationFile.smelterProfession.Value, ConfigurationFile.smelterUsageForbidden.Value); } if (text.ToLower().StartsWith("blastfurnace")) { return checkPiece(__instance, ConfigurationFile.blastfurnaceProfession.Value, ConfigurationFile.blastfurnaceUsageForbidden.Value); } if (text.ToLower().StartsWith("eitrrefinery")) { return checkPiece(__instance, ConfigurationFile.eitrrefineryProfession.Value, ConfigurationFile.eitrrefineryUsageForbidden.Value); } Transform parent2 = go.transform.parent; if ((Object)(object)((parent2 != null) ? parent2.parent : null) != (Object)null) { Transform parent3 = go.transform.parent; object obj; if (parent3 == null) { obj = null; } else { Transform parent4 = parent3.parent; obj = ((parent4 != null) ? ((Component)parent4).gameObject : null); } if ((Object)obj != (Object)null) { Logger.Log("Checking last option"); Transform parent5 = go.transform.parent; object obj2; if (parent5 == null) { obj2 = null; } else { Transform parent6 = parent5.parent; obj2 = ((parent6 != null) ? ((Object)((Component)parent6).gameObject).name : null); } string text2 = (string)obj2; Logger.Log("gameObject parent parent name: " + text2); if (text2.ToLower().StartsWith("fermenter")) { return checkPiece(__instance, ConfigurationFile.fermenterProfession.Value, ConfigurationFile.fermenterUsageForbidden.Value); } } } return true; } private static bool checkPiece(Player __instance, string professionName, string unavailableMessage) { if (professionName != PlayerInfoManager.GetPlayerProfession()) { Logger.Log("Interact bloqueado"); ((Character)__instance).Message((MessageType)2, unavailableMessage, 0, (Sprite)null); return false; } Logger.Log("Interact permitido"); return true; } } [HarmonyPatch(typeof(InventoryGui), "Show")] public static class CraftStationDescriptionsPatch { public static bool updated; public static bool Prefix(Container container, int activeGroup) { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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) if (updated) { return true; } foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if (RecipeManager.recipesProfessionData.ContainsKey(((Object)recipe).name)) { string playerProfession = PlayerInfoManager.GetPlayerProfession(); ProfessionData valueSafe = GeneralExtensions.GetValueSafe<string, ProfessionData>(RecipeManager.recipesProfessionData, ((Object)recipe).name); string professionName = valueSafe.professionName; string text = ((playerProfession == professionName) ? "green" : "red"); string text2 = recipe.m_item.m_itemData.m_shared.m_description.Split(new char[1] { '\n' })[0]; SharedData shared = recipe.m_item.m_itemData.m_shared; string[] obj = new string[9] { text2, "\n", ConfigurationFile.profession.Value, ": <color=", text, ">", professionName, "</color>", null }; object obj2; if ((int)valueSafe.SkillType == 0 || valueSafe.MinSkillLevel <= 0) { obj2 = ""; } else { SkillType skillType = valueSafe.SkillType; obj2 = $"\n(Skill = $skill_{((object)(SkillType)(ref skillType)).ToString().ToLower()}, $msg_level = {valueSafe.MinSkillLevel})"; } obj[8] = (string)obj2; shared.m_description = string.Concat(obj); } } updated = true; return true; } } [HarmonyPatch(typeof(UITooltip), "UpdateTextElements")] public static class UITooltipPatch { public static void Postfix(UITooltip __instance) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_00f8: 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_011c: Unknown result type (might be due to invalid IL or missing references) GameObject val = (GameObject)GameManager.GetPrivateValue(__instance, "m_tooltip", BindingFlags.Static | BindingFlags.NonPublic); if (!((Object)(object)val != (Object)null)) { return; } Transform val2 = Utils.FindChild(val.transform, "Text", (IterativeSearchType)0); if (!((Object)(object)val2 != (Object)null)) { return; } ProfessionData professionData = RecipeManager.FindRecipeByItemName(__instance.m_topic); if (professionData?.ObjectName == null) { return; } string playerProfession = PlayerInfoManager.GetPlayerProfession(); string professionName = professionData.professionName; string text = ((playerProfession == professionName) ? "green" : "red"); if (!__instance.m_text.Contains(ConfigurationFile.profession.Value)) { string[] obj = new string[8] { "\n", ConfigurationFile.profession.Value, ": <color=", text, ">", professionName, "</color>", null }; object obj2; if ((int)professionData.SkillType == 0 || professionData.MinSkillLevel <= 0) { obj2 = ""; } else { SkillType skillType = professionData.SkillType; obj2 = $"\n(Skill = $skill_{((object)(SkillType)(ref skillType)).ToString().ToLower()}, $msg_level = {professionData.MinSkillLevel})"; } obj[7] = (string)obj2; string text2 = string.Concat(obj); __instance.m_text = __instance.m_text.Replace("_description", "_description " + text2); } ((Component)val2).GetComponent<TMP_Text>().text = Localization.instance.Localize(__instance.m_text); } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] public static class PlacePiecePatch { private static bool Prefix(Player __instance, Piece piece) { //IL_0123: 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) Logger.Log("**PlacePiecePatch TryPlacePiece PREFIX"); string steamID = PlayerInfoManager.GetSteamID(__instance); if (steamID == null) { return true; } Logger.Log("steamId = " + steamID); if (ConfigurationFile.bypassAdmins.Value) { bool flag = PlayerInfoManager.IsPlayerLocalAdmin(); Logger.Log($"isAdmin: {flag}"); if (flag) { return true; } flag = PlayerInfoManager.IsAdmin(steamID); Logger.Log($"{steamID} isAdmin: {flag}"); if (flag) { return true; } } if (!IsAllowed(steamID, piece)) { ProfessionData professionData = PlayerInfoManager.GetProfessionData(piece); string errorMessage = GetErrorMessage(ConfigurationFile.unavailablePieceMessage.Value, professionData.professionName); ((Character)__instance).Message((MessageType)2, errorMessage, 0, (Sprite)null); return false; } if (!IsAllowedByLevel(__instance, piece)) { ProfessionData professionData2 = PlayerInfoManager.GetProfessionData(piece); string value = ConfigurationFile.unavailablePieceLevelMessage.Value; string replace = professionData2.MinSkillLevel.ToString(); Localization instance = Localization.instance; SkillType skillType = professionData2.SkillType; string errorMessage2 = GetErrorMessage(value, replace, instance.Localize("$skill_" + ((object)(SkillType)(ref skillType)).ToString().ToLower())); ((Character)__instance).Message((MessageType)2, errorMessage2, 0, (Sprite)null); return false; } Logger.Log("**Player IS PIECE ALLOWED"); return true; } public static bool IsAllowed(string steamId, Piece piece) { Logger.Log("Piece.m_name: " + piece.m_name + ", Piece.name: " + ((Object)piece).name); ProfessionData professionData = PlayerInfoManager.GetProfessionData(piece); Logger.Log($"Condition: {professionData == null}"); Logger.Log("pieceProfessionData = " + professionData); if (professionData?.ObjectName == null) { return true; } string playerProfession = PlayerInfoManager.GetPlayerProfession(); bool flag = playerProfession != null; Logger.Log(steamId + " hasAProfession: " + flag); if (!flag) { return false; } bool flag2 = professionData.professionName.ToLower().Contains(playerProfession.ToLower()); Logger.Log($"professionMatching: {professionData.professionName.ToLower()} vs {playerProfession.ToLower()} = {flag2}"); return flag2; } public static bool IsAllowedByLevel(Player player, Piece piece) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //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) ProfessionData professionData = PlayerInfoManager.GetProfessionData(piece); if (professionData != null && professionData.MinSkillLevel > 0 && (int)professionData.SkillType > 0) { List<Skill> skillList = ((Character)player).GetSkills().GetSkillList(); for (int i = 0; i < skillList.Count; i++) { Skill val = skillList[i]; if (val.m_info.m_skill == professionData.SkillType) { int num = (int)val.m_level; bool flag = num >= professionData.MinSkillLevel; Logger.Log($"currentLevel {num} necessaryLevel {professionData.MinSkillLevel} professionMatching: {flag}"); return flag; } } } return true; } private static string GetErrorMessage(string message, string replace0 = null, string replace1 = null) { if (replace0 != null) { message = message.Replace("{0}", replace0); } if (replace1 != null) { message = message.Replace("{1}", replace1); } return message; } } [HarmonyPatch(typeof(Player), "CheckCanRemovePiece")] public static class CheckCanRemovePiecePatch { private static bool Prefix(Player __instance, Piece piece) { //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) Logger.Log("**CheckCanRemovePiecePatch CheckCanRemovePiece PREFIX"); string steamID = PlayerInfoManager.GetSteamID(__instance); if (steamID == null) { return true; } Logger.Log("steamId = " + steamID); if (ConfigurationFile.bypassAdmins.Value) { bool flag = PlayerInfoManager.IsPlayerLocalAdmin(); Logger.Log($"CheckCanRemovePiece.Prefix IsPlayerLocalAdmin: {flag}"); if (flag) { return true; } Logger.Log("CheckCanRemovePiece.Prefix " + steamID + " IsAdmin: " + PlayerInfoManager.IsAdmin(steamID)); } if (!PlacePiecePatch.IsAllowed(steamID, piece)) { ProfessionData professionData = PlayerInfoManager.GetProfessionData(piece); string errorMessage = GetErrorMessage(ConfigurationFile.unremovablePieceMessage.Value, professionData.professionName); ((Character)__instance).Message((MessageType)2, errorMessage, 0, (Sprite)null); return false; } if (!PlacePiecePatch.IsAllowedByLevel(__instance, piece)) { ProfessionData professionData2 = PlayerInfoManager.GetProfessionData(piece); string value = ConfigurationFile.unremovablePieceLevelMessage.Value; string replace = professionData2.MinSkillLevel.ToString(); Localization instance = Localization.instance; SkillType skillType = professionData2.SkillType; string errorMessage2 = GetErrorMessage(value, replace, instance.Localize("$skill_" + ((object)(SkillType)(ref skillType)).ToString().ToLower())); ((Character)__instance).Message((MessageType)2, errorMessage2, 0, (Sprite)null); return false; } Logger.Log("**Player IS ALLOWED TO REMOVE PIECE"); return true; } private static string GetErrorMessage(string message, string replace0 = null, string replace1 = null) { if (replace0 != null) { message = message.Replace("{0}", replace0); } if (replace1 != null) { message = message.Replace("{1}", replace1); } return message; } } [HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")] public static class RecipeCraftPatch { private static bool Prefix(InventoryGui __instance) { //IL_0127: 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) Logger.Log("**RecipeCraftPatch OnCraftPressed PREFIX"); Recipe selectedRecipe = GetSelectedRecipe(__instance); Player localPlayer = Player.m_localPlayer; if ((Object)(object)selectedRecipe == (Object)null || (Object)(object)localPlayer == (Object)null) { Logger.LogError("Error detecting recipe or player. Continue as vanilla."); return true; } ProfessionData professionData = PlayerInfoManager.GetProfessionData(selectedRecipe); string text = professionData?.professionName; Logger.Log("professionData.professionName = " + text); if (text == null) { Logger.Log("No profession assigned to recipe. Skipping."); return true; } Logger.Log("ProfessionData for recipe " + ((Object)selectedRecipe).name + " with professionName: " + text); Logger.Log("ProfessionData: " + professionData.ToString()); if (!PlayerMeetsProfessionRequirement(professionData)) { string errorMessage = GetErrorMessage(ConfigurationFile.unavailableRecipeMessage.Value, text); ((Character)localPlayer).Message((MessageType)2, errorMessage, 0, (Sprite)null); return false; } if (!PlayerMeetsProfessionLevelRequirement(localPlayer, professionData)) { string value = ConfigurationFile.unavailableRecipeLevelMessage.Value; string replace = professionData.MinSkillLevel.ToString(); Localization instance = Localization.instance; SkillType skillType = professionData.SkillType; string errorMessage2 = GetErrorMessage(value, replace, instance.Localize("$skill_" + ((object)(SkillType)(ref skillType)).ToString().ToLower())); ((Character)localPlayer).Message((MessageType)2, errorMessage2, 0, (Sprite)null); return false; } Logger.Log("**Player IS RECIPE ALLOWED"); return true; } private static string GetErrorMessage(string message, string replace0 = null, string replace1 = null) { if (replace0 != null) { message = message.Replace("{0}", replace0); } if (replace1 != null) { message = message.Replace("{1}", replace1); } return message; } private static Recipe GetSelectedRecipe(InventoryGui instance) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown object privateValue = GameManager.GetPrivateValue(instance, "m_selectedRecipe"); FieldInfo[] fields = privateValue.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo fieldInfo = null; FieldInfo[] array = fields; foreach (FieldInfo fieldInfo2 in array) { if (fieldInfo2.Name.Contains("Recipe")) { Logger.Log("Recipe attribute found"); fieldInfo = fieldInfo2; break; } } Recipe val = (Recipe)(fieldInfo?.GetValue(privateValue)); Logger.Log("recipe: " + (object)val); return val; } private static bool PlayerMeetsProfessionRequirement(ProfessionData professionData) { string playerProfession = PlayerInfoManager.GetPlayerProfession(); Logger.Log("PlayerMeetsProfessionRequirement: " + playerProfession + " vs " + professionData.professionName); return playerProfession == professionData.professionName; } private static bool PlayerMeetsProfessionLevelRequirement(Player player, ProfessionData professionData) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_0054: 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) if (!ConfigurationFile.bypassAdmins.Value && professionData != null && professionData.ObjectName != null && professionData.MinSkillLevel > 0 && (int)professionData.SkillType > 0) { List<Skill> skillList = ((Character)player).GetSkills().GetSkillList(); for (int i = 0; i < skillList.Count; i++) { Skill val = skillList[i]; if (val.m_info.m_skill == professionData.SkillType) { int num = (int)val.m_level; bool flag = num >= professionData.MinSkillLevel; Logger.Log($"PlayerMeetsProfessionLevelRequirement: currentLevel {num} necessaryLevel {professionData.MinSkillLevel}. meets: {flag}"); return flag; } } } return true; } } } namespace CraftByProfession.Managers { public class GameManager { public static object GetPrivateValue(object obj, string name, BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic) { return obj.GetType().GetField(name, bindingAttr).GetValue(obj); } } public class ResourcesManager { private static Dictionary<string, Sprite> cachedSprites = new Dictionary<string, Sprite>(); private static Dictionary<string, TMP_FontAsset> cachedFonts = new Dictionary<string, TMP_FontAsset>(); public static Sprite getSprite(string name) { if (!cachedSprites.ContainsKey(name)) { Logger.Log("Finding " + name + " sprite..."); Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>(); foreach (Sprite val in array) { if (((Object)val).name == name) { Logger.Log(name + " sprite found."); cachedSprites.Add(name, val); return val; } } Logger.Log(name + " sprite NOT found."); return null; } return GeneralExtensions.GetValueSafe<string, Sprite>(cachedSprites, name); } public static TMP_FontAsset getFontAsset(string name) { if (!cachedFonts.ContainsKey(name)) { Logger.Log("Finding " + name + " font..."); TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if (((Object)val).name == name) { Logger.Log(name + " font found."); cachedFonts.Add(name, val); return val; } } Logger.Log(name + " font NOT found."); return null; } return GeneralExtensions.GetValueSafe<string, TMP_FontAsset>(cachedFonts, name); } public static void TriggerLightningEffect() { SEMan sEMan = ((Character)Player.m_localPlayer).GetSEMan(); if ((Object)(object)sEMan.GetStatusEffect("Lightning".GetHashCode()) == (Object)null) { StatusEffect val = sEMan.AddStatusEffect("Lightning".GetHashCode(), false, 0, 0f); val.m_ttl = 5f; } } } public class UIManager { private static readonly Color BUTTON_VANILLA_COLOR = new Color(1f, 0.7176f, 0.3603f); public static TextMeshProUGUI createUIText(string goName, Transform parent, Vector2 pos, string text, int fontSize, string fontName = null) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(goName, new Type[1] { typeof(TextMeshProUGUI) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchoredPosition = pos; TextMeshProUGUI component2 = val.GetComponent<TextMeshProUGUI>(); if (fontName != null) { ((TMP_Text)component2).font = ResourcesManager.getFontAsset(fontName); } ((TMP_Text)component2).fontSize = fontSize; ((TMP_Text)component2).text = text; return component2; } public static Button createUIButton(string goName, Transform copyFrom, Transform parent, Vector2 pos, string text) { //IL_002c: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown GameObject val = Object.Instantiate<GameObject>(((Component)copyFrom).gameObject, parent); ((Object)val).name = goName; val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchoredPosition = pos; TextMeshProUGUI componentInChildren = val.GetComponentInChildren<TextMeshProUGUI>(); ((TMP_Text)componentInChildren).text = text; ((TMP_Text)componentInChildren).fontStyle = (FontStyles)0; ((Graphic)componentInChildren).color = BUTTON_VANILLA_COLOR; ((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)514; Button component2 = val.GetComponent<Button>(); component2.onClick = new ButtonClickedEvent(); return component2; } public static Image createUIImage(string goName, Transform parent, Vector2 size, Vector2 pos, Sprite sprite, bool shadowBkg = false) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001e: 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_0045: 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) //IL_006a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(goName); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent<RectTransform>(); val2.sizeDelta = size; val2.anchoredPosition = pos; if (shadowBkg) { Image val3 = createUIImage(goName + "Bkg", val.transform, size, Vector2.zero, null); ((Graphic)val3).color = new Color(0f, 0f, 0f, 0.5f); } Image val4 = val.AddComponent<Image>(); val4.sprite = sprite; return val4; } private static byte[] ReadEmbeddedFileBytes(string name) { using MemoryStream memoryStream = new MemoryStream(); Assembly.GetExecutingAssembly().GetManifestResourceStream("CraftByProfession." + name)?.CopyTo(memoryStream); return memoryStream.ToArray(); } private static Texture2D loadTexture(string name) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown Texture2D val = new Texture2D(0, 0); ImageConversion.LoadImage(val, ReadEmbeddedFileBytes("icons." + name)); return val; } public static Sprite loadSprite(string name, int width, int height) { //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) return Sprite.Create(loadTexture(name), new Rect(0f, 0f, (float)width, (float)height), Vector2.zero); } public static Sprite LoadSpriteFromFile(string filePath) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0071: 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 (!File.Exists(filePath)) { Debug.LogError((object)("File not found at path: " + filePath)); return null; } try { byte[] array = File.ReadAllBytes(filePath); Texture2D val = new Texture2D(2, 2); if (!ImageConversion.LoadImage(val, array)) { Debug.LogError((object)"Failed to load texture from image data."); return null; } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } catch (Exception ex) { Debug.LogError((object)("Failed to load image from file: " + ex.Message)); return null; } } public static Sprite LoadSpriteFromEmbedded(string embeddedPath) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0048: 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) try { byte[] array = ReadEmbeddedFileBytes(embeddedPath); Texture2D val = new Texture2D(2, 2); if (!ImageConversion.LoadImage(val, array)) { Debug.LogError((object)"Failed to load texture from image data."); return null; } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } catch (Exception ex) { Debug.LogError((object)("Failed to load image from file: " + ex.Message)); return null; } } public static void CloseInventoryGui() { ((Component)InventoryGui.instance.m_textsDialog).gameObject.SetActive(false); InventoryGui.instance.Hide(); } } public class PlayerInfoManager { public static ProfessionData GetProfessionData(Piece piece) { if (LoaderPiecePatch.TOOL_CULTIVATE == ((Object)piece).name) { return LoaderPiecePatch.cultivate; } if (LoaderPiecePatch.TOOL_REPLANT == ((Object)piece).name) { return LoaderPiecePatch.replant; } if (LoaderPiecePatch.TOOL_PAVE == ((Object)piece).name) { return LoaderPiecePatch.paved; } if (LoaderPiecePatch.TOOL_RAISE == ((Object)piece).name) { return LoaderPiecePatch.paved; } string name = ((Object)piece).name.Replace("$", "").Replace("(Clone)", ""); Logger.Log("Finding gameObject starting with " + name); GameObject val = ZNetScene.instance.m_prefabs.Find((GameObject i) => ((Object)i).name.StartsWith(name)); ProfessionDataComponent professionDataComponent = ((val != null) ? val.GetComponent<ProfessionDataComponent>() : null); if ((Object)(object)professionDataComponent == (Object)null) { return null; } return professionDataComponent.getProfessionData(); } public static string GetPlayerProfession() { string[] array = ConfigurationFile.professions.Value.Split(new char[1] { ',' }); List<string> list = new List<string>(); for (int i = 0; i < array.Length; i++) { list.Add(array[i]); } foreach (string uniqueKey in Player.m_localPlayer.GetUniqueKeys()) { string text = uniqueKey.Replace("HDF_", ""); if (list.Contains(text)) { return text; } } return null; } public static string GetSteamID(Player player) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_004b: 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_0058: 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_0079: 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_0080: 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) ZNetView val = (ZNetView)GameManager.GetPrivateValue(player, "m_nview"); string text = ((object)val.GetZDO()).ToString(); Logger.Log("characterIDToFind = " + text); List<PlayerInfo> playerList = ZNet.instance.GetPlayerList(); foreach (PlayerInfo item in playerList) { ZDOID characterID = item.m_characterID; Logger.Log("playerInfo.m_characterID.ToString() = " + ((object)(ZDOID)(ref characterID)).ToString()); characterID = item.m_characterID; if (((object)(ZDOID)(ref characterID)).ToString() == text) { Logger.Log("Match characterIDToFind!"); string host = item.m_host; Logger.Log("steamID found: " + host); return host; } } return ""; } public static ProfessionData GetProfessionData(Recipe recipe) { Logger.Log("recipe.name " + ((Object)recipe).name + " firstPart " + ((Object)recipe).name.Split(new char[1] { ' ' })[0]); ProfessionData value; return RecipeManager.recipesProfessionData.TryGetValue(((Object)recipe).name.Split(new char[1] { ' ' })[0], out value) ? value : null; } public static bool IsPlayerLocalAdmin() { if ((Object)(object)ZNet.instance == (Object)null) { Logger.LogWarning("ZNet is not initialized in IsAdmin. returning false."); return false; } try { return ZNet.instance.LocalPlayerIsAdminOrHost(); } catch (Exception s) { Logger.LogWarning(s); } return false; } public static bool IsAdmin(string steamId) { if ((Object)(object)ZNet.instance == (Object)null) { Logger.LogWarning("ZNet is not initialized in IsAdmin. returning false."); return false; } try { return ZNet.instance.IsAdmin(steamId); } catch (Exception s) { Logger.LogWarning(s); } return false; } } public class RecipeManager { public static Dictionary<string, ProfessionData> recipesProfessionData = new Dictionary<string, ProfessionData>(); public static ProfessionData FindRecipeByItemName(string itemName) { foreach (ProfessionData value in recipesProfessionData.Values) { if (value.ItemName == itemName) { return value; } } return null; } } } namespace FxResources.System.Buffers { internal static class SR { } } namespace System { internal static class <f389ca43-32bf-4e24-ad8c-a6ed5efddff3>SR { private static ResourceManager s_resourceManager; private static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(ResourceType)); internal static Type ResourceType { get; } = typeof(FxResources.System.Buffers.SR); internal static string ArgumentException_BufferNotFromPool => GetResourceString("ArgumentException_BufferNotFromPool", null); [MethodImpl(MethodImplOptions.NoInlining)] private static bool UsingResourceKeys() { return false; } internal static string GetResourceString(string resourceKey, string defaultString) { string text = null; try { text = ResourceManager.GetString(resourceKey); } catch (MissingManifestResourceException) { } if (defaultString != null && resourceKey.Equals(text, StringComparison.Ordinal)) { return defaultString; } return text; } internal static string Format(string resourceFormat, params object[] args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + string.Join(", ", args); } return string.Format(resourceFormat, args); } return resourceFormat; } internal static string Format(string resourceFormat, object p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(resourceFormat, p1); } internal static string Format(string resourceFormat, object p1, object p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(resourceFormat, p1, p2); } internal static string Format(string resourceFormat, object p1, object p2, object p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(resourceFormat, p1, p2, p3); } } } namespace System.Buffers { internal abstract class ArrayPool<T> { private static ArrayPool<T> s_sharedInstance; public static ArrayPool<T> Shared { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Volatile.Read(ref s_sharedInstance) ?? EnsureSharedCreated(); } } [MethodImpl(MethodImplOptions.NoInlining)] private static ArrayPool<T> EnsureSharedCreated() { Interlocked.CompareExchange(ref s_sharedInstance, Create(), null); return s_sharedInstance; } public static ArrayPool<T> Create() { return new DefaultArrayPool<T>(); } public static ArrayPool<T> Create(int maxArrayLength, int maxArraysPerBucket) { return new DefaultArrayPool<T>(maxArrayLength, maxArraysPerBucket); } public abstract T[] Rent(int minimumLength); public abstract void Return(T[] array, bool clearArray = false); } [EventSource(Name = "System.Buffers.ArrayPoolEventSource")] internal sealed class ArrayPoolEventSource : EventSource { internal enum BufferAllocatedReason { Pooled, OverMaximumSize, PoolExhausted } internal static readonly System.Buffers.ArrayPoolEventSource Log = new System.Buffers.ArrayPoolEventSource(); [Event(1, Level = EventLevel.Verbose)] internal unsafe void BufferRented(int bufferId, int bufferSize, int poolId, int bucketId) { EventData* ptr = stackalloc EventData[4]; *ptr = new EventData { Size = 4, DataPointer = (IntPtr)(&bufferId) }; ptr[1] = new EventData { Size = 4, DataPointer = (IntPtr)(&bufferSize) }; ptr[2] = new EventData { Size = 4, DataPointer = (IntPtr)(&poolId) }; ptr[3] = new EventData { Size = 4, DataPointer = (IntPtr)(&bucketId) }; WriteEventCore(1, 4, ptr); } [Event(2, Level = EventLevel.Informational)] internal unsafe void BufferAllocated(int bufferId, int bufferSize, int poolId, int bucketId, BufferAllocatedReason reason) { EventData* ptr = stackalloc EventData[5]; *ptr = new EventData { Size = 4, DataPointer = (IntPtr)(&bufferId) }; ptr[1] = new EventData { Size = 4, DataPointer = (IntPtr)(&bufferSize) }; ptr[2] = new EventData { Size = 4, DataPointer = (IntPtr)(&poolId) }; ptr[3] = new EventData { Size = 4, DataPointer = (IntPtr)(&bucketId) }; ptr[4] = new EventData { Size = 4, DataPointer = (IntPtr)(&reason) }; WriteEventCore(2, 5, ptr); } [Event(3, Level = EventLevel.Verbose)] internal void BufferReturned(int bufferId, int bufferSize, int poolId) { WriteEvent(3, bufferId, bufferSize, poolId); } } internal sealed class DefaultArrayPool<T> : ArrayPool<T> { private sealed class Bucket { internal readonly int _bufferLength; private readonly T[][] _buffers; private readonly int _poolId; private SpinLock _lock; private int _index; internal int Id => GetHashCode(); internal Bucket(int bufferLength, int numberOfBuffers, int poolId) { _lock = new SpinLock(Debugger.IsAttached); _buffers = new T[numberOfBuffers][]; _bufferLength = bufferLength; _poolId = poolId; } internal T[] Rent() { T[][] buffers = _buffers; T[] array = null; bool lockTaken = false; bool flag = false; try { _lock.Enter(ref lockTaken); if (_index < buffers.Length) { array = buffers[_index]; buffers[_index++] = null; flag = array == null; } } finally { if (lockTaken) { _lock.Exit(useMemoryBarrier: false); } } if (flag) { array = new T[_bufferLength]; System.Buffers.ArrayPoolEventSource log = System.Buffers.ArrayPoolEventSource.Log; if (log.IsEnabled()) { log.BufferAllocated(array.GetHashCode(), _bufferLength, _poolId, Id, System.Buffers.ArrayPoolEventSource.BufferAllocatedReason.Pooled); } } return array; } internal void Return(T[] array) { if (array.Length != _bufferLength) { throw new ArgumentException(<f389ca43-32bf-4e24-ad8c-a6ed5efddff3>SR.ArgumentException_BufferNotFromPool, "array"); } bool lockTaken = false; try { _lock.Enter(ref lockTaken); if (_index != 0) { _buffers[--_index] = array; } } finally { if (lockTaken) { _lock.Exit(useMemoryBarrier: false); } } } } private const int DefaultMaxArrayLength = 1048576; private const int DefaultMaxNumberOfArraysPerBucket = 50; private static T[] s_emptyArray; private readonly Bucket[] _buckets; private int Id => GetHashCode(); internal DefaultArrayPool() : this(1048576, 50) { } internal DefaultArrayPool(int maxArrayLength, int maxArraysPerBucket) { if (maxArrayLength <= 0) { throw new ArgumentOutOfRangeException("maxArrayLength"); } if (maxArraysPerBucket <= 0) { throw new ArgumentOutOfRangeException("maxArraysPerBucket"); } if (maxArrayLength > 1073741824) { maxArrayLength = 1073741824; } else if (maxArrayLength < 16) { maxArrayLength = 16; } int id = Id; int num = System.Buffers.Utilities.SelectBucketIndex(maxArrayLength); Bucket[] array = new Bucket[num + 1]; for (int i = 0; i < array.Length; i++) { array[i] = new Bucket(System.Buffers.Utilities.GetMaxSizeForBucket(i), maxArraysPerBucket, id); } _buckets = array; } public override T[] Rent(int minimumLength) { if (minimumLength < 0) { throw new ArgumentOutOfRangeException("minimumLength"); } if (minimumLength == 0) { return s_emptyArray ?? (s_emptyArray = new T[0]); } System.Buffers.ArrayPoolEventSource log = System.Buffers.ArrayPoolEventSource.Log; T[] array = null; int num = System.Buffers.Utilities.SelectBucketIndex(minimumLength); if (num < _buckets.Length) { int num2 = num; do { array = _buckets[num2].Rent(); if (array != null) { if (log.IsEnabled()) { log.BufferRented(array.GetHashCode(), array.Length, Id, _buckets[num2].Id); } return array; } } while (++num2 < _buckets.Length && num2 != num + 2); array = new T[_buckets[num]._bufferLength]; } else { array = new T[minimumLength]; } if (log.IsEnabled()) { int hashCode = array.GetHashCode(); int bucketId = -1; log.BufferRented(hashCode, array.Length, Id, bucketId); log.BufferAllocated(hashCode, array.Length, Id, bucketId, (num >= _buckets.Length) ? System.Buffers.ArrayPoolEventSource.BufferAllocatedReason.OverMaximumSize : System.Buffers.ArrayPoolEventSource.BufferAllocatedReason.PoolExhausted); } return array; } public override void Return(T[] array, bool clearArray = false) { if (array == null) { throw new ArgumentNullException("array"); } if (array.Length == 0) { return; } int num = System.Buffers.Utilities.SelectBucketIndex(array.Length); if (num < _buckets.Length) { if (clearArray) { Array.Clear(array, 0, array.Length); } _buckets[num].Return(array); } System.Buffers.ArrayPoolEventSource log = System.Buffers.ArrayPoolEventSource.Log; if (log.IsEnabled()) { log.BufferReturned(array.GetHashCode(), array.Length, Id); } } } internal static class Utilities { [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int SelectBucketIndex(int bufferSize) { uint num = (uint)(bufferSize - 1) >> 4; int num2 = 0; if (num > 65535) { num >>= 16; num2 = 16; } if (num > 255) { num >>= 8; num2 += 8; } if (num > 15) { num >>= 4; num2 += 4; } if (num > 3) { num >>= 2; num2 += 2; } if (num > 1) { num >>= 1; num2++; } return num2 + (int)num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int GetMaxSizeForBucket(int binIndex) { return 16 << binIndex; } } } 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 { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class NullablePublicOnlyAttribute : Attribute { public readonly bool IncludesInternals; public NullablePublicOnlyAttribute(bool P_0) { IncludesInternals = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FxResources.System.IO.Pipelines { internal static class SR { } } namespace System { internal static class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>SR { private static readonly bool s_usingResourceKeys = GetUsingResourceKeysSwitchValue(); private static ResourceManager s_resourceManager; internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(FxResources.System.IO.Pipelines.SR))); internal static string AdvanceToInvalidCursor => GetResourceString("AdvanceToInvalidCursor"); internal static string ArgumentOutOfRange_NeedPosNum => GetResourceString("ArgumentOutOfRange_NeedPosNum"); internal static string ConcurrentOperationsNotSupported => GetResourceString("ConcurrentOperationsNotSupported"); internal static string FlushCanceledOnPipeWriter => GetResourceString("FlushCanceledOnPipeWriter"); internal static string GetResultBeforeCompleted => GetResourceString("GetResultBeforeCompleted"); internal static string InvalidExaminedOrConsumedPosition => GetResourceString("InvalidExaminedOrConsumedPosition"); internal static string InvalidExaminedPosition => GetResourceString("InvalidExaminedPosition"); internal static string InvalidZeroByteRead => GetResourceString("InvalidZeroByteRead"); internal static string ObjectDisposed_StreamClosed => GetResourceString("ObjectDisposed_StreamClosed"); internal static string NoReadingOperationToComplete => GetResourceString("NoReadingOperationToComplete"); internal static string NotSupported_UnreadableStream => GetResourceString("NotSupported_UnreadableStream"); internal static string NotSupported_UnwritableStream => GetResourceString("NotSupported_UnwritableStream"); internal static string ReadCanceledOnPipeReader => GetResourceString("ReadCanceledOnPipeReader"); internal static string ReaderAndWriterHasToBeCompleted => GetResourceString("ReaderAndWriterHasToBeCompleted"); internal static string ReadingAfterCompleted => GetResourceString("ReadingAfterCompleted"); internal static string ReadingIsInProgress => GetResourceString("ReadingIsInProgress"); internal static string WritingAfterCompleted => GetResourceString("WritingAfterCompleted"); internal static string UnflushedBytesNotSupported => GetResourceString("UnflushedBytesNotSupported"); private static bool GetUsingResourceKeysSwitchValue() { if (!AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled)) { return false; } return isEnabled; } internal static bool UsingResourceKeys() { return s_usingResourceKeys; } private static string GetResourceString(string resourceKey) { if (UsingResourceKeys()) { return resourceKey; } string result = null; try { result = ResourceManager.GetString(resourceKey); } catch (MissingManifestResourceException) { } return result; } private static string GetResourceString(string resourceKey, string defaultString) { string resourceString = GetResourceString(resourceKey); if (!(resourceKey == resourceString) && resourceString != null) { return resourceString; } return defaultString; } internal static string Format(string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(resourceFormat, p1); } internal static string Format(string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(resourceFormat, p1, p2); } internal static string Format(string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(resourceFormat, p1, p2, p3); } internal static string Format(string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(resourceFormat, args); } return resourceFormat; } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(provider, resourceFormat, p1); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(provider, resourceFormat, p1, p2); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(provider, resourceFormat, p1, p2, p3); } internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(provider, resourceFormat, args); } return resourceFormat; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>DisallowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>MaybeNullWhenAttribute : Attribute { public bool ReturnValue { get; } public <51b2773e-ed85-4f48-bea9-0bd26c07cd62>MaybeNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public <51b2773e-ed85-4f48-bea9-0bd26c07cd62>NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>NotNullIfNotNullAttribute : Attribute { public string ParameterName { get; } public <51b2773e-ed85-4f48-bea9-0bd26c07cd62>NotNullIfNotNullAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Method, Inherited = false)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>DoesNotReturnAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public <51b2773e-ed85-4f48-bea9-0bd26c07cd62>DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>MemberNotNullAttribute : Attribute { public string[] Members { get; } public <51b2773e-ed85-4f48-bea9-0bd26c07cd62>MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public <51b2773e-ed85-4f48-bea9-0bd26c07cd62>MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public <51b2773e-ed85-4f48-bea9-0bd26c07cd62>MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public <51b2773e-ed85-4f48-bea9-0bd26c07cd62>MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } } namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] internal sealed class <51b2773e-ed85-4f48-bea9-0bd26c07cd62>LibraryImportAttribute : Attribute { public string LibraryName { get; } public string? EntryPoint { get; set; } public <51b2773e-ed85-4f48-bea9-0bd26c07cd62>StringMarshalling StringMarshalling { get; set; } public Type? StringMarshallingCustomType { get; set; } public bool SetLastError { get; set; } public <51b2773e-ed85-4f48-bea9-0bd26c07cd62>LibraryImportAttribute(string libraryName) { LibraryName = libraryName; } } internal enum <51b2773e-ed85-4f48-bea9-0bd26c07cd62>StringMarshalling { Custom, Utf8, Utf16 } } namespace System.Threading { internal static class CancellationTokenExtensions { internal static CancellationTokenRegistration UnsafeRegister(this CancellationToken cancellationToken, Action<object> callback, object state) { return cancellationToken.Register(callback, state); } } } namespace System.Threading.Tasks { internal static class TaskToAsyncResult { private sealed class TaskAsyncResult : IAsyncResult { internal readonly Task _task; private readonly AsyncCallback _callback; public object AsyncState { get; } public bool CompletedSynchronously { get; } public bool IsCompleted => _task.IsCompleted; public WaitHandle AsyncWaitHandle => ((IAsyncResult)_task).AsyncWaitHandle; internal TaskAsyncResult(Task task, object state, AsyncCallback callback) { _task = task; AsyncState = state; if (task.IsCompleted) { CompletedSynchronously = true; callback?.Invoke(this); } else if (callback != null) { _callback = callback; _task.ConfigureAwait(continueOnCapturedContext: false).GetAwaiter().OnCompleted(delegate { _callback(this); }); } } } public static IAsyncResult Begin(Task task, AsyncCallback? callback, object? state) { if (task == null) { throw new ArgumentNullException("task"); } return new TaskAsyncResult(task, state, callback); } public static void End(IAsyncResult asyncResult) { Unwrap(asyncResult).GetAwaiter().GetResult(); } public static TResult End<TResult>(IAsyncResult asyncResult) { return Unwrap<TResult>(asyncResult).GetAwaiter().GetResult(); } public static Task Unwrap(IAsyncResult asyncResult) { if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } return (asyncResult as TaskAsyncResult)?._task ?? throw new ArgumentException(null, "asyncResult"); } public static Task<TResult> Unwrap<TResult>(IAsyncResult asyncResult) { if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } return ((asyncResult as TaskAsyncResult)?._task as Task<TResult>) ?? throw new ArgumentException(null, "asyncResult"); } } } namespace System.IO { internal static class StreamHelpers { public static void ValidateCopyToArgs(Stream source, Stream destination, int bufferSize) { if (destination == null) { throw new ArgumentNullException("destination"); } if (bufferSize <= 0) { throw new ArgumentOutOfRangeException("bufferSize", bufferSize, <51b2773e-ed85-4f48-bea9-0bd26c07cd62>SR.ArgumentOutOfRange_NeedPosNum); } bool canRead = source.CanRead; if (!canRead && !source.CanWrite) { throw new ObjectDisposedException(null, <51b2773e-ed85-4f48-bea9-0bd26c07cd62>SR.ObjectDisposed_StreamClosed); } bool canWrite = destination.CanWrite; if (!canWrite && !destination.CanRead) { throw new ObjectDisposedException("destination", <51b2773e-ed85-4f48-bea9-0bd26c07cd62>SR.ObjectDisposed_StreamClosed); } if (!canRead) { throw new NotSupportedException(<51b2773e-ed85-4f48-bea9-0bd26c07cd62>SR.NotSupported_UnreadableStream); } if (!canWrite) { throw new NotSupportedException(<51b2773e-ed85-4f48-bea9-0bd26c07cd62>SR.NotSupported_UnwritableStream); } } } } namespace System.IO.Pipelines { internal sealed class BufferSegment : ReadOnlySequenceSegment<byte> { private IMemoryOwner<byte> _memoryOwner; private byte[] _array; private BufferSegment _next; private int _end; public int End { get { return _end; } set { _end = value; base.Memory = AvailableMemory.Slice(0, value); } } public BufferSegment? NextSegment { get { return _next; } set { base.Next = value; _next = value; } } internal object? MemoryOwner => ((object)_memoryOwner) ?? ((object)_array); public Memory<byte> AvailableMemory { get; private set; } public int Length => End; public int WritableBytes { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return AvailableMemory.Length - End; } } public void SetOwnedMemory(IMemoryOwner<byte> memoryOwner) { _memoryOwner = memoryOwner; AvailableMemory = memoryOwner.Memory; } public void SetOwnedMemory(byte[] arrayPoolBuffer) { _array = arrayPoolBuffer; AvailableMemory = arrayPoolBuffer; } public void Reset() { ResetMemory(); base.Next = null; base.RunningIndex = 0L; _next = null; } public void ResetMemory() { IMemoryOwner<byte> memoryOwner = _memoryOwner; if (memoryOwner != null) { _memoryOwner = null; memoryOwner.Dispose(); } else { ArrayPool<byte>.Shared.Return(_array); _array = null; } base.Memory = default(ReadOnlyMemory<byte>); _end = 0; AvailableMemory = default(Memory<byte>); } public void SetNext(BufferSegment segment) { NextSegment = segment; segment = this; while (segment.Next != null) { segment.NextSegment.RunningIndex = segment.RunningIndex + segment.Length; segment = segment.NextSegment; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static long GetLength(BufferSegment startSegment, int startIndex, BufferSegment endSegment, int endIndex) { return endSegment.RunningIndex + (uint)endIndex - (startSegment.RunningIndex + (uint)startIndex); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static long GetLength(long startPosition, BufferSegment endSegment, int endIndex) { return endSegment.RunningIndex + (uint)endIndex - startPosition; } } internal readonly struct CompletionData { public Action<object?> Completion { get; } public object? CompletionState { get; } public ExecutionContext? ExecutionContext { get; } public SynchronizationContext? SynchronizationContext { get; } public CompletionData(Action<object?> completion, object? completionState, ExecutionContext? executionContext, SynchronizationContext? synchronizationContext) { Completion = completion; CompletionState = completionState; ExecutionContext = executionContext; SynchronizationContext = synchronizationContext; } } internal struct FlushResult { internal ResultFlags _resultFlags; public bool IsCanceled => (_resultFlags & ResultFlags.Cance