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 TraderCompass v1.21.1
TraderCompass_v1.21.1.dll
Decompiled 9 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("TraderCompass")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.21.1.0")] [assembly: AssemblyInformationalVersion("1.21.1")] [assembly: AssemblyProduct("TraderCompass")] [assembly: AssemblyTitle("TraderCompass")] [assembly: AssemblyVersion("1.21.1.0")] namespace TraderCompass; [BepInPlugin("frost.tradercompass", "TraderCompass", "1.21.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class TraderCompassPlugin : BaseUnityPlugin { public const string PluginGuid = "frost.tradercompass"; public const string PluginName = "TraderCompass"; public const string PluginVersion = "1.21.1"; public const string ItemPrefabName = "Compass_Trader"; public const string ItemName = "Компас"; internal static ManualLogSource Log; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; new Harmony("frost.tradercompass").PatchAll(); PrefabManager.OnVanillaPrefabsAvailable += CreateCompassItem; CompassCommand.Register(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"TraderCompass 1.21.1 загружен (Jötunn)"); } private void CreateCompassItem() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= CreateCompassItem; try { ItemConfig val = new ItemConfig(); val.Name = "Компас"; val.Description = "Странный компас, стрелка которого всегда тянется к торговцу.\nВозьми в руку и нажми <color=yellow>ПКМ</color> — он покажет путь к Халдору.\nДля запуска нужно 1 ядро суртлинга. Перезарядка 10 минут."; val.Icons = (Sprite[])(object)new Sprite[1] { CompassIcon.Create() }; val.Weight = 0.5f; val.StackSize = 1; ItemConfig val2 = val; GameObject obj = PrefabManager.Instance.CreateClonedPrefab("Compass_Trader", "Crystal"); CompassModel.Apply(obj); CustomItem val3 = new CustomItem(obj, false, val2); ItemManager.Instance.AddItem(val3); Log.LogInfo((object)"Компас зарегистрирован через Jötunn"); } catch (Exception ex) { Debug.LogError((object)("[TraderCompass] Ошибка создания предмета: " + ex)); } } } internal static class CompassModel { private const float TargetSize = 0.5f; private static AssetBundle _bundle; public static void Apply(GameObject clone) { //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) try { Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("compass_bundle"); if (manifestResourceStream == null) { TraderCompassPlugin.Log.LogWarning((object)"compass_bundle не найден в ресурсах — ванильный вид"); return; } byte[] array = new byte[manifestResourceStream.Length]; using (MemoryStream memoryStream = new MemoryStream()) { manifestResourceStream.CopyTo(memoryStream); array = memoryStream.ToArray(); } string text = Path.Combine(Path.GetTempPath(), "frost.tradercompass.bundle"); File.WriteAllBytes(text, array); _bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)_bundle == (Object)null) { _bundle = AssetBundle.LoadFromMemory(array); } if ((Object)(object)_bundle == (Object)null) { TraderCompassPlugin.Log.LogWarning((object)("Бандл не загрузился (" + array.Length + " байт, header: " + BitConverter.ToString(array, 0, 8) + ") — ванильный вид")); return; } TraderCompassPlugin.Log.LogInfo((object)("Бандл загружен, ассеты: " + string.Join(", ", _bundle.GetAllAssetNames()))); GameObject val = null; string[] allAssetNames = _bundle.GetAllAssetNames(); foreach (string text2 in allAssetNames) { val = _bundle.LoadAsset<GameObject>(text2); if ((Object)(object)val != (Object)null) { break; } } if ((Object)(object)val == (Object)null) { TraderCompassPlugin.Log.LogWarning((object)"В бандле нет префаба — ванильный вид"); return; } GameObject val2 = Object.Instantiate<GameObject>(val, clone.transform); ((Object)val2).name = "custom_visual"; val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; Renderer[] componentsInChildren = clone.GetComponentsInChildren<Renderer>(true); foreach (Renderer val3 in componentsInChildren) { if (!((Component)val3).transform.IsChildOf(val2.transform)) { val3.enabled = false; } } Light[] componentsInChildren2 = clone.GetComponentsInChildren<Light>(true); foreach (Light val4 in componentsInChildren2) { if (!((Component)val4).transform.IsChildOf(val2.transform)) { ((Behaviour)val4).enabled = false; } } float num = 0f; MeshFilter[] componentsInChildren3 = val2.GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter val5 in componentsInChildren3) { if (!((Object)(object)val5.sharedMesh == (Object)null)) { Bounds bounds = val5.sharedMesh.bounds; Vector3 val6 = Vector3.Scale(((Bounds)(ref bounds)).size, ((Component)val5).transform.lossyScale); num = Mathf.Max(num, Mathf.Max(val6.x, Mathf.Max(val6.y, val6.z))); } } if (num > 0.0001f) { float num2 = 0.5f / num; val2.transform.localScale = val2.transform.localScale * num2; } TraderCompassPlugin.Log.LogInfo((object)$"3D-модель компаса применена (габарит {0.5f:F2} м, масштаб x{((num > 0.0001f) ? (0.5f / num) : 1f):F2})"); } catch (Exception ex) { TraderCompassPlugin.Log.LogWarning((object)("3D-модель не применилась — остаётся ванильный вид: " + ex)); } } } [HarmonyPatch(typeof(Game), "Start")] internal static class Game_Start_LootPatch { private const float LootChancePercent = 4f; private static void Postfix() { //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) RegisterRPC(); try { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return; } ObjectDB instance2 = ObjectDB.instance; if ((Object)(object)instance2 == (Object)null) { return; } GameObject val = null; foreach (GameObject prefab in instance.m_prefabs) { if ((Object)(object)prefab != (Object)null && ((Object)prefab).name == "Compass_Trader") { val = prefab; break; } } if ((Object)(object)val == (Object)null) { TraderCompassPlugin.Log.LogWarning((object)"Компас не найден в ZNetScene — лут сундуков не добавлен"); return; } EnsureCompassRecipe(instance, instance2, val); int num = 0; foreach (GameObject prefab2 in instance.m_prefabs) { if ((Object)(object)prefab2 == (Object)null) { continue; } string name = ((Object)prefab2).name; if (name.IndexOf("TreasureChest", StringComparison.OrdinalIgnoreCase) < 0 || (name.IndexOf("blackforest", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("dungeon", StringComparison.OrdinalIgnoreCase) < 0)) { continue; } Container component = prefab2.GetComponent<Container>(); if ((Object)(object)component == (Object)null || component.m_defaultItems == null) { continue; } bool flag = false; float num2 = 0f; foreach (DropData drop in component.m_defaultItems.m_drops) { if ((Object)(object)drop.m_item == (Object)(object)val) { flag = true; break; } num2 += drop.m_weight; } if (!flag) { float weight = num2 * 0.04f / 0.96f; component.m_defaultItems.m_drops.Add(new DropData { m_item = val, m_stackMin = 1, m_stackMax = 1, m_weight = weight, m_dontScale = true }); num++; } } if (num > 0) { TraderCompassPlugin.Log.LogInfo((object)("Компас добавлен в лут сундуков: " + num + " шт")); } } catch (Exception ex) { Debug.LogError((object)("[TraderCompass] Ошибка добавления лута: " + ex)); } } private static void RegisterRPC() { CompassCache.Reset(); TraderPosSync.Reset(); if (ZRoutedRpc.instance == null) { TraderCompassPlugin.Log.LogWarning((object)"ZRoutedRpc недоступен при старте мира — RPC не зарегистрированы"); return; } ZRoutedRpc.instance.Register("TraderCompass_RequestPos", (Action<long>)TraderCompassRPC.OnPosRequested); ZRoutedRpc.instance.Register<Vector3, bool, bool>("TraderCompass_Pos", (Action<long, Vector3, bool, bool>)TraderCompassRPC.OnPosReceived); TraderCompassPlugin.Log.LogInfo((object)"RPC зарегистрированы (запрос позиции и ответ)"); } private static ItemDrop FindItemBySharedName(ObjectDB db, string sharedName) { foreach (GameObject item in db.m_items) { if (!((Object)(object)item == (Object)null)) { ItemDrop component = item.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null && component.m_itemData.m_shared.m_name == sharedName) { return component; } } } return null; } private static void EnsureCompassRecipe(ZNetScene zns, ObjectDB db, GameObject compassPrefab) { //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Expected O, but got Unknown //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Expected O, but got Unknown //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Expected O, but got Unknown //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Expected O, but got Unknown foreach (Recipe recipe in db.m_recipes) { if ((Object)(object)recipe != (Object)null && (Object)(object)recipe.m_item != (Object)null && ((Object)((Component)recipe.m_item).gameObject).name == "Compass_Trader") { return; } } GameObject val = (((Object)(object)zns != (Object)null) ? zns.GetPrefab("piece_forge") : null); CraftingStation val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<CraftingStation>() : null); if ((Object)(object)val2 == (Object)null) { foreach (Recipe recipe2 in db.m_recipes) { if (!((Object)(object)recipe2 == (Object)null) && !((Object)(object)recipe2.m_craftingStation == (Object)null) && recipe2.m_craftingStation.m_name == "$piece_forge") { val2 = recipe2.m_craftingStation; break; } } } GameObject itemPrefab = db.GetItemPrefab("Bronze"); ItemDrop val3 = FindItemBySharedName(db, "$item_silver"); GameObject itemPrefab2 = db.GetItemPrefab("Crystal"); GameObject itemPrefab3 = db.GetItemPrefab("SurtlingCore"); List<string> list = new List<string>(); if ((Object)(object)val2 == (Object)null) { list.Add("кузница"); } if ((Object)(object)itemPrefab == (Object)null) { list.Add("бронза"); } if ((Object)(object)val3 == (Object)null) { list.Add("серебро"); } if ((Object)(object)itemPrefab2 == (Object)null) { list.Add("кристалл"); } if ((Object)(object)itemPrefab3 == (Object)null) { list.Add("ядро"); } if (list.Count > 0) { TraderCompassPlugin.Log.LogWarning((object)("Рецепт компаса: не найдены компоненты — " + string.Join(", ", list))); return; } Recipe val4 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val4).name = "Recipe_Compass_Trader"; val4.m_item = compassPrefab.GetComponent<ItemDrop>(); val4.m_amount = 1; val4.m_craftingStation = val2; val4.m_minStationLevel = 1; val4.m_resources = (Requirement[])(object)new Requirement[4] { new Requirement { m_resItem = itemPrefab.GetComponent<ItemDrop>(), m_amount = 4 }, new Requirement { m_resItem = ((Component)val3).GetComponent<ItemDrop>(), m_amount = 4 }, new Requirement { m_resItem = itemPrefab2.GetComponent<ItemDrop>(), m_amount = 1 }, new Requirement { m_resItem = itemPrefab3.GetComponent<ItemDrop>(), m_amount = 1 } }; db.m_recipes.Add(val4); TraderCompassPlugin.Log.LogInfo((object)"Рецепт компаса создан: кузница, 4 бронзы + 4 серебра + 1 кристалл + 1 ядро"); } } [HarmonyPatch(typeof(Humanoid), "UseItem", new Type[] { typeof(Inventory), typeof(ItemData), typeof(bool) })] internal static class Humanoid_UseItem_Patch { private const float CooldownSeconds = 600f; private static float _nextUseTime; private static bool Prefix(Humanoid __instance, ItemData item) { //IL_0084: 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) if (item == null || item.m_shared == null || item.m_shared.m_name != "Компас") { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null) { return true; } if (Time.time < _nextUseTime) { float num = _nextUseTime - Time.time; ((Character)val).Message((MessageType)2, $"Компас остывает: ещё {(int)(num / 60f)} мин {(int)(num % 60f)} с", 0, (Sprite)null, false); return false; } if (!TryFindTrader(((Component)val).transform.position, out var pos, out var traderPlaced)) { RequestTraderPosFromServer(val); return false; } if (!TryConsumeSurtlingCore(val)) { ((Character)val).Message((MessageType)2, "Для запуска компаса нужно 1 ядро суртлинга", 0, (Sprite)null, false); return false; } ShowTraderDirection(val, pos, traderPlaced); _nextUseTime = Time.time + 600f; return false; } private static bool TryConsumeSurtlingCore(Player player) { foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems()) { if (allItem != null && (Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == "SurtlingCore") { ((Humanoid)player).GetInventory().RemoveItem(allItem, 1); return true; } } return false; } private static void ShowTraderDirection(Player player, Vector3 traderPos, bool traderPlaced) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { Vector3 val = traderPos - ((Component)player).transform.position; float magnitude = ((Vector3)(ref val)).magnitude; ((Character)player).SetLookDir(val, 3.5f); string arg = (traderPlaced ? "Торговец" : "Торговец (возможная точка)"); ((Character)player).Message((MessageType)1, $"{arg}: {BearingHelper.BearingName(val)} ({magnitude:F0} м)", 0, (Sprite)null, false); } } private static bool TryFindTrader(Vector3 near, out Vector3 pos, out bool traderPlaced) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0197: 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_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; traderPlaced = false; if (CompassCache.Valid && CompassCache.Placed) { pos = CompassCache.Pos; traderPlaced = true; return true; } if (TraderPosSync.SyncedValid) { pos = TraderPosSync.SyncedPos; traderPlaced = TraderPosSync.Placed; return true; } if (CompassCache.Valid && Time.time < CompassCache.NextScanTime) { pos = CompassCache.Pos; traderPlaced = CompassCache.Placed; return true; } CompassCache.NextScanTime = Time.time + 2f; ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return false; } LocationInstance? val = null; float num = float.MaxValue; LocationInstance? val2 = null; float num2 = float.MaxValue; foreach (LocationInstance value2 in instance.m_locationInstances.Values) { if (!IsTraderLocation(value2.m_location)) { continue; } float num3 = Vector3.Distance(value2.m_position, near); if (value2.m_placed) { if (num3 < num) { num = num3; val = value2; } } else if (num3 < num2) { num2 = num3; val2 = value2; } } LocationInstance value; if (val.HasValue) { value = val.Value; traderPlaced = true; } else { if (!val2.HasValue) { if (!CompassCache.DumpLogged) { CompassCache.DumpLogged = true; TraderCompassPlugin.Log.LogInfo((object)$"Локация торговца не найдена локально (локаций в списке: {instance.m_locationInstances.Count}) — при ПКМ будет запрошена позиция у сервера"); } return false; } value = val2.Value; } CompassCache.Valid = true; CompassCache.Placed = traderPlaced; CompassCache.Pos = value.m_position; pos = value.m_position; return true; } private static bool IsTraderLocation(ZoneLocation zoneLocation) { if (zoneLocation == null) { return false; } string prefabName = zoneLocation.m_prefabName; if (prefabName != null) { if (prefabName.IndexOf("vendor_blackforest", StringComparison.OrdinalIgnoreCase) < 0) { return prefabName.IndexOf("haldor", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } private static void RequestTraderPosFromServer(Player player) { if (!(Time.time < TraderPosSync.NextRequestTime)) { TraderPosSync.NextRequestTime = Time.time + 5f; if (ZRoutedRpc.instance == null) { TraderCompassPlugin.Log.LogWarning((object)"ZRoutedRpc недоступен — запрос позиции не отправлен"); return; } ((Character)player).Message((MessageType)2, "Запрашиваю позицию торговца у сервера...", 0, (Sprite)null, false); TraderCompassPlugin.Log.LogInfo((object)"Локально торговец не найден — отправляю запрос на сервер"); ZRoutedRpc.instance.InvokeRoutedRPC("TraderCompass_RequestPos", Array.Empty<object>()); } } } internal static class TraderCompassRPC { public static void OnPosRequested(long sender) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return; } LocationInstance? val = null; float num = float.MaxValue; float num2 = float.MaxValue; int num3 = 0; Vector3 val2 = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : Vector3.zero); foreach (LocationInstance value in instance.m_locationInstances.Values) { if (!IsTraderLocation(value.m_location)) { continue; } num3++; float num4 = Vector3.Distance(value.m_position, val2); if (value.m_placed) { if (num4 < num) { num = num4; val = value; } } else if (num4 < num2) { num2 = num4; if (!val.HasValue) { val = value; } } } if (val.HasValue) { bool placed = val.Value.m_placed; TraderCompassPlugin.Log.LogInfo((object)$"RPC: отвечаю клиенту {sender}: позиция ({val.Value.m_position.x:F0}, {val.Value.m_position.y:F0}, {val.Value.m_position.z:F0}), размещён={placed} (торговых локаций: {num3})"); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "TraderCompass_Pos", new object[3] { val.Value.m_position, placed, true }); } else { TraderCompassPlugin.Log.LogWarning((object)$"RPC: торговец не найден среди {instance.m_locationInstances.Count} локаций мира (торговых: {num3}) — мир ещё генерируется?"); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "TraderCompass_Pos", new object[3] { Vector3.zero, false, false }); } } catch (Exception ex) { Debug.LogError((object)("[TraderCompass] Ошибка ответа на запрос: " + ex)); } } public static void OnPosReceived(long sender, Vector3 pos, bool placed, bool found) { //IL_0037: 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_005b: 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_0077: Unknown result type (might be due to invalid IL or missing references) try { if (!found) { TraderCompassPlugin.Log.LogInfo((object)"RPC: сервер ответил — торговец пока не найден в мире"); if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, "Торговец пока не известен серверу — мир ещё генерируется, попробуй позже", 0, (Sprite)null, false); } return; } TraderPosSync.SyncedPos = pos; TraderPosSync.Placed = placed; TraderPosSync.SyncedValid = true; TraderCompassPlugin.Log.LogInfo((object)$"RPC: получена позиция торговца ({pos.x:F0}, {pos.y:F0}, {pos.z:F0}), размещён={placed}"); if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, "Позиция торговца получена — нажми ПКМ ещё раз", 0, (Sprite)null, false); } } catch (Exception ex) { Debug.LogError((object)("[TraderCompass] Ошибка приёма позиции: " + ex)); } } private static bool IsTraderLocation(ZoneLocation location) { if (location == null) { return false; } string prefabName = location.m_prefabName; if (prefabName != null) { if (prefabName.IndexOf("vendor_blackforest", StringComparison.OrdinalIgnoreCase) < 0) { return prefabName.IndexOf("haldor", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } } internal static class RpcNames { public const string Request = "TraderCompass_RequestPos"; public const string Pos = "TraderCompass_Pos"; } internal static class TraderPosSync { public static Vector3 SyncedPos; public static bool SyncedValid; public static bool Placed; public static float NextRequestTime; public static void Reset() { SyncedValid = false; Placed = false; NextRequestTime = 0f; } } internal static class CompassCache { public static Vector3 Pos; public static bool Valid; public static bool Placed; public static float NextScanTime; public static bool DumpLogged; public static void Reset() { Valid = false; Placed = false; DumpLogged = false; } } internal static class BearingHelper { public static string BearingName(Vector3 dir) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Atan2(dir.x, 0f - dir.z) * 57.29578f; if (num < 0f) { num += 360f; } return (new string[8] { "С", "СВ", "В", "ЮВ", "Ю", "ЮЗ", "З", "СЗ" })[(int)Mathf.Round(num / 45f) % 8]; } } [HarmonyPatch(typeof(Player), "Load")] internal static class Player_Load_Patch { private static void Postfix(Player __instance) { try { ObjectDB instance = ObjectDB.instance; if (!((Object)(object)instance == (Object)null)) { RecipeUnlocker.UnlockFor(__instance, instance); } } catch (Exception ex) { Debug.LogError((object)("[TraderCompass] Ошибка выдачи рецепта (загрузка): " + ex)); } } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class Player_OnSpawned_Patch { private static void Postfix(Player __instance) { try { ObjectDB instance = ObjectDB.instance; if (!((Object)(object)instance == (Object)null)) { RecipeUnlocker.UnlockFor(__instance, instance); } } catch (Exception ex) { Debug.LogError((object)("[TraderCompass] Ошибка выдачи рецепта: " + ex)); } } } [HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")] internal static class InventoryGui_UpdateCraftingPanel_Patch { private static int _diagCalls; private static void Postfix(InventoryGui __instance) { try { Player localPlayer = Player.m_localPlayer; ObjectDB instance = ObjectDB.instance; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)instance == (Object)null)) { RecipeUnlocker.UnlockFor(localPlayer, instance); if (_diagCalls < 2) { _diagCalls++; LogCraftingMenuDiagnostics(localPlayer, instance); } } } catch (Exception ex) { Debug.LogError((object)("[TraderCompass] Ошибка выдачи рецепта (меню): " + ex)); } } private static void LogCraftingMenuDiagnostics(Player player, ObjectDB db) { try { List<Recipe> list = new List<Recipe>(); player.GetAvailableRecipes(ref list); bool flag = false; foreach (Recipe item in list) { if ((Object)(object)item != (Object)null && (Object)(object)item.m_item != (Object)null && ((Object)((Component)item.m_item).gameObject).name == "Compass_Trader") { flag = true; break; } } bool flag2 = false; foreach (GameObject item2 in db.m_items) { if ((Object)(object)item2 != (Object)null && ((Object)item2).name == "Compass_Trader") { flag2 = true; break; } } TraderCompassPlugin.Log.LogInfo((object)string.Format("Меню крафта: компас в доступных: {0} из {1}, предмет в БД: {2}, рецепт изучен: {3}", flag, list.Count, flag2, player.IsRecipeKnown("Компас"))); } catch (Exception ex) { Debug.LogError((object)("[TraderCompass] Ошибка диагностики меню: " + ex)); } } } [HarmonyPatch(typeof(InventoryGui), "AddRecipeToList")] internal static class InventoryGui_AddRecipeToList_Patch { private static void Postfix(InventoryGui __instance, Recipe recipe, ItemData item, bool canCraft) { //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null || ((Object)((Component)recipe.m_item).gameObject).name != "Compass_Trader" || !(AccessTools.Field(typeof(InventoryGui), "m_availableRecipes")?.GetValue(__instance) is IEnumerable enumerable)) { return; } object obj = null; foreach (object item2 in enumerable) { obj = item2; } object member = TraderCompassAccess.GetMember(obj, "InterfaceElement"); GameObject val = (GameObject)((member is GameObject) ? member : null); object obj2; if (!((Object)(object)val != (Object)null)) { obj2 = null; } else { Transform obj3 = val.transform.Find("icon"); obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<Image>() : null); } Image val2 = (Image)obj2; if (!((Object)(object)val2 == (Object)null)) { ((Graphic)val2).color = (Color)(canCraft ? Color.white : new Color(1f, 1f, 1f, 0.4f)); } } catch { } } } internal static class TraderCompassAccess { public static object GetMember(object obj, string name) { Type type = obj.GetType(); PropertyInfo propertyInfo = AccessTools.Property(type, name); if (propertyInfo != null) { return propertyInfo.GetValue(obj); } return AccessTools.Field(type, name)?.GetValue(obj); } } internal static class RecipeUnlocker { public static void UnlockFor(Player player, ObjectDB db) { if (player.IsRecipeKnown("Компас")) { return; } Recipe val = null; foreach (Recipe recipe in db.m_recipes) { if ((Object)(object)recipe != (Object)null && (Object)(object)recipe.m_item != (Object)null && ((Object)((Component)recipe.m_item).gameObject).name == "Compass_Trader") { val = recipe; break; } } if (!((Object)(object)val == (Object)null)) { AccessTools.Method(typeof(Player), "AddKnownRecipe", (Type[])null, (Type[])null)?.Invoke(player, new object[1] { val }); TraderCompassPlugin.Log.LogInfo((object)("Рецепт выдан игроку " + player.GetPlayerName())); } } } internal static class CompassCommand { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; internal void <Register>b__0_0(ConsoleEventArgs <p0>) { Player localPlayer = Player.m_localPlayer; ObjectDB instance = ObjectDB.instance; if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null) { return; } ItemDrop val = null; foreach (GameObject item in instance.m_items) { if ((Object)(object)item != (Object)null && ((Object)item).name == "Compass_Trader") { val = item.GetComponent<ItemDrop>(); break; } } if ((Object)(object)val == (Object)null) { ((Character)localPlayer).Message((MessageType)2, "Компас ещё не готов, попробуй через секунду", 0, (Sprite)null, false); } else if (((Humanoid)localPlayer).GetInventory().AddItem(((Component)val).gameObject, 1)) { ((Character)localPlayer).Message((MessageType)1, "Компас торговца получен", 0, (Sprite)null, false); } else { ((Character)localPlayer).Message((MessageType)2, "В инвентаре нет места", 0, (Sprite)null, false); } } } public static void Register() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate { Player localPlayer = Player.m_localPlayer; ObjectDB instance = ObjectDB.instance; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)instance == (Object)null)) { ItemDrop val2 = null; foreach (GameObject item in instance.m_items) { if ((Object)(object)item != (Object)null && ((Object)item).name == "Compass_Trader") { val2 = item.GetComponent<ItemDrop>(); break; } } if ((Object)(object)val2 == (Object)null) { ((Character)localPlayer).Message((MessageType)2, "Компас ещё не готов, попробуй через секунду", 0, (Sprite)null, false); } else if (((Humanoid)localPlayer).GetInventory().AddItem(((Component)val2).gameObject, 1)) { ((Character)localPlayer).Message((MessageType)1, "Компас торговца получен", 0, (Sprite)null, false); } else { ((Character)localPlayer).Message((MessageType)2, "В инвентаре нет места", 0, (Sprite)null, false); } } }; <>c.<>9__0_0 = val; obj = (object)val; } new ConsoleCommand("compass", "выдать компас торговца в инвентарь", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } internal static class CompassIcon { private static Sprite _sprite; public static Sprite Create() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_sprite != (Object)null) { return _sprite; } Texture2D val = LoadEmbeddedTexture(); if ((Object)(object)val == (Object)null) { val = CreateProceduralTexture(); } ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; val.Apply(true, true); _sprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); return _sprite; } private static Texture2D LoadEmbeddedTexture() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown try { Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("compass_icon.png"); if (manifestResourceStream == null) { return null; } using (manifestResourceStream) { byte[] array = new byte[manifestResourceStream.Length]; using (MemoryStream memoryStream = new MemoryStream()) { manifestResourceStream.CopyTo(memoryStream); array = memoryStream.ToArray(); } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true); return ImageConversion.LoadImage(val, array) ? val : null; } } catch (Exception ex) { Debug.LogError((object)("[TraderCompass] Не удалось загрузить иконку: " + ex)); return null; } } private static Texture2D CreateProceduralTexture() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); ((Texture)val).wrapMode = (TextureWrapMode)1; Color32[] array = (Color32[])(object)new Color32[4096]; float num = 31.5f; float num2 = 30f; Color32 val2 = default(Color32); for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num3 = (float)j - num; float num4 = (float)i - num; float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4); ((Color32)(ref val2))..ctor((byte)0, (byte)0, (byte)0, (byte)0); if (num5 <= num2) { ((Color32)(ref val2))..ctor((byte)52, (byte)48, (byte)56, byte.MaxValue); if (num5 > num2 - 4f) { ((Color32)(ref val2))..ctor((byte)198, (byte)156, (byte)82, byte.MaxValue); } float num6 = 7f * (1f - Mathf.Abs(num4) / 28f); if (Mathf.Abs(num4) <= 28f && Mathf.Abs(num3) <= num6) { val2 = ((num4 > 0f) ? new Color32((byte)214, (byte)62, (byte)48, byte.MaxValue) : new Color32((byte)232, (byte)228, (byte)220, byte.MaxValue)); } } array[i * 64 + j] = val2; } } val.SetPixels32(array); ((Texture)val).filterMode = (FilterMode)1; val.Apply(false, true); return val; } }