Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CraftFromChestsPlus v1.1.5
plugins\CraftFromChestsPlus.dll
Decompiled 6 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CraftFromChestsPlus.Chest; using CraftFromChestsPlus.Effects; using CraftFromChestsPlus.Localization; using CraftFromChestsPlus.Totem; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("PONEIS")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Craft and build from chests inside a Craft Totem zone (max 200 m)")] [assembly: AssemblyFileVersion("1.1.5.0")] [assembly: AssemblyInformationalVersion("1.1.5+1fefb8f7be7537233096a5bace21382c155c79a4")] [assembly: AssemblyProduct("CraftFromChestsPlus")] [assembly: AssemblyTitle("CraftFromChestsPlus")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.5.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CraftFromChestsPlus { internal static class ModConfig { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<float> Range; internal static ConfigEntry<bool> EnableCraftFromChests; internal static ConfigEntry<bool> EnableBuildFromChests; internal static ConfigEntry<bool> EnableSmeltFromChests; internal static ConfigEntry<bool> RequireTotem; internal static ConfigEntry<KeyCode> RangeHoldKey; internal static ConfigEntry<bool> BlockCameraZoom; internal static ConfigEntry<float> ScrollStep; internal static ConfigEntry<float> MaxAdjustDistance; internal static ConfigEntry<bool> ShowAreaMarker; internal static ConfigEntry<bool> VisualFeedback; internal static ConfigEntry<bool> FlyingItemEffect; internal static ConfigEntry<string> Language; internal static void Bind(ConfigFile config) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown Enabled = config.Bind<bool>("General", "Enabled", true, "Master switch for CraftFromChestsPlus."); Range = config.Bind<float>("General", "Range", 50f, new ConfigDescription("Default zone / chest-pull radius (meters). With a totem, per-totem Alt+scroll can override.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>())); Range.SettingChanged += delegate { NearbyChestService.Invalidate(); }; RequireTotem = config.Bind<bool>("Activation", "RequireTotem", true, "If true: craft/build/smelt from chests only inside a placed Craft Totem zone. If false: always active around the player (uses Range). Edit via Configuration Manager / Mod Settings."); EnableCraftFromChests = config.Bind<bool>("Features", "EnableCraftFromChests", true, "Use chests for workbench / inventory crafting when activation allows."); EnableBuildFromChests = config.Bind<bool>("Features", "EnableBuildFromChests", true, "Use chests for hammer building when activation allows."); EnableSmeltFromChests = config.Bind<bool>("Features", "EnableSmeltFromChests", true, "Use chests for smelter / kiln / furnace ore & fuel when activation allows."); RangeHoldKey = config.Bind<KeyCode>("Controls", "RangeHoldKey", (KeyCode)308, "Hold this key and scroll while looking at a Craft Totem to change its radius. Default LeftAlt."); BlockCameraZoom = config.Bind<bool>("Controls", "BlockCameraZoom", true, "While RangeHoldKey is held, block camera zoom so scroll only changes totem range."); ScrollStep = config.Bind<float>("Controls", "ScrollStep", 2f, new ConfigDescription("Meters added/removed per scroll tick.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), Array.Empty<object>())); MaxAdjustDistance = config.Bind<float>("Controls", "MaxAdjustDistance", 12f, new ConfigDescription("Max distance to a totem for Alt+scroll adjust.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 40f), Array.Empty<object>())); ShowAreaMarker = config.Bind<bool>("Controls", "ShowAreaMarker", true, "Show the totem area circle while adjusting range."); VisualFeedback = config.Bind<bool>("Feedback", "VisualFeedback", true, "Play SmartContainers-style VFX/SFX when items are pulled from chests."); FlyingItemEffect = config.Bind<bool>("Feedback", "FlyingItemEffect", true, "Spawn a short flying item visual from the chest toward you when materials are pulled."); Language = config.Bind<string>("Localization", "Language", "pt-BR", "Language for CraftFromChestsPlus messages. Values: Auto, English, Portuguese, pt-BR."); Language.SettingChanged += delegate { Loc.ApplyLanguagePreference(); }; } internal static bool IsRangeHoldKeyDown() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 //IL_0086: Unknown result type (might be due to invalid IL or missing references) KeyCode value = RangeHoldKey.Value; if ((int)value == 308 || (int)value == 307) { if (!Input.GetKey((KeyCode)308)) { return Input.GetKey((KeyCode)307); } return true; } if ((int)value == 306 || (int)value == 305) { if (!Input.GetKey((KeyCode)306)) { return Input.GetKey((KeyCode)305); } return true; } if ((int)value == 304 || (int)value == 303) { if (!Input.GetKey((KeyCode)304)) { return Input.GetKey((KeyCode)303); } return true; } return Input.GetKey(value); } } [BepInPlugin("poneis.valheim.CraftFromChestsPlus", "CraftFromChestsPlus", "1.1.5")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGUID = "poneis.valheim.CraftFromChestsPlus"; public const string PluginName = "CraftFromChestsPlus"; public const string PluginVersion = "1.1.5"; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); Loc.Init(); TotemPieceFactory.Init(); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "poneis.valheim.CraftFromChestsPlus"); ((Component)this).gameObject.AddComponent<TotemRangeInputListener>(); Log.LogInfo((object)string.Format("{0} {1} loaded. Default range={2:0.#} m", "CraftFromChestsPlus", "1.1.5", ModConfig.Range.Value)); } } } namespace CraftFromChestsPlus.Totem { internal class CraftTotem : MonoBehaviour, Hoverable { internal static readonly int RangeHash = StringExtensionMethods.GetStableHashCode("cfc_range"); private GameObject _marker; private CircleProjector _projector; private float _hideMarkerAt; private bool _forceMarker; private ZNetView _nview; private string _displayNameToken = "cfc_totem_sign_name"; internal void SetDisplayNameToken(string token) { if (!string.IsNullOrEmpty(token)) { _displayNameToken = token; } } private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); if (IsPlacedInstance()) { EnsureMarker(); TotemZoneService.Register(this); } } private void Start() { if (IsPlacedInstance()) { EnsureMarker(); TotemZoneService.Register(this); } } private void OnDestroy() { TotemZoneService.Unregister(this); } internal bool IsPlacedInstance() { if ((Object)(object)this == (Object)null || (Object)(object)((Component)this).transform == (Object)null) { return false; } try { if ((Object)(object)_nview == (Object)null) { _nview = ((Component)this).GetComponent<ZNetView>(); } if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return false; } ZDO zDO = _nview.GetZDO(); return zDO != null && zDO.IsValid(); } catch { return false; } } internal bool IsValid() { return IsPlacedInstance(); } internal float GetRange() { float effectiveRange = NearbyChestService.EffectiveRange; try { ZDO val = (((Object)(object)_nview != (Object)null) ? _nview.GetZDO() : null); if (val != null && val.IsValid()) { float num = val.GetFloat(RangeHash, -1f); if (num >= 5f) { return Mathf.Clamp(num, 5f, 200f); } } } catch { } return effectiveRange; } internal void SetRange(float range) { range = Mathf.Clamp(range, 5f, 200f); try { ZDO val = (((Object)(object)_nview != (Object)null) ? _nview.GetZDO() : null); if (val == null || !val.IsValid()) { return; } val.Set(RangeHash, range); } catch { } ApplyRadius(); NearbyChestService.Invalidate(); } public string GetHoverName() { return Loc.T(_displayNameToken); } public string GetHoverText() { ShowMarkerTemporarily(); float range = GetRange(); string text = BuildFeatureHint(); return Localization.instance.Localize(Loc.T(_displayNameToken) + "\n" + Loc.Tf("cfc_totem_hover", range) + "\n" + Loc.T("cfc_totem_scroll_hint") + (string.IsNullOrEmpty(text) ? "" : ("\n" + text))); } public float GetHoverOffset() { return 0f; } private static string BuildFeatureHint() { List<string> list = new List<string>(3); if (ModConfig.EnableCraftFromChests.Value) { list.Add(Loc.T("cfc_feat_craft")); } if (ModConfig.EnableBuildFromChests.Value) { list.Add(Loc.T("cfc_feat_build")); } if (ModConfig.EnableSmeltFromChests.Value) { list.Add(Loc.T("cfc_feat_smelt")); } if (list.Count != 0) { return string.Join(" · ", list); } return Loc.T("cfc_feat_none"); } internal void ShowMarkerTemporarily() { EnsureMarker(); if (!((Object)(object)_marker == (Object)null)) { TotemZoneService.HideAllMarkersExcept(this); ApplyRadius(); _marker.SetActive(true); if (!_forceMarker) { _hideMarkerAt = Time.time + 0.35f; } } } internal void ShowMarkerForced() { _forceMarker = true; ShowMarkerTemporarily(); } internal void HideMarker() { _forceMarker = false; if ((Object)(object)_marker != (Object)null) { _marker.SetActive(false); } } private void LateUpdate() { if (!_forceMarker && (Object)(object)_marker != (Object)null && _marker.activeSelf && Time.time >= _hideMarkerAt) { _marker.SetActive(false); } } private void EnsureMarker() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_marker != (Object)null)) { Transform val = ((Component)this).transform.Find("cfc_area_marker"); if ((Object)(object)val != (Object)null) { _marker = ((Component)val).gameObject; _projector = _marker.GetComponentInChildren<CircleProjector>(true); _marker.SetActive(false); return; } _marker = new GameObject("cfc_area_marker"); _marker.transform.SetParent(((Component)this).transform, false); _marker.transform.localPosition = Vector3.zero; _projector = _marker.AddComponent<CircleProjector>(); _projector.m_radius = GetRange(); _projector.m_nrOfSegments = 64; _marker.SetActive(false); } } internal void ApplyRadius() { float range = GetRange(); if ((Object)(object)_projector != (Object)null) { _projector.m_radius = range; } } internal static void SetupPrefabMarker(GameObject prefab) { if ((Object)(object)prefab == (Object)null || (Object)(object)prefab.transform.Find("cfc_area_marker") != (Object)null) { return; } GameObject val = null; try { val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("piece_workbench") : null); } catch { } CraftingStation val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<CraftingStation>() : null); if (!((Object)(object)val2?.m_areaMarker == (Object)null)) { GameObject obj2 = Object.Instantiate<GameObject>(val2.m_areaMarker, prefab.transform); ((Object)obj2).name = "cfc_area_marker"; obj2.SetActive(false); CircleProjector componentInChildren = obj2.GetComponentInChildren<CircleProjector>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.m_radius = NearbyChestService.EffectiveRange; componentInChildren.m_nrOfSegments = 64; } } } } internal class CraftZoneLabel : MonoBehaviour { private Transform _label; private TextMesh _text; private void Start() { EnsureLabel(); } private void EnsureLabel() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_label != (Object)null)) { Transform val = ((Component)this).transform.Find("cfc_craft_zone_label"); GameObject val2; if ((Object)(object)val != (Object)null) { val2 = ((Component)val).gameObject; } else { val2 = new GameObject("cfc_craft_zone_label"); val2.transform.SetParent(((Component)this).transform, false); val2.transform.localPosition = new Vector3(0f, 1.55f, 0f); } _label = val2.transform; _text = val2.GetComponent<TextMesh>(); if ((Object)(object)_text == (Object)null) { _text = val2.AddComponent<TextMesh>(); } _text.text = Loc.T("cfc_zone_tag"); _text.anchor = (TextAnchor)4; _text.alignment = (TextAlignment)1; _text.characterSize = 0.06f; _text.fontSize = 48; _text.color = new Color(1f, 0.82f, 0.35f, 1f); _text.fontStyle = (FontStyle)1; } } private void LateUpdate() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) EnsureLabel(); if (!((Object)(object)_label == (Object)null)) { Camera val = Camera.main; if ((Object)(object)val == (Object)null && (Object)(object)GameCamera.instance != (Object)null) { val = ((Component)GameCamera.instance).GetComponent<Camera>(); } if (!((Object)(object)val == (Object)null)) { _label.rotation = Quaternion.LookRotation(_label.position - ((Component)val).transform.position); } } } } internal static class TotemPieceFactory { internal const string SignPieceName = "cfc_craft_totem_sign"; internal const string StatuePieceName = "cfc_craft_totem_statue"; internal const string LegacyPieceName = "cfc_craft_totem"; private static bool _registered; internal static void Init() { PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; PieceManager.OnPiecesRegistered -= OnPiecesRegistered; PieceManager.OnPiecesRegistered += OnPiecesRegistered; } internal static bool IsTotemPrefabName(string name) { if (string.IsNullOrEmpty(name)) { return false; } switch (name) { default: if (!name.StartsWith("cfc_craft_totem_sign") && !name.StartsWith("cfc_craft_totem_statue")) { return name.StartsWith("cfc_craft_totem"); } break; case "cfc_craft_totem_sign": case "cfc_craft_totem_statue": case "cfc_craft_totem": break; } return true; } private static void OnVanillaPrefabsAvailable() { if (_registered) { return; } try { RegisterLocalization(); RegisterPiece("cfc_craft_totem_sign", "sign", "$cfc_totem_sign_name", "$cfc_totem_sign_desc"); RegisterPiece("cfc_craft_totem_statue", "sign", "$cfc_totem_statue_name", "$cfc_totem_statue_desc"); RegisterPiece("cfc_craft_totem", "sign", "$cfc_totem_sign_name", "$cfc_totem_sign_desc"); _registered = true; Plugin.Log.LogInfo((object)"Registered Craft Totem sign pieces."); } catch (Exception arg) { Plugin.Log.LogError((object)$"Failed to register Craft Totems: {arg}"); } } private static RequirementConfig[] TotemRequirements() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown return (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig("Wood", 20, 0, true), new RequirementConfig("Resin", 10, 0, true), new RequirementConfig("Bronze", 5, 0, true) }; } private static void RegisterPiece(string name, string basePrefab, string nameToken, string descToken) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown if (PieceManager.Instance.GetPiece(name) == null) { PieceConfig val = new PieceConfig { Name = nameToken, Description = descToken, PieceTable = PieceTables.Hammer, Category = PieceCategories.Misc, CraftingStation = CraftingStations.Workbench, Requirements = TotemRequirements() }; PieceManager.Instance.AddPiece(new CustomPiece(name, basePrefab, val)); } } private static void OnPiecesRegistered() { FinalizePiece("cfc_craft_totem_sign", "cfc_totem_sign_name"); FinalizePiece("cfc_craft_totem_statue", "cfc_totem_statue_name"); FinalizePiece("cfc_craft_totem", "cfc_totem_sign_name"); } private static void FinalizePiece(string prefabName, string displayToken) { GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName); if ((Object)(object)prefab == (Object)null) { Plugin.Log.LogWarning((object)("Craft Totem prefab '" + prefabName + "' not found after registration.")); return; } CraftTotem craftTotem = prefab.GetComponent<CraftTotem>(); if ((Object)(object)craftTotem == (Object)null) { craftTotem = prefab.AddComponent<CraftTotem>(); } craftTotem.SetDisplayNameToken(displayToken); CraftTotem.SetupPrefabMarker(prefab); Piece component = prefab.GetComponent<Piece>(); if ((Object)(object)component != (Object)null) { component.m_name = "$" + displayToken; component.m_description = "$" + displayToken.Replace("_name", "_desc"); component.m_canBeRemoved = true; ((StaticTarget)component).m_primaryTarget = false; } WearNTear component2 = prefab.GetComponent<WearNTear>(); if ((Object)(object)component2 != (Object)null) { component2.m_noRoofWear = false; component2.m_noSupportWear = false; } EnsureSignIcon(prefab); StripLegacyFulingVisual(prefab); if ((Object)(object)prefab.GetComponent<CraftZoneLabel>() == (Object)null) { prefab.AddComponent<CraftZoneLabel>(); } } private static void StripLegacyFulingVisual(GameObject prefab) { Transform val = prefab.transform.Find("cfc_fuling_visual"); if ((Object)(object)val != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val).gameObject); } Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { string name = ((Object)((Component)val2).transform).name; if (name.IndexOf("cfc_area", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("cfc_craft_zone", StringComparison.OrdinalIgnoreCase) < 0) { val2.enabled = true; } } } Sign component = prefab.GetComponent<Sign>(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = true; } } private static void EnsureSignIcon(GameObject prefab) { Piece component = prefab.GetComponent<Piece>(); if (!((Object)(object)component == (Object)null)) { GameObject prefab2 = PrefabManager.Instance.GetPrefab("sign"); Piece val = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Piece>() : null); if ((Object)(object)val != (Object)null && (Object)(object)val.m_icon != (Object)null) { component.m_icon = val.m_icon; } } } private static void RegisterLocalization() { string text = "{\"cfc_totem_sign_name\":\"Craft Totem (Sign)\",\"cfc_totem_sign_desc\":\"Placed craft-zone sign. Activates craft/build/smelt from nearby chests for all players in range. Hammer → Misc near a Workbench.\",\"cfc_totem_statue_name\":\"Craft Totem (Zone Sign)\",\"cfc_totem_statue_desc\":\"Normal sign with a Craft Zone label. Same zone rules. Hammer → Misc near a Workbench.\",\"cfc_totem_name\":\"Craft Totem\",\"cfc_totem_desc\":\"Activates crafting, building and smelting from nearby chests for all players within range.\",\"cfc_zone_tag\":\"Craft Zone\"}"; string text2 = "{\"cfc_totem_sign_name\":\"Totem de Craft (Placa)\",\"cfc_totem_sign_desc\":\"Placa de zona de craft. Ativa craft/construção/fundição a partir de baús. Martelo → Misc perto da Bancada.\",\"cfc_totem_statue_name\":\"Totem de Craft (Placa Zone)\",\"cfc_totem_statue_desc\":\"Placa normal com etiqueta Craft Zone. Mesmas regras. Martelo → Misc perto da Bancada.\",\"cfc_totem_name\":\"Totem de Craft\",\"cfc_totem_desc\":\"Ativa craft, construção e fundição a partir de baús próximos para todos os jogadores no alcance.\",\"cfc_zone_tag\":\"Craft Zone\"}"; LocalizationManager.Instance.AddJson("English", text); LocalizationManager.Instance.AddJson("Portuguese_Brazilian", text2); } } internal static class TotemRangeService { private static CraftTotem _lastMarker; private static float _nextMsg; internal static void TryAdjustFromScroll(Player player, float scrollY) { if ((Object)(object)player == (Object)null || Mathf.Abs(scrollY) < 0.01f) { return; } CraftTotem craftTotem = TotemZoneService.FindAdjustTarget(player); if ((Object)(object)craftTotem == (Object)null) { if (Time.time >= _nextMsg) { _nextMsg = Time.time + 0.5f; ((Character)player).Message((MessageType)2, Loc.T("cfc_msg_no_totem"), 0, (Sprite)null, false); } return; } float value = ModConfig.ScrollStep.Value; float num = ((scrollY > 0f) ? value : (0f - value)); float range = craftTotem.GetRange() + num; craftTotem.SetRange(range); if (ModConfig.ShowAreaMarker.Value) { if ((Object)(object)_lastMarker != (Object)null && (Object)(object)_lastMarker != (Object)(object)craftTotem) { _lastMarker.HideMarker(); } craftTotem.ShowMarkerForced(); _lastMarker = craftTotem; } ((Character)player).Message((MessageType)2, Loc.Tf("cfc_msg_range", craftTotem.GetRange()), 0, (Sprite)null, false); } internal static void TickMarkers() { if (!ModConfig.IsRangeHoldKeyDown() && (Object)(object)_lastMarker != (Object)null) { _lastMarker.HideMarker(); _lastMarker = null; } } } internal sealed class TotemRangeInputListener : MonoBehaviour { private void Update() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) TotemRangeService.TickMarkers(); if (!ModConfig.IsRangeHoldKeyDown()) { return; } float y = Input.mouseScrollDelta.y; if (!(Mathf.Abs(y) < 0.01f)) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !Console.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus())) { TotemRangeService.TryAdjustFromScroll(localPlayer, y); } } } } internal static class TotemZoneService { private static readonly List<CraftTotem> Totems = new List<CraftTotem>(); private static bool _wasInZone; private static float _nextToast; private const float ToastCooldown = 4f; internal static void Register(CraftTotem totem) { if (!((Object)(object)totem == (Object)null) && totem.IsPlacedInstance() && !Totems.Contains(totem)) { Totems.Add(totem); } } internal static void Unregister(CraftTotem totem) { if (!((Object)(object)totem == (Object)null)) { Totems.Remove(totem); } } internal static void Prune() { for (int num = Totems.Count - 1; num >= 0; num--) { CraftTotem craftTotem = Totems[num]; if ((Object)(object)craftTotem == (Object)null || !craftTotem.IsPlacedInstance()) { Totems.RemoveAt(num); } } } internal static bool IsInZone(Player player) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.Enabled.Value || (Object)(object)player == (Object)null) { return false; } if (!ModConfig.RequireTotem.Value) { return true; } Prune(); if (Totems.Count == 0) { return false; } Vector3 position = ((Component)player).transform.position; for (int i = 0; i < Totems.Count; i++) { CraftTotem craftTotem = Totems[i]; if (!((Object)(object)craftTotem == (Object)null) && craftTotem.IsPlacedInstance()) { float range = craftTotem.GetRange(); float num = range * range; Vector3 val = ((Component)craftTotem).transform.position - position; if (((Vector3)(ref val)).sqrMagnitude <= num) { return true; } } } return false; } internal static float GetActivePullRange(Player player) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return NearbyChestService.EffectiveRange; } if (!ModConfig.RequireTotem.Value) { return NearbyChestService.EffectiveRange; } CraftTotem craftTotem = FindCoveringTotem(((Component)player).transform.position); if ((Object)(object)craftTotem != (Object)null) { return craftTotem.GetRange(); } return NearbyChestService.EffectiveRange; } internal static CraftTotem FindCoveringTotem(Vector3 pos) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Prune(); CraftTotem result = null; float num = float.MaxValue; for (int i = 0; i < Totems.Count; i++) { CraftTotem craftTotem = Totems[i]; if (!((Object)(object)craftTotem == (Object)null) && craftTotem.IsPlacedInstance()) { float range = craftTotem.GetRange(); Vector3 val = ((Component)craftTotem).transform.position - pos; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (!(sqrMagnitude > range * range) && sqrMagnitude < num) { num = sqrMagnitude; result = craftTotem; } } } return result; } internal static CraftTotem FindNearest(Vector3 pos, out float distance) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) Prune(); CraftTotem craftTotem = null; float num = float.MaxValue; for (int i = 0; i < Totems.Count; i++) { CraftTotem craftTotem2 = Totems[i]; if (!((Object)(object)craftTotem2 == (Object)null) && craftTotem2.IsPlacedInstance()) { Vector3 val = ((Component)craftTotem2).transform.position - pos; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; craftTotem = craftTotem2; } } } distance = (((Object)(object)craftTotem != (Object)null) ? Mathf.Sqrt(num) : float.MaxValue); return craftTotem; } internal static CraftTotem FindAdjustTarget(Player player) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return null; } float value = ModConfig.MaxAdjustDistance.Value; CraftTotem result = null; float num = float.MaxValue; Vector3 eyePoint = ((Character)player).GetEyePoint(); Vector3 lookDir = ((Character)player).GetLookDir(); Prune(); for (int i = 0; i < Totems.Count; i++) { CraftTotem craftTotem = Totems[i]; if ((Object)(object)craftTotem == (Object)null || !craftTotem.IsPlacedInstance()) { continue; } float num2 = Vector3.Distance(((Component)player).transform.position, ((Component)craftTotem).transform.position); if (num2 > value) { continue; } Vector3 val = ((Component)craftTotem).transform.position - eyePoint; Vector3 normalized = ((Vector3)(ref val)).normalized; float num3 = Vector3.Dot(lookDir, normalized); if (!(num3 < 0.25f)) { float num4 = num2 * (1.5f - num3); if (num4 < num) { num = num4; result = craftTotem; } } } return result; } internal static void Tick(Player player) { if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer)) { bool flag = IsInZone(player); if (flag && !_wasInZone && Time.time >= _nextToast) { _nextToast = Time.time + 4f; float activePullRange = GetActivePullRange(player); string key = (ModConfig.RequireTotem.Value ? "cfc_zone_enter" : "cfc_zone_enter_always"); ((Character)player).Message((MessageType)2, Loc.Tf(key, activePullRange), 0, (Sprite)null, false); } _wasInZone = flag; } } internal static void HideAllMarkersExcept(CraftTotem keep) { for (int i = 0; i < Totems.Count; i++) { CraftTotem craftTotem = Totems[i]; if (!((Object)(object)craftTotem == (Object)null) && !((Object)(object)craftTotem == (Object)(object)keep)) { craftTotem.HideMarker(); } } } } } namespace CraftFromChestsPlus.Patches { [HarmonyPatch] internal static class CameraZoomBlockPatch { private static float _savedDistance; private static bool _restore; [HarmonyPrefix] [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] private static void Prefix(GameCamera __instance) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) _restore = false; if (ModConfig.BlockCameraZoom.Value && ModConfig.IsRangeHoldKeyDown() && Input.mouseScrollDelta.y != 0f && !((Object)(object)Player.m_localPlayer == (Object)null)) { _savedDistance = __instance.m_distance; _restore = true; } } [HarmonyPostfix] [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] private static void Postfix(GameCamera __instance) { if (_restore) { __instance.m_distance = _savedDistance; } } } [HarmonyPatch] internal static class ConsumePatches { [HarmonyPrefix] [HarmonyPatch(typeof(Player), "ConsumeResources")] private static bool ConsumeResourcesPrefix(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier) { return Consume(__instance, requirements, qualityLevel, multiplier); } private static bool Consume(Player __instance, Requirement[] requirements, int qualityLevel, int multiplier) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.Enabled.Value || (Object)(object)__instance == (Object)null || requirements == null) { return true; } Inventory inventory = ((Humanoid)__instance).GetInventory(); if (inventory == null) { return true; } Vector3 position = ((Component)__instance).transform.position; bool flag = CountPatches.ShouldQueryChests(); foreach (Requirement val in requirements) { if (val == null || (Object)(object)val.m_resItem == (Object)null) { continue; } int num = val.GetAmount(qualityLevel) * Mathf.Max(1, multiplier); if (num > 0) { string name = val.m_resItem.m_itemData.m_shared.m_name; CountPatches.IncludeChests = false; int num2; try { num2 = inventory.CountItems(name, -1, true); } finally { CountPatches.IncludeChests = true; } int num3 = Mathf.Min(num2, num); if (num3 > 0) { inventory.RemoveItem(name, num3, -1, true); } int num4 = num - num3; if (num4 > 0 && flag) { NearbyChestService.RemoveFromChests(name, num4, position); } } } return false; } } [HarmonyPatch] internal static class CountPatches { internal static bool IncludeChests = true; private static bool IsLocalPlayerInventory(Inventory inventory) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && inventory != null) { return inventory == ((Humanoid)localPlayer).GetInventory(); } return false; } internal static bool ShouldQueryChests() { if (!ModConfig.Enabled.Value || !IncludeChests) { return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } if (!TotemZoneService.IsInZone(localPlayer)) { return false; } try { if (((Character)localPlayer).InPlaceMode()) { return ModConfig.EnableBuildFromChests.Value; } } catch { } return ModConfig.EnableCraftFromChests.Value; } internal static bool ShouldQueryChestsForSmelt() { if (!ModConfig.Enabled.Value || !ModConfig.EnableSmeltFromChests.Value) { return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { return TotemZoneService.IsInZone(localPlayer); } return false; } [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "CountItems")] private static void CountItemsPostfix(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (ShouldQueryChests() && !string.IsNullOrEmpty(name) && IsLocalPlayerInventory(__instance)) { Player localPlayer = Player.m_localPlayer; __result += NearbyChestService.CountInChests(name, quality, matchWorldLevel, ((Component)localPlayer).transform.position); } } [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "HaveItem", new Type[] { typeof(string), typeof(bool) })] private static void HaveItemPostfix(Inventory __instance, string name, bool matchWorldLevel, ref bool __result) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!__result && ShouldQueryChests() && !string.IsNullOrEmpty(name) && IsLocalPlayerInventory(__instance)) { Player localPlayer = Player.m_localPlayer; __result = NearbyChestService.CountInChests(name, -1, matchWorldLevel, ((Component)localPlayer).transform.position) > 0; } } [HarmonyPrefix] [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")] private static void UpdateRecipeListPrefix() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (ModConfig.Enabled.Value && ModConfig.EnableCraftFromChests.Value) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && TotemZoneService.IsInZone(localPlayer)) { NearbyChestService.InvalidateCounts(); NearbyChestService.GetNearby(((Component)localPlayer).transform.position); } } } } [HarmonyPatch] internal static class RequirementPatches { [HarmonyPostfix] [HarmonyPatch(typeof(InventoryGui), "SetupRequirement")] private static void SetupRequirementPostfix(Transform elementRoot, Requirement req, Player player, bool craft, int quality, int craftMultiplier) { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.Enabled.Value || (Object)(object)elementRoot == (Object)null || (Object)(object)req?.m_resItem == (Object)null || (Object)(object)player == (Object)null) { return; } Transform val = elementRoot.Find("res_amount"); if ((Object)(object)val == (Object)null) { return; } TMP_Text component = ((Component)val).GetComponent<TMP_Text>(); if ((Object)(object)component == (Object)null) { return; } int num = req.GetAmount(quality) * Mathf.Max(1, craftMultiplier); if (num > 0) { string name = req.m_resItem.m_itemData.m_shared.m_name; int num2 = ((Humanoid)player).GetInventory().CountItems(name, -1, true); component.text = num2 + "/" + num; bool flag = num2 >= num; if (!flag && craft) { flag = (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey((GlobalKeys)25); } if (flag) { ((Graphic)component).color = Color.white; return; } bool flag2 = Mathf.Sin(Time.time * 10f) > 0f; ((Graphic)component).color = (flag2 ? Color.red : Color.white); } } } [HarmonyPatch] internal static class SmelterPatches { private static bool CanPullFromChests(Humanoid user) { Player val = (Player)(object)((user is Player) ? user : null); if (val != null && CountPatches.ShouldQueryChestsForSmelt()) { return TotemZoneService.IsInZone(val); } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Smelter), "OnAddOre")] private static bool OnAddOrePrefix(Smelter __instance, Switch sw, Humanoid user, ItemData item, ref bool __result) { //IL_0066: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.Enabled.Value || (Object)(object)__instance == (Object)null || (Object)(object)user == (Object)null) { return true; } if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer) { return true; } if (!CanPullFromChests(user)) { return true; } if (item != null) { return true; } Inventory inventory = user.GetInventory(); if (inventory != null && __instance.FindCookableItem(inventory) != null) { return true; } Vector3 position = ((Component)user).transform.position; if (!NearbyChestService.TryFindOreInChests(__instance, position, out var prefabName, out var sharedName)) { return true; } if (!__instance.IsItemAllowed(prefabName)) { ((Character)user).Message((MessageType)2, "$msg_wontwork", 0, (Sprite)null, false); __result = false; return false; } if (__instance.GetQueueSize() >= __instance.m_maxOre) { ((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null, false); __result = false; return false; } if (NearbyChestService.RemoveFromChests(sharedName, 1, position) <= 0) { return true; } ((Character)user).Message((MessageType)2, "$msg_added " + sharedName, 0, (Sprite)null, false); __instance.m_nview.InvokeRPC("RPC_AddOre", new object[2] { prefabName, false }); __instance.m_addedOreTime = Time.time; if (__instance.m_addOreAnimationDuration > 0f) { __instance.SetAnimation(true); } __result = true; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Smelter), "OnAddFuel")] private static bool OnAddFuelPrefix(Smelter __instance, Switch sw, Humanoid user, ItemData item, ref bool __result) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.Enabled.Value || (Object)(object)__instance == (Object)null || (Object)(object)user == (Object)null || (Object)(object)__instance.m_fuelItem == (Object)null) { return true; } if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer) { return true; } if (!CanPullFromChests(user)) { return true; } string name = __instance.m_fuelItem.m_itemData.m_shared.m_name; if (item != null && item.m_shared.m_name != name) { return true; } if (__instance.GetFuel() > (float)(__instance.m_maxFuel - 1)) { return true; } Inventory inventory = user.GetInventory(); bool flag = false; if (inventory != null) { CountPatches.IncludeChests = false; try { flag = inventory.HaveItem(name, true); } finally { CountPatches.IncludeChests = true; } } if (flag) { return true; } Vector3 position = ((Component)user).transform.position; if (NearbyChestService.CountInChests(name, position) <= 0) { return true; } if (NearbyChestService.RemoveFromChests(name, 1, position) <= 0) { return true; } ((Character)user).Message((MessageType)2, "$msg_added " + name, 0, (Sprite)null, false); __instance.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); __result = true; return false; } [HarmonyPostfix] [HarmonyPatch(typeof(Smelter), "CanUseItems")] private static void CanUseItemsPostfix(Smelter __instance, Player player, Switch switchRef, bool sendErrorMessage, ref bool __result) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (__result || !ModConfig.Enabled.Value || (Object)(object)__instance == (Object)null || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || !CountPatches.ShouldQueryChestsForSmelt()) { return; } Vector3 position = ((Component)player).transform.position; if (__instance.m_conversion != null && NearbyChestService.TryFindOreInChests(__instance, position, out var _, out var _) && __instance.GetQueueSize() < __instance.m_maxOre) { __result = true; } else if ((Object)(object)__instance.m_fuelItem != (Object)null) { string name = __instance.m_fuelItem.m_itemData.m_shared.m_name; if (__instance.GetFuel() <= (float)(__instance.m_maxFuel - 1) && NearbyChestService.CountInChests(name, position) > 0) { __result = true; } } } } [HarmonyPatch] internal static class TotemZonePatches { [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Update")] private static void PlayerUpdatePostfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { TotemZoneService.Tick(__instance); } } } } namespace CraftFromChestsPlus.Localization { internal static class Loc { private static readonly Dictionary<string, Dictionary<string, string>> Tables = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); private static string _activeCode = "en"; private static string LangDir => Path.Combine(Paths.ConfigPath, "CraftFromChestsPlus", "lang"); internal static void Init() { EnsureLangFolder(); LoadEmbedded("en"); LoadEmbedded("pt"); LoadDiskOverrides(); ApplyLanguagePreference(); Plugin.Log.LogInfo((object)("Localization ready (active=" + _activeCode + ", files in " + LangDir + ")")); } internal static string T(string key) { if (string.IsNullOrEmpty(key)) { return key; } if (Tables.TryGetValue(_activeCode, out var value) && value.TryGetValue(key, out var value2)) { return value2; } if (Tables.TryGetValue("en", out var value3) && value3.TryGetValue(key, out value2)) { return value2; } return key; } internal static string Tf(string key, params object[] args) { try { return string.Format(T(key), args); } catch (FormatException) { return T(key); } } private static void EnsureLangFolder() { Directory.CreateDirectory(LangDir); WriteEmbedded("en"); WriteEmbedded("pt"); } private static void WriteEmbedded(string code) { string path = Path.Combine(LangDir, code + ".json"); string text = ReadEmbedded(code); if (!string.IsNullOrEmpty(text)) { File.WriteAllText(path, text, Encoding.UTF8); } } private static void LoadEmbedded(string code) { string text = ReadEmbedded(code); if (!string.IsNullOrEmpty(text)) { Tables[code] = ParseFlatJson(text); } } private static void LoadDiskOverrides() { if (!Directory.Exists(LangDir)) { return; } string[] files = Directory.GetFiles(LangDir, "*.json"); foreach (string text in files) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); try { Dictionary<string, string> dictionary = ParseFlatJson(File.ReadAllText(text, Encoding.UTF8)); if (dictionary.Count == 0) { continue; } if (!Tables.TryGetValue(fileNameWithoutExtension, out var value)) { Tables[fileNameWithoutExtension] = dictionary; continue; } foreach (KeyValuePair<string, string> item in dictionary) { value[item.Key] = item.Value; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to load lang file " + text + ": " + ex.Message)); } } } private static string ReadEmbedded(string code) { string text = "CraftFromChestsPlus.Languages." + code + ".json"; using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text); if (stream == null) { Plugin.Log.LogWarning((object)("Missing embedded language resource: " + text)); return null; } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); return streamReader.ReadToEnd(); } internal static void ApplyLanguagePreference() { string a = ModConfig.Language?.Value ?? "Auto"; if (string.Equals(a, "Portuguese", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "pt", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "pt-BR", StringComparison.OrdinalIgnoreCase)) { _activeCode = (Tables.ContainsKey("pt") ? "pt" : "en"); return; } if (string.Equals(a, "English", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "en", StringComparison.OrdinalIgnoreCase)) { _activeCode = "en"; return; } try { string text = ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : null); if (!string.IsNullOrEmpty(text) && (text.IndexOf("Portuguese", StringComparison.OrdinalIgnoreCase) >= 0 || text.StartsWith("pt", StringComparison.OrdinalIgnoreCase) || text.IndexOf("Brazil", StringComparison.OrdinalIgnoreCase) >= 0)) { _activeCode = (Tables.ContainsKey("pt") ? "pt" : "en"); return; } } catch { } _activeCode = "en"; } internal static Dictionary<string, string> ParseFlatJson(string json) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(json)) { return dictionary; } int i = 0; SkipWs(json, ref i); if (i >= json.Length || json[i] != '{') { return dictionary; } i++; while (i < json.Length) { SkipWs(json, ref i); if (i < json.Length && json[i] == '}') { break; } if (i < json.Length && json[i] == ',') { i++; continue; } if (!TryReadString(json, ref i, out var value)) { break; } SkipWs(json, ref i); if (i >= json.Length || json[i] != ':') { break; } i++; SkipWs(json, ref i); if (!TryReadString(json, ref i, out var value2)) { break; } dictionary[value] = value2; } return dictionary; } private static void SkipWs(string s, ref int i) { while (i < s.Length && char.IsWhiteSpace(s[i])) { i++; } } private static bool TryReadString(string s, ref int i, out string value) { value = null; SkipWs(s, ref i); if (i >= s.Length || s[i] != '"') { return false; } i++; StringBuilder stringBuilder = new StringBuilder(); while (i < s.Length) { char c = s[i++]; switch (c) { case '"': value = stringBuilder.ToString(); return true; case '\\': if (i < s.Length) { char c2 = s[i++]; StringBuilder stringBuilder2 = stringBuilder; stringBuilder2.Append(c2 switch { 'n' => '\n', 'r' => '\r', 't' => '\t', '"' => '"', '\\' => '\\', _ => c2, }); continue; } break; } stringBuilder.Append(c); } return false; } } } namespace CraftFromChestsPlus.Effects { internal static class PullFeedback { private static float _lastVfxTime; private const float VfxCooldown = 0.08f; internal static void OnPulledFromChest(string itemSharedName, Vector3 chestPos, Vector3 targetPos) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.VisualFeedback.Value) { return; } float time = Time.time; if (time - _lastVfxTime < 0.08f) { return; } _lastVfxTime = time; PlayPrefabSafe("vfx_Potion_health_medium", chestPos + Vector3.up * 0.4f); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { try { EffectList autopickupEffects = localPlayer.m_autopickupEffects; if (autopickupEffects != null) { autopickupEffects.Create(targetPos, Quaternion.identity, (Transform)null, 1f, -1, ZDOID.None); } } catch { } } PlayPrefabSafe("sfx_lootspawn", targetPos); if (ModConfig.FlyingItemEffect.Value) { SpawnTrail(chestPos + Vector3.up * 0.6f, targetPos + Vector3.up * 1.1f); } } private static void PlayPrefabSafe(string prefabName, Vector3 pos) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)ZNetScene.instance == (Object)null)) { GameObject prefab = ZNetScene.instance.GetPrefab(prefabName); if (!((Object)(object)prefab == (Object)null)) { Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity); } } } catch { } } private static void SpawnTrail(Vector3 from, Vector3 to) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) try { GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)obj).name = "CFC_PullTrail"; Object.Destroy((Object)(object)obj.GetComponent<Collider>()); obj.transform.position = from; obj.transform.localScale = Vector3.one * 0.12f; Renderer component = obj.GetComponent<Renderer>(); if ((Object)(object)component != (Object)null) { component.material = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Standard")); component.material.color = new Color(0.35f, 0.85f, 1f, 0.85f); } obj.AddComponent<PullFlyer>().Begin(from, to, 0.4f); } catch { } } } internal sealed class PullFlyer : MonoBehaviour { private Vector3 _from; private Vector3 _to; private float _duration; private float _t; private Vector3 _arcPeak; internal void Begin(Vector3 from, Vector3 to, float duration) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) _from = from; _to = to; _duration = Mathf.Max(0.05f, duration); _t = 0f; _arcPeak = Vector3.Lerp(from, to, 0.5f) + Vector3.up * Mathf.Clamp(Vector3.Distance(from, to) * 0.15f, 0.4f, 2.5f); } private void Update() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) _t += Time.deltaTime / _duration; float num = Mathf.Clamp01(_t); Vector3 val = Vector3.Lerp(_from, _arcPeak, num); Vector3 val2 = Vector3.Lerp(_arcPeak, _to, num); ((Component)this).transform.position = Vector3.Lerp(val, val2, num); if (num >= 1f) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } } namespace CraftFromChestsPlus.Chest { internal static class NearbyChestService { private readonly struct CountKey : IEquatable<CountKey> { public readonly string Name; public readonly int Quality; public readonly bool MatchWorld; public CountKey(string name, int quality, bool matchWorld) { Name = name; Quality = quality; MatchWorld = matchWorld; } public bool Equals(CountKey other) { if (Quality == other.Quality && MatchWorld == other.MatchWorld) { return Name == other.Name; } return false; } public override bool Equals(object obj) { if (obj is CountKey other) { return Equals(other); } return false; } public override int GetHashCode() { return (((((Name != null) ? Name.GetHashCode() : 0) * 397) ^ Quality) * 397) ^ (MatchWorld ? 1 : 0); } } private struct CountEntry { public int Total; public float Time; } internal const float MinRange = 5f; internal const float MaxRange = 200f; internal const int MaxNearbyChests = 32; private static readonly List<Container> Tracked = new List<Container>(); private static readonly List<Container> NearbyCache = new List<Container>(); private static readonly Dictionary<CountKey, CountEntry> CountCache = new Dictionary<CountKey, CountEntry>(); private static readonly HashSet<int> LoadedOnce = new HashSet<int>(); private static float _nextNearbyRefresh; private static Vector3 _lastCenter; private static float _lastRange; private static bool _trackedDirty = true; private static bool _bootstrapped; private const float NearbyRefreshInterval = 2f; private const float MoveRefresh = 4f; private const float CountCacheTtl = 0.5f; internal static float EffectiveRange => Mathf.Clamp(ModConfig.Range.Value, 5f, 200f); internal static float GetPullRangeForLocalPlayer() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { return TotemZoneService.GetActivePullRange(localPlayer); } return EffectiveRange; } internal static void Register(Container container) { if (!((Object)(object)container == (Object)null) && !Tracked.Contains(container)) { Tracked.Add(container); _trackedDirty = true; InvalidateCounts(); } } internal static void Unregister(Container container) { if (!((Object)(object)container == (Object)null)) { Tracked.Remove(container); if ((Object)(object)container != (Object)null) { LoadedOnce.Remove(((Object)container).GetInstanceID()); } _trackedDirty = true; InvalidateCounts(); } } internal static void Invalidate() { _nextNearbyRefresh = 0f; NearbyCache.Clear(); _trackedDirty = true; InvalidateCounts(); } internal static void InvalidateCounts() { CountCache.Clear(); } internal static List<Container> GetNearby(Vector3 center) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.Enabled.Value) { return NearbyCache; } float pullRangeForLocalPlayer = GetPullRangeForLocalPlayer(); float time = Time.time; bool flag = Vector3.Distance(center, _lastCenter) > 4f; if (_trackedDirty || time >= _nextNearbyRefresh || flag || Mathf.Abs(pullRangeForLocalPlayer - _lastRange) > 0.01f || NearbyCache.Count == 0) { RefreshNearby(center, pullRangeForLocalPlayer); _nextNearbyRefresh = time + 2f; _lastCenter = center; _lastRange = pullRangeForLocalPlayer; _trackedDirty = false; InvalidateCounts(); } return NearbyCache; } private static void RefreshNearby(Vector3 center, float range) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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) NearbyCache.Clear(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } for (int num = Tracked.Count - 1; num >= 0; num--) { if ((Object)(object)Tracked[num] == (Object)null) { Tracked.RemoveAt(num); } } if (Tracked.Count == 0 && !_bootstrapped) { BootstrapScan(localPlayer); } float num2 = range * range; List<(Container, float)> list = new List<(Container, float)>(32); for (int i = 0; i < Tracked.Count; i++) { Container val = Tracked[i]; if (IsValidChest(val, localPlayer)) { Vector3 val2 = ((Component)val).transform.position - center; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > num2)) { list.Add((val, sqrMagnitude)); } } } list.Sort(((Container c, float d) a, (Container c, float d) b) => a.d.CompareTo(b.d)); int num3 = Mathf.Min(list.Count, 32); for (int num4 = 0; num4 < num3; num4++) { Container item = list[num4].Item1; EnsureLoaded(item); if (item.GetInventory() != null) { NearbyCache.Add(item); } } } private static void BootstrapScan(Player player) { _bootstrapped = true; Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0); foreach (Container container in array) { if (IsValidChest(container, player)) { Register(container); } } } private static void EnsureLoaded(Container container) { try { int instanceID = ((Object)container).GetInstanceID(); if (container.GetInventory() != null) { LoadedOnce.Add(instanceID); } else if (!LoadedOnce.Contains(instanceID)) { LoadedOnce.Add(instanceID); container.Load(); } } catch { } } internal static bool IsValidChest(Container container, Player player) { if ((Object)(object)container == (Object)null || (Object)(object)((Component)container).transform == (Object)null) { return false; } if (((Object)container).name.StartsWith("Treasure")) { return false; } if ((Object)(object)((Component)container).GetComponentInParent<Piece>() == (Object)null) { return false; } if ((Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid()) { return false; } try { if (container.m_nview.GetZDO().GetLong(ZDOVars.s_creator, 0L) == 0L) { return false; } } catch { return false; } try { if ((Object)(object)player != (Object)null && !container.CheckAccess(player.GetPlayerID())) { return false; } } catch { return false; } return true; } internal static int CountInChests(string itemName, int quality, bool matchWorldLevel, Vector3 center) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(itemName)) { return 0; } CountKey key = new CountKey(itemName, quality, matchWorldLevel); float time = Time.time; if (CountCache.TryGetValue(key, out var value) && time - value.Time <= 0.5f) { return value.Total; } int num = 0; List<Container> nearby = GetNearby(center); for (int i = 0; i < nearby.Count; i++) { Container val = nearby[i]; if (!((Object)(object)val == (Object)null)) { Inventory inventory = val.GetInventory(); if (inventory != null) { num += inventory.CountItems(itemName, quality, matchWorldLevel); } } } CountCache[key] = new CountEntry { Total = num, Time = time }; return num; } internal static int CountInChests(string itemName, Vector3 center) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) return CountInChests(itemName, -1, matchWorldLevel: true, center); } internal static bool TryFindOreInChests(Smelter smelter, Vector3 center, out string prefabName, out string sharedName) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) prefabName = null; sharedName = null; if (smelter?.m_conversion == null) { return false; } GetNearby(center); for (int i = 0; i < smelter.m_conversion.Count; i++) { ItemConversion val = smelter.m_conversion[i]; if ((Object)(object)val?.m_from == (Object)null) { continue; } SharedData val2 = val.m_from.m_itemData?.m_shared; if (val2 != null) { string name = val2.m_name; if (CountInChests(name, -1, matchWorldLevel: true, center) > 0) { prefabName = ((Object)val.m_from).name; sharedName = name; return true; } } } return false; } internal static int RemoveFromChests(string itemName, int amount, Vector3 center) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (amount <= 0 || string.IsNullOrEmpty(itemName)) { return 0; } int num = 0; List<Container> nearby = GetNearby(center); for (int i = 0; i < nearby.Count; i++) { if (num >= amount) { break; } Container val = nearby[i]; if ((Object)(object)val == (Object)null) { continue; } Inventory inventory = val.GetInventory(); if (inventory == null) { continue; } int num2 = inventory.CountItems(itemName, -1, true); if (num2 > 0) { int num3 = Mathf.Min(num2, amount - num); inventory.RemoveItem(itemName, num3, -1, true); num += num3; try { val.Save(); } catch { } PullFeedback.OnPulledFromChest(itemName, ((Component)val).transform.position, center); } } InvalidateCounts(); return num; } } [HarmonyPatch] internal static class ChestLifecyclePatches { [HarmonyPostfix] [HarmonyPatch(typeof(Container), "Awake")] private static void ContainerAwakePostfix(Container __instance) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && NearbyChestService.IsValidChest(__instance, localPlayer)) { NearbyChestService.Register(__instance); } } [HarmonyPostfix] [HarmonyPatch(typeof(Container), "OnDestroyed")] private static void ContainerDestroyedPostfix(Container __instance) { NearbyChestService.Unregister(__instance); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }