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 MJNetworkCore v0.1.18
plugins/MJNetworkCore.dll
Decompiled 4 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [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 MJNetworkCore { internal static class ActiveObjectHooks { private static readonly Dictionary<int, ZDOID> ViewIds = new Dictionary<int, ZDOID>(); internal static void ResetMappings() { ViewIds.Clear(); } internal static void RegisterView(ZNetView view) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)view == (Object)null || Plugin.Registry == null) { return; } try { if (view.IsValid()) { ZDO zDO = view.GetZDO(); if (zDO != null) { ViewIds[((Object)view).GetInstanceID()] = zDO.m_uid; Plugin.Registry.Register(zDO, ((Component)view).gameObject); } } } catch (Exception ex) { Plugin.LogDebug("Register view failed: " + ex.Message); } } internal static void UnregisterView(ZNetView view) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)view == (Object)null || Plugin.Registry == null) { return; } try { int instanceID = ((Object)view).GetInstanceID(); if (ViewIds.TryGetValue(instanceID, out var value)) { ViewIds.Remove(instanceID); Plugin.Registry.Unregister(value, ((Component)view).gameObject); return; } ZDO zDO = view.GetZDO(); if (zDO != null) { Plugin.Registry.Unregister(zDO.m_uid, ((Component)view).gameObject); } } catch { } } internal static void SeedCurrentlyLoadedViews() { try { ZNetView[] array = Object.FindObjectsByType<ZNetView>((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { RegisterView(array[i]); } Plugin.LogDebug("Seeded loaded ZNetViews: " + array.Length); } catch (Exception ex) { Plugin.LogWarning("Loaded-view seed failed: " + ex.Message); } } } internal static class CoreClientControls { private static FieldInfo _hovering; private static readonly int[] Steps = new int[7] { 0, 1, 5, 10, 25, 50, 100 }; private static GUIStyle _networkStyle; internal static void Update() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } bool flag = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); bool flag2 = Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); bool flag3 = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); if (flag && flag3 && Input.GetKeyDown((KeyCode)118)) { StorageRef storageRef = HoveredStorage(localPlayer); if (storageRef != null && storageRef.RequiresNetworkOptIn && storageRef.Zdo != null) { ZNetView val = (((Object)(object)storageRef.GameObject == (Object)null) ? null : storageRef.GameObject.GetComponent<ZNetView>()); if ((Object)(object)val != (Object)null && val.IsValid() && !val.IsOwner()) { val.ClaimOwnership(); } bool flag4 = !storageRef.NetworkOptInEnabled; storageRef.Zdo.Set(CoreUtil.StorageNetworkEnabledHash, flag4); CoreUtil.ForceSend(storageRef.Zdo); if (Plugin.Registry != null) { Plugin.Registry.MarkDirty(); } Show("Vernichter-Netzwerk: " + (flag4 ? "AN" : "AUS")); } } else if (flag && flag3 && Input.GetKeyDown((KeyCode)110)) { NetworkInfo networkInfo = HoveredNetwork(localPlayer); if (networkInfo != null && !NetworkApi.RequestNetworkRename(networkInfo)) { Show("MJ Network Map & Statistics wird zum Benennen benoetigt."); } } else { if (!flag || !flag2 || !Input.GetKeyDown((KeyCode)101)) { return; } StorageRef storageRef2 = HoveredStorage(localPlayer); if (storageRef2 == null) { return; } int reserve = StorageApi.GetReserve(storageRef2); int value = Steps[0]; for (int i = 0; i < Steps.Length; i++) { if (Steps[i] > reserve) { value = Steps[i]; break; } if (i == Steps.Length - 1) { value = Steps[0]; } } StorageApi.SetReserve(storageRef2, value); Show(storageRef2.PrefabName + ": Mindestbestand = " + value); } } internal static void OnGUI() { } internal static string AppendStationHover(CraftingStation station, string current) { if ((Object)(object)station == (Object)null) { return current; } NetworkInfo networkForStation = NetworkApi.GetNetworkForStation(station); if (networkForStation == null) { return current; } string text = (string.IsNullOrWhiteSpace(networkForStation.Name) ? "unbenannt" : networkForStation.Name); string text2 = "Netzwerk: " + text + "\n[Strg+Shift+N] Netzwerk benennen"; if (!string.IsNullOrEmpty(current)) { return current.TrimEnd(Array.Empty<char>()) + "\n" + text2; } return text2; } internal static string AppendStorageHover(GameObject go, string current) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)go == (Object)null) { return current; } ZNetView val = go.GetComponentInParent<ZNetView>() ?? go.GetComponent<ZNetView>(); if ((Object)(object)val == (Object)null || !val.IsValid() || val.GetZDO() == null) { return current; } StorageRef storageRef = null; foreach (StorageRef storage in NetworkApi.Storages) { if (storage != null) { ZDOID id = storage.Id; if (((ZDOID)(ref id)).Equals(val.GetZDO().m_uid)) { storageRef = storage; break; } } } if (storageRef == null || !storageRef.RequiresNetworkOptIn) { return current; } string text = "[Strg+Shift+V] Vernichter-Netzwerk: " + (storageRef.NetworkOptInEnabled ? "AN" : "AUS"); if (!string.IsNullOrEmpty(current) && current.IndexOf("Vernichter-Netzwerk", StringComparison.Ordinal) >= 0) { return current; } if (!string.IsNullOrEmpty(current)) { return current.TrimEnd(Array.Empty<char>()) + "\n" + text; } return text; } private static NetworkInfo HoveredNetwork(Player p) { GameObject val = HoveredObject(p); if ((Object)(object)val == (Object)null) { return null; } CraftingStation val2 = val.GetComponentInParent<CraftingStation>(); if ((Object)(object)val2 == (Object)null) { val2 = val.GetComponent<CraftingStation>(); } if (!((Object)(object)val2 == (Object)null)) { return NetworkApi.GetNetworkForStation(val2); } return null; } private static StorageRef HoveredStorage(Player p) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) GameObject val = HoveredObject(p); if ((Object)(object)val == (Object)null) { return null; } ZNetView componentInParent = val.GetComponentInParent<ZNetView>(); if ((Object)(object)componentInParent == (Object)null || !componentInParent.IsValid()) { return null; } foreach (StorageRef storage in NetworkApi.Storages) { ZDOID id = storage.Id; if (((ZDOID)(ref id)).Equals(componentInParent.GetZDO().m_uid)) { return storage; } } return null; } private static GameObject HoveredObject(Player p) { _hovering = _hovering ?? AccessTools.Field(typeof(Player), "m_hovering"); if (!(_hovering == null)) { object? value = _hovering.GetValue(p); return (GameObject)((value is GameObject) ? value : null); } return null; } private static void Show(string s) { if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, s, 0, (Sprite)null, false, true); } } } internal sealed class CoreConfig { internal readonly ConfigEntry<float> RebuildDebounceSeconds; internal readonly ConfigEntry<float> StorageAttachExtraRange; internal readonly ConfigEntry<int> DefaultReserve; internal readonly ConfigEntry<float> SnapshotSeconds; internal readonly ConfigEntry<bool> PlayerBuiltOnly; internal readonly ConfigEntry<bool> NetworkWideBuildStations; internal readonly ConfigEntry<bool> VerboseLogging; internal CoreConfig(ConfigFile cfg) { RebuildDebounceSeconds = cfg.Bind<float>("Network", "RebuildDebounceSeconds", 0.2f, "Wait this long after loaded stations/containers change before rebuilding the active network graph."); StorageAttachExtraRange = cfg.Bind<float>("Network", "StorageAttachExtraRange", 0f, "Extra meters beyond the actual crafting-station build radius in which a storage belongs to that network."); DefaultReserve = cfg.Bind<int>("Storage", "DefaultReserve", 1, "Minimum amount each consuming module leaves in a container unless that container has its own override."); SnapshotSeconds = cfg.Bind<float>("Performance", "SnapshotSeconds", 0.25f, "How long a network resource snapshot may be reused for UI/count checks."); PlayerBuiltOnly = cfg.Bind<bool>("Network", "PlayerBuiltOnly", true, "Only player-built crafting stations and storage pieces participate in networks. Prevents dungeon/world stations from polluting the network list."); NetworkWideBuildStations = cfg.Bind<bool>("Building", "NetworkWideBuildStations", true, "If true, a required build station may be anywhere in the same connected MJ network. The build point/player still has to be inside that network."); VerboseLogging = cfg.Bind<bool>("Debug", "VerboseLogging", false, "Extra diagnostic logging."); } } internal static class CoreRpc { private const string RpcName = "MJNC_Settings_v1"; private const int OpReserve = 1; private const int OpNetworkName = 2; private const int OpNetworkBool = 3; private static ZRoutedRpc _registeredOn; private static MethodInfo _getServerPeerId; internal static void EnsureRegistered() { if (ZRoutedRpc.instance == null || _registeredOn == ZRoutedRpc.instance) { return; } try { ZRoutedRpc.instance.Register<ZPackage>("MJNC_Settings_v1", (Action<long, ZPackage>)OnRpc); _registeredOn = ZRoutedRpc.instance; } catch (Exception ex) { Plugin.LogDebug("Core RPC registration: " + ex.Message); } } internal static void SetReserve(StorageRef storage, int value) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown if (storage != null && storage.Zdo != null) { ZPackage val = new ZPackage(); val.Write(1); val.Write(storage.Id); val.Write(Math.Max(0, value)); Send(val); } } internal static void SetNetworkName(NetworkInfo network, string name) { //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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown if (network != null && network.Stations.Count != 0) { ZPackage val = new ZPackage(); val.Write(2); val.Write(network.Stations[0].Id); val.Write(name ?? string.Empty); Send(val); } } internal static void SetNetworkBool(NetworkInfo network, string key, bool value) { //IL_0019: 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_0025: 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_003c: 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_0052: Expected O, but got Unknown if (network != null && network.Stations.Count != 0 && IsSafeKey(key)) { ZPackage val = new ZPackage(); val.Write(3); val.Write(network.Stations[0].Id); val.Write(key); val.Write(value ? 1 : 0); Send(val); } } private static void Send(ZPackage p) { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { p.SetPos(0); OnRpc(0L, p); } else if (ZRoutedRpc.instance != null) { long serverPeerId = GetServerPeerId(); if (serverPeerId != 0L) { ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerId, "MJNC_Settings_v1", new object[1] { p }); } } } private static void OnRpc(long sender, ZPackage p) { //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_0081: 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_0121: Unknown result type (might be due to invalid IL or missing references) if (p == null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } try { int num = p.ReadInt(); ZDOID val = p.ReadZDOID(); switch (num) { case 1: { ZDO val2 = ((ZDOMan.instance == null) ? null : ZDOMan.instance.GetZDO(val)); if (val2 != null) { val2.Set(CoreUtil.ReserveHash, Math.Max(0, p.ReadInt()), false); CoreUtil.ForceSend(val2); NetworkApi.InvalidateSnapshots(); } break; } case 2: { string text = p.ReadString(); NetworkInfo networkInfo2 = FindNetworkByStation(val); if (networkInfo2 != null) { for (int j = 0; j < networkInfo2.Stations.Count; j++) { networkInfo2.Stations[j].Zdo.Set(CoreUtil.NetworkNameHash, text); CoreUtil.ForceSend(networkInfo2.Stations[j].Zdo); } if (Plugin.Registry != null) { Plugin.Registry.MarkDirty(); } } break; } case 3: { string key = p.ReadString(); bool flag = p.ReadInt() != 0; if (!IsSafeKey(key)) { break; } NetworkInfo networkInfo = FindNetworkByStation(val); if (networkInfo != null) { int num2 = CoreUtil.NetworkSettingHash(key); for (int i = 0; i < networkInfo.Stations.Count; i++) { networkInfo.Stations[i].Zdo.Set(num2, flag ? 1 : 0, false); CoreUtil.ForceSend(networkInfo.Stations[i].Zdo); } NetworkApi.RaiseNetworksChanged(); } break; } } } catch (Exception ex) { Plugin.LogWarning("Core RPC failed: " + ex.Message); } } private static NetworkInfo FindNetworkByStation(ZDOID id) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<NetworkInfo> networks = NetworkApi.Networks; for (int i = 0; i < networks.Count; i++) { for (int j = 0; j < networks[i].Stations.Count; j++) { ZDOID id2 = networks[i].Stations[j].Id; if (((ZDOID)(ref id2)).Equals(id)) { return networks[i]; } } } return null; } private static bool IsSafeKey(string key) { if (string.IsNullOrWhiteSpace(key) || key.Length > 64) { return false; } foreach (char c in key) { if (!char.IsLetterOrDigit(c) && c != '.' && c != '_' && c != '-') { return false; } } return true; } private static long GetServerPeerId() { try { _getServerPeerId = _getServerPeerId ?? AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", Type.EmptyTypes, (Type[])null); object obj = ((_getServerPeerId == null) ? null : _getServerPeerId.Invoke(ZRoutedRpc.instance, null)); return (obj is long) ? ((long)obj) : 0; } catch { return 0L; } } } internal static class CoreUtil { internal static readonly int ItemsHash = Stable("items"); internal static readonly int InUseHash = Stable("InUse"); internal static readonly int LegacyInUseHash = Stable("inUse"); internal static readonly int ReserveHash = Stable("mjnc_reserve"); internal static readonly int NetworkNameHash = Stable("mjnc_network_name"); internal static readonly int NetworkIdentityHash = Stable("mjnc_network_id_v2"); internal static readonly int StorageNetworkIdentityHash = Stable("mjnc_storage_network_id_v2"); internal static readonly int NetworkStationTypesHash = Stable("mjnc_network_station_types_v2"); internal static readonly int StorageNetworkEnabledHash = StringExtensionMethods.GetStableHashCode("mjnc_storage_network_enabled"); private static MethodInfo _forceSend; private static FieldInfo _zdoVarsInUse; private static FieldInfo _containerInUse; private static FieldInfo _inventoryGuiCurrentContainer; private static MethodInfo _mucInventoryBlockGet; private static MethodInfo _mucInventoryBlockAnyBlocked; private static bool _mucResolved; private static bool _mucUnavailable; internal static int Stable(string value) { return StringExtensionMethods.GetStableHashCode(value); } internal static int NetworkSettingHash(string key) { return Stable("mjnc_net_" + (key ?? string.Empty).Trim().ToLowerInvariant()); } internal static GameObject GetPrefab(ZDO zdo) { if (zdo == null || (Object)(object)ZNetScene.instance == (Object)null) { return null; } try { return ZNetScene.instance.GetPrefab(zdo.GetPrefab()); } catch { return null; } } internal static string PrefabName(GameObject go) { if ((Object)(object)go == (Object)null) { return string.Empty; } string text = ((Object)go).name ?? string.Empty; if (!text.EndsWith("(Clone)", StringComparison.Ordinal)) { return text; } return text.Substring(0, text.Length - 7); } internal static bool IsInUse(ZDO zdo) { if (zdo == null) { return false; } try { _zdoVarsInUse = _zdoVarsInUse ?? AccessTools.Field(typeof(ZDOVars), "s_inUse"); if (_zdoVarsInUse != null) { object value = _zdoVarsInUse.GetValue(null); if (value is int && zdo.GetInt((int)value, 0) != 0) { return true; } } } catch { } try { if (zdo.GetInt(InUseHash, 0) != 0) { return true; } } catch { } try { if (zdo.GetBool(InUseHash, false)) { return true; } } catch { } try { if (zdo.GetInt(LegacyInUseHash, 0) != 0) { return true; } } catch { } try { if (zdo.GetBool(LegacyInUseHash, false)) { return true; } } catch { } return false; } internal static bool IsInUse(StorageRef storage) { if (storage == null) { return false; } if (IsInUse(storage.Zdo)) { return true; } Container val = storage.Container; try { if ((Object)(object)val == (Object)null && (Object)(object)storage.GameObject != (Object)null) { val = storage.GameObject.GetComponent<Container>() ?? storage.GameObject.GetComponentInChildren<Container>(true); } } catch { } if ((Object)(object)val != (Object)null) { try { _containerInUse = _containerInUse ?? AccessTools.Field(typeof(Container), "m_inUse"); if (_containerInUse != null && (bool)_containerInUse.GetValue(val)) { return true; } } catch { } try { if ((Object)(object)InventoryGui.instance != (Object)null) { _inventoryGuiCurrentContainer = _inventoryGuiCurrentContainer ?? AccessTools.Field(typeof(InventoryGui), "m_currentContainer"); Container val2 = (Container)((_inventoryGuiCurrentContainer == null) ? null : /*isinst with value type is only supported in some contexts*/); if ((Object)(object)val2 != (Object)null && val2 == val) { return true; } } } catch { } try { Inventory inventory = val.GetInventory(); if (inventory != null && IsMultiUserChestTransactionPending(inventory)) { return true; } } catch { } } return false; } private static bool IsMultiUserChestTransactionPending(Inventory inventory) { if (inventory == null || _mucUnavailable) { return false; } try { Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos; if (pluginInfos == null || !pluginInfos.TryGetValue("com.maxsch.valheim.MultiUserChest", out var value) || value == null || (Object)(object)value.Instance == (Object)null) { return false; } if (!_mucResolved) { Type type = ((object)value.Instance).GetType().Assembly.GetType("MultiUserChest.InventoryBlock", throwOnError: false); if (type == null) { _mucUnavailable = true; return false; } _mucInventoryBlockGet = type.GetMethod("Get", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Inventory) }, null); _mucInventoryBlockAnyBlocked = type.GetMethod("IsAnySlotBlocked", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); _mucResolved = true; if (_mucInventoryBlockGet == null || _mucInventoryBlockAnyBlocked == null) { _mucUnavailable = true; return false; } } object obj = _mucInventoryBlockGet.Invoke(null, new object[1] { inventory }); if (obj == null) { return false; } object obj2 = _mucInventoryBlockAnyBlocked.Invoke(obj, null); return obj2 is bool && (bool)obj2; } catch { _mucUnavailable = true; return false; } } internal static void ForceSend(ZDO zdo) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || ZDOMan.instance == null) { return; } try { _forceSend = _forceSend ?? AccessTools.Method(typeof(ZDOMan), "ForceSendZDO", new Type[1] { typeof(ZDOID) }, (Type[])null); if (_forceSend != null) { _forceSend.Invoke(ZDOMan.instance, new object[1] { zdo.m_uid }); } } catch { } } internal static bool EnsureOwnership(StorageRef storage) { if (storage == null || storage.Zdo == null || IsInUse(storage)) { return false; } try { ZNetView val = (((Object)(object)storage.GameObject == (Object)null) ? null : storage.GameObject.GetComponent<ZNetView>()); if ((Object)(object)val != (Object)null && val.IsValid()) { if (!val.IsOwner()) { val.ClaimOwnership(); } if (!val.IsOwner() && ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())) { return false; } } return true; } catch { return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer(); } } } public enum StorageKind { VanillaContainer, MakailItemDrawer } public sealed class StationRef { public ZDO Zdo { get; internal set; } public ZDOID Id { get; internal set; } public GameObject GameObject { get; internal set; } public CraftingStation Station { get; internal set; } public Vector3 Position { get; internal set; } public float BuildRange { get; internal set; } public string StationName { get; internal set; } public string PrefabName { get; internal set; } public bool IsLive => (Object)(object)GameObject != (Object)null; public bool IsRelay { get; internal set; } } public sealed class StorageRef { public ZDO Zdo { get; internal set; } public ZDOID Id { get; internal set; } public GameObject GameObject { get; internal set; } public Container Container { get; internal set; } public StorageKind Kind { get; internal set; } public Vector3 Position { get; internal set; } public string PrefabName { get; internal set; } public int NetworkId { get; internal set; } public bool RequiresNetworkOptIn { get; internal set; } public bool NetworkOptInEnabled { get { if (RequiresNetworkOptIn) { if (Zdo != null) { return Zdo.GetBool(CoreUtil.StorageNetworkEnabledHash, false); } return false; } return true; } } } public sealed class TrackedWorldObject { public ZDO Zdo { get; internal set; } public ZDOID Id { get; internal set; } public GameObject GameObject { get; internal set; } public Vector3 Position { get; internal set; } public string PrefabName { get; internal set; } } public sealed class NetworkInfo { internal readonly List<StationRef> MutableStations = new List<StationRef>(); internal readonly List<StorageRef> MutableStorages = new List<StorageRef>(); internal readonly HashSet<string> KnownStationTypes = new HashSet<string>(StringComparer.Ordinal); public int Id { get; internal set; } public string Name { get; internal set; } public IReadOnlyList<StationRef> Stations => MutableStations; public IReadOnlyList<StorageRef> Storages => MutableStorages; public int StationCount { get { int num = 0; foreach (StationRef mutableStation in MutableStations) { if (mutableStation != null && !mutableStation.IsRelay) { num++; } } return num; } } public int StorageCount => MutableStorages.Count; public int LiveStationCount { get { int num = 0; for (int i = 0; i < MutableStations.Count; i++) { if (MutableStations[i] != null && !MutableStations[i].IsRelay && MutableStations[i].IsLive) { num++; } } return num; } } public int LiveStorageCount { get { int num = 0; for (int i = 0; i < MutableStorages.Count; i++) { if (MutableStorages[i] != null && (Object)(object)MutableStorages[i].GameObject != (Object)null) { num++; } } return num; } } public bool IsLoaded { get { if (LiveStationCount <= 0) { return LiveStorageCount > 0; } return true; } } public bool ContainsXZ(Vector3 point) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < MutableStations.Count; i++) { StationRef stationRef = MutableStations[i]; float num = point.x - stationRef.Position.x; float num2 = point.z - stationRef.Position.z; float buildRange = stationRef.BuildRange; if (num * num + num2 * num2 <= buildRange * buildRange) { return true; } } return false; } } public sealed class ResourceSnapshot { private readonly Dictionary<string, int> _total; private readonly Dictionary<string, int> _available; public IReadOnlyDictionary<string, int> Total => _total; public IReadOnlyDictionary<string, int> Available => _available; internal ResourceSnapshot(Dictionary<string, int> total, Dictionary<string, int> available) { _total = total; _available = available; } public int GetTotal(string prefab) { return GetEquivalent(_total, prefab); } public int GetAvailable(string prefab) { return GetEquivalent(_available, prefab); } private static int GetEquivalent(Dictionary<string, int> map, string prefab) { if (map == null || string.IsNullOrEmpty(prefab)) { return 0; } int num = 0; foreach (KeyValuePair<string, int> item in map) { if (StorageApi.AreEquivalentPrefabs(item.Key, prefab)) { num += item.Value; } } return num; } } internal sealed class StorageData { internal StorageRef Node; internal Inventory Inventory; internal string DrawerPrefab; internal int DrawerQuantity; internal bool Dirty; } internal sealed class UnionFind { private readonly int[] _parent; private readonly byte[] _rank; internal UnionFind(int n) { _parent = new int[n]; _rank = new byte[n]; for (int i = 0; i < n; i++) { _parent[i] = i; } } internal int Find(int x) { int num = _parent[x]; if (num != x) { _parent[x] = Find(num); } return _parent[x]; } internal void Union(int a, int b) { int num = Find(a); int num2 = Find(b); if (num != num2) { if (_rank[num] < _rank[num2]) { _parent[num] = num2; return; } if (_rank[num] > _rank[num2]) { _parent[num2] = num; return; } _parent[num2] = num; _rank[num]++; } } } public static class NetworkApi { private sealed class SnapshotEntry { internal int Revision; internal float At; internal ResourceSnapshot Snapshot; } public delegate void ReadOnlyResourceProvider(NetworkInfo network, IDictionary<string, int> total); private sealed class PlannedTake { internal StorageRef Storage; internal string Prefab; internal int Amount; } private static NetworkRegistry _registry; private static CoreConfig _settings; private static readonly Dictionary<int, SnapshotEntry> Snapshots = new Dictionary<int, SnapshotEntry>(); private static readonly List<ReadOnlyResourceProvider> ReadOnlyProviders = new List<ReadOnlyResourceProvider>(); public const string AutoStorageEnabledSetting = "autostorage.enabled"; private static readonly Dictionary<string, string> InventoryNamePrefabCache = new Dictionary<string, string>(StringComparer.Ordinal); public static int Revision { get { if (_registry != null) { return _registry.Revision; } return 0; } } public static IReadOnlyList<NetworkInfo> Networks { get { if (_registry != null) { return _registry.Networks; } return new NetworkInfo[0]; } } public static IEnumerable<StorageRef> Storages { get { if (_registry != null) { return _registry.Storages; } return new StorageRef[0]; } } public static IEnumerable<TrackedWorldObject> ActiveGroundDrops { get { if (_registry != null) { return _registry.GroundDrops; } return new TrackedWorldObject[0]; } } public static IEnumerable<TrackedWorldObject> ActiveCreatures { get { if (_registry != null) { return _registry.Creatures; } return new TrackedWorldObject[0]; } } public static IEnumerable<TrackedWorldObject> ActiveMachines { get { if (_registry != null) { return _registry.Machines; } return new TrackedWorldObject[0]; } } public static event Action NetworksChanged; public static event Action<TrackedWorldObject> GroundDropRegistered; public static event Action<TrackedWorldObject> CreatureRegistered; public static event Action<TrackedWorldObject> MachineRegistered; public static event Action<NetworkInfo> NetworkRenameRequested; public static event Action<ZDOID> StationDestroyed; internal static void Initialize(NetworkRegistry registry, CoreConfig settings) { _registry = registry; _settings = settings; registry.DropRegistered += delegate(TrackedWorldObject o) { if (NetworkApi.GroundDropRegistered != null) { NetworkApi.GroundDropRegistered(o); } }; registry.CreatureRegistered += delegate(TrackedWorldObject o) { if (NetworkApi.CreatureRegistered != null) { NetworkApi.CreatureRegistered(o); } }; registry.MachineRegistered += delegate(TrackedWorldObject o) { if (NetworkApi.MachineRegistered != null) { NetworkApi.MachineRegistered(o); } }; } internal static void Shutdown() { Snapshots.Clear(); } internal static void RaiseStationDestroyed(ZDOID id) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (NetworkApi.StationDestroyed != null) { NetworkApi.StationDestroyed(id); } } public static NetworkInfo GetNetworkForStation(CraftingStation station) { if (_registry != null) { return _registry.FindForStation(station); } return null; } public static NetworkInfo GetNetworkAt(Vector3 position) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_registry != null) { return _registry.FindForPosition(position); } return null; } public static NetworkInfo GetNetworkForBuildPiece(Piece piece, Vector3 position) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (_registry != null) { return _registry.FindForBuildPiece(piece, position); } return null; } public static NetworkInfo GetNetworkById(int id) { IReadOnlyList<NetworkInfo> networks = Networks; for (int i = 0; i < networks.Count; i++) { if (networks[i].Id == id) { return networks[i]; } } return null; } public static void RegisterReadOnlyResourceProvider(ReadOnlyResourceProvider provider) { if (provider != null && !ReadOnlyProviders.Contains(provider)) { ReadOnlyProviders.Add(provider); InvalidateSnapshots(); } } public static void UnregisterReadOnlyResourceProvider(ReadOnlyResourceProvider provider) { if (provider != null && ReadOnlyProviders.Remove(provider)) { InvalidateSnapshots(); } } public static bool GetNetworkBool(NetworkInfo network, string key, bool defaultValue) { if (network == null || string.IsNullOrWhiteSpace(key)) { return defaultValue; } int num = CoreUtil.NetworkSettingHash(key); bool flag = false; for (int i = 0; i < network.Stations.Count; i++) { ZDO zdo = network.Stations[i].Zdo; if (zdo != null) { switch (zdo.GetInt(num, int.MinValue)) { case 0: return false; case int.MinValue: continue; } flag = true; } } if (!flag) { return defaultValue; } return true; } public static void SetNetworkBool(NetworkInfo network, string key, bool value) { if (network != null && !string.IsNullOrWhiteSpace(key)) { CoreRpc.SetNetworkBool(network, key, value); } } public static List<StorageRef> GetStoragesNearest(NetworkInfo network, Vector3 origin) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) List<StorageRef> list = new List<StorageRef>(); if (network == null) { return list; } for (int i = 0; i < network.MutableStorages.Count; i++) { list.Add(network.MutableStorages[i]); } list.Sort((StorageRef a, StorageRef b) => SqrXZ(a.Position, origin).CompareTo(SqrXZ(b.Position, origin))); return list; } public static List<StorageRef> GetStoragesNear(Vector3 origin, float range) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) float num = range * range; List<StorageRef> list = new List<StorageRef>(); foreach (StorageRef storage in Storages) { if (SqrXZ(storage.Position, origin) <= num) { list.Add(storage); } } list.Sort((StorageRef a, StorageRef b) => SqrXZ(a.Position, origin).CompareTo(SqrXZ(b.Position, origin))); return list; } public static int GetAvailableForInventoryName(NetworkInfo network, string inventoryName) { if (network == null || string.IsNullOrEmpty(inventoryName)) { return 0; } ResourceSnapshot snapshot = GetSnapshot(network); int available = snapshot.GetAvailable(inventoryName); if (available > 0) { return available; } string text = ResolvePrefabNameFromInventoryName(inventoryName); if (!string.IsNullOrEmpty(text)) { return snapshot.GetAvailable(text); } return 0; } private static string ResolvePrefabNameFromInventoryName(string inventoryName) { if (InventoryNamePrefabCache.TryGetValue(inventoryName, out var value)) { return value; } string text = string.Empty; try { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance != (Object)null) { FieldInfo field = typeof(ObjectDB).GetField("m_items", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); IEnumerable enumerable = ((field == null) ? null : (field.GetValue(instance) as IEnumerable)); if (enumerable != null) { foreach (object item in enumerable) { GameObject val = (GameObject)((item is GameObject) ? item : null); if (!((Object)(object)val == (Object)null)) { string text2 = CoreUtil.PrefabName(val); if (string.Equals(text2, inventoryName, StringComparison.Ordinal)) { text = text2; break; } ItemDrop component = val.GetComponent<ItemDrop>(); if (string.Equals(((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null) ? string.Empty : component.m_itemData.m_shared.m_name, inventoryName, StringComparison.Ordinal)) { text = text2; break; } } } } } } catch { } InventoryNamePrefabCache[inventoryName] = text; return text; } public static ResourceSnapshot GetSnapshot(NetworkInfo network) { if (network == null) { return EmptySnapshot(); } float unscaledTime = Time.unscaledTime; float num = ((_settings == null) ? 0.25f : Mathf.Max(0.02f, _settings.SnapshotSeconds.Value)); if (Snapshots.TryGetValue(network.Id, out var value) && value.Revision == Revision && unscaledTime - value.At <= num) { return value.Snapshot; } Dictionary<string, int> total = new Dictionary<string, int>(StringComparer.Ordinal); Dictionary<string, int> available = new Dictionary<string, int>(StringComparer.Ordinal); for (int i = 0; i < network.MutableStorages.Count; i++) { StorageApi.TryAccumulateSnapshot(network.MutableStorages[i], total, available); } for (int j = 0; j < ReadOnlyProviders.Count; j++) { ReadOnlyResourceProvider readOnlyResourceProvider = ReadOnlyProviders[j]; if (readOnlyResourceProvider != null) { try { readOnlyResourceProvider(network, total); } catch (Exception ex) { Plugin.LogWarning("Read-only resource provider failed: " + ex.Message); } } } ResourceSnapshot resourceSnapshot = new ResourceSnapshot(total, available); Snapshots[network.Id] = new SnapshotEntry { Revision = Revision, At = unscaledTime, Snapshot = resourceSnapshot }; return resourceSnapshot; } public static bool CanWithdraw(NetworkInfo network, IDictionary<string, int> wanted) { if (network == null || wanted == null) { return false; } ResourceSnapshot snapshot = GetSnapshot(network); foreach (KeyValuePair<string, int> item in wanted) { if (item.Value > 0 && snapshot.GetAvailable(item.Key) < item.Value) { return false; } } return true; } public static bool TryWithdraw(NetworkInfo network, IDictionary<string, int> wanted, Vector3 origin, out string reason) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: 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_017b: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0411: Unknown result type (might be due to invalid IL or missing references) reason = string.Empty; if (network == null) { reason = "no network"; return false; } if (wanted == null || wanted.Count == 0) { return true; } if (!CanWithdraw(network, wanted)) { reason = "not enough available stock after reserve"; return false; } List<StorageRef> storagesNearest = GetStoragesNearest(network, origin); Dictionary<ZDOID, StorageData> dictionary = new Dictionary<ZDOID, StorageData>(); List<PlannedTake> list = new List<PlannedTake>(); HashSet<ZDOID> hashSet = new HashSet<ZDOID>(); foreach (KeyValuePair<string, int> item in wanted) { int num = Math.Max(0, item.Value); if (num <= 0) { continue; } for (int i = 0; i < storagesNearest.Count && num > 0; i++) { StorageRef storageRef = storagesNearest[i]; if (!dictionary.TryGetValue(storageRef.Id, out var value)) { if (!StorageApi.TryLoad(storageRef, out value)) { continue; } dictionary[storageRef.Id] = value; } int num2 = Math.Max(0, StorageApi.Count(value, item.Key) - StorageApi.GetReserve(storageRef)); if (num2 > 0) { int num3 = Math.Min(num2, num); list.Add(new PlannedTake { Storage = storageRef, Prefab = item.Key, Amount = num3 }); hashSet.Add(storageRef.Id); num -= num3; } } if (num > 0) { reason = "stock changed during preflight"; return false; } } foreach (ZDOID item2 in hashSet) { if (!dictionary.TryGetValue(item2, out var value2) || value2 == null || value2.Node == null) { reason = "planned container vanished"; return false; } if (!CoreUtil.EnsureOwnership(value2.Node)) { reason = "container busy or ownership unavailable"; return false; } } Dictionary<ZDOID, StorageData> dictionary2 = new Dictionary<ZDOID, StorageData>(); foreach (ZDOID item3 in hashSet) { if (!dictionary.TryGetValue(item3, out var value3) || value3 == null || value3.Node == null) { reason = "planned container vanished"; return false; } if (!StorageApi.TryLoad(value3.Node, out var data)) { reason = "container became busy or unreadable"; return false; } dictionary2[item3] = data; } Dictionary<string, int> dictionary3 = new Dictionary<string, int>(StringComparer.Ordinal); Dictionary<string, int> dictionary4 = new Dictionary<string, int>(StringComparer.Ordinal); for (int j = 0; j < list.Count; j++) { PlannedTake plannedTake = list[j]; string key = PlanKey(plannedTake.Storage.Id, plannedTake.Prefab); dictionary3.TryGetValue(key, out var value4); dictionary3[key] = value4 + plannedTake.Amount; } foreach (KeyValuePair<ZDOID, StorageData> item4 in dictionary2) { foreach (PlannedTake item5 in list) { ZDOID id = item5.Storage.Id; if (((ZDOID)(ref id)).Equals(item4.Key)) { string key2 = PlanKey(item4.Key, item5.Prefab); if (!dictionary4.ContainsKey(key2)) { dictionary4[key2] = Math.Max(0, StorageApi.Count(item4.Value, item5.Prefab) - StorageApi.GetReserve(item4.Value.Node)); } } } } foreach (KeyValuePair<string, int> item6 in dictionary3) { dictionary4.TryGetValue(item6.Key, out var value5); if (value5 < item6.Value) { reason = "container changed while acquiring ownership"; return false; } } for (int k = 0; k < list.Count; k++) { PlannedTake plannedTake2 = list[k]; if (!dictionary2.TryGetValue(plannedTake2.Storage.Id, out var value6)) { reason = "transaction storage missing"; return false; } if (StorageApi.RemoveAvailable(value6, plannedTake2.Prefab, plannedTake2.Amount) != plannedTake2.Amount) { reason = "unexpected removal mismatch"; return false; } } foreach (StorageData value7 in dictionary2.Values) { StorageApi.Save(value7); } InvalidateSnapshots(); return true; } private unsafe static string PlanKey(ZDOID id, string prefab) { return ((object)(*(ZDOID*)(&id))/*cast due to .constrained prefix*/).ToString() + "|" + (prefab ?? string.Empty); } private static ResourceSnapshot EmptySnapshot() { return new ResourceSnapshot(new Dictionary<string, int>(), new Dictionary<string, int>()); } public static string GetNetworkName(NetworkInfo network) { if (network == null || string.IsNullOrWhiteSpace(network.Name)) { return "Sonstige"; } return network.Name; } public static void SetNetworkName(NetworkInfo network, string name) { if (network != null) { CoreRpc.SetNetworkName(network, name ?? string.Empty); } } public static void InvalidateSnapshots() { Snapshots.Clear(); } internal static void RaiseNetworksChanged() { if (NetworkApi.NetworksChanged != null) { NetworkApi.NetworksChanged(); } } public static bool RequestNetworkRename(NetworkInfo network) { if (network == null || NetworkApi.NetworkRenameRequested == null) { return false; } NetworkApi.NetworkRenameRequested(network); return true; } private static Dictionary<string, int> CountLocal(List<ItemData> items) { Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal); for (int i = 0; i < items.Count; i++) { string prefabName = StorageApi.GetPrefabName(items[i]); if (!string.IsNullOrEmpty(prefabName)) { Add(dictionary, prefabName, items[i].m_stack); } } return dictionary; } private static void Add(Dictionary<string, int> d, string key, int amount) { if (amount > 0 && !string.IsNullOrEmpty(key)) { d.TryGetValue(key, out var value); d[key] = value + amount; } } private static float SqrXZ(Vector3 a, Vector3 b) { //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) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = a.x - b.x; float num2 = a.z - b.z; return num * num + num2 * num2; } } internal sealed class NetworkRegistry { private readonly Dictionary<ZDOID, StationRef> _stations = new Dictionary<ZDOID, StationRef>(); private readonly Dictionary<ZDOID, StorageRef> _storages = new Dictionary<ZDOID, StorageRef>(); private readonly Dictionary<ZDOID, TrackedWorldObject> _drops = new Dictionary<ZDOID, TrackedWorldObject>(); private readonly Dictionary<ZDOID, TrackedWorldObject> _creatures = new Dictionary<ZDOID, TrackedWorldObject>(); private readonly Dictionary<ZDOID, TrackedWorldObject> _machines = new Dictionary<ZDOID, TrackedWorldObject>(); private readonly List<NetworkInfo> _networks = new List<NetworkInfo>(); private readonly Dictionary<int, NetworkInfo> _byId = new Dictionary<int, NetworkInfo>(); private readonly Dictionary<ZDOID, NetworkInfo> _byStation = new Dictionary<ZDOID, NetworkInfo>(); private readonly HashSet<int> _splitPendingNetworkIds = new HashSet<int>(); private bool _dirty = true; private float _lastDirtyAt; private int _revision; private static MethodInfo _getExtensionCount; private static FieldInfo _extraRangePerLevel; private static FieldInfo _rangeBuild; private static MethodInfo _getStationBuildRange; private static FieldInfo _creatorHashField; private static int? _creatorHash; internal int Revision => _revision; internal IReadOnlyList<NetworkInfo> Networks => _networks; internal IEnumerable<StorageRef> Storages => _storages.Values; internal IEnumerable<TrackedWorldObject> GroundDrops => _drops.Values; internal IEnumerable<TrackedWorldObject> Creatures => _creatures.Values; internal IEnumerable<TrackedWorldObject> Machines => _machines.Values; internal event Action<TrackedWorldObject> DropRegistered; internal event Action<TrackedWorldObject> CreatureRegistered; internal event Action<TrackedWorldObject> MachineRegistered; internal void Reset() { _stations.Clear(); _storages.Clear(); _drops.Clear(); _creatures.Clear(); _machines.Clear(); _networks.Clear(); _byId.Clear(); _byStation.Clear(); _splitPendingNetworkIds.Clear(); _dirty = true; _lastDirtyAt = Time.unscaledTime; _revision++; NetworkApi.InvalidateSnapshots(); } internal void Register(ZDO zdo, GameObject instance) { //IL_0029: 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_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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_015f: 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_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_0400: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_04ac: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || (Object)(object)instance == (Object)null) { return; } GameObject val = CoreUtil.GetPrefab(zdo) ?? instance; Vector3 position; try { position = zdo.GetPosition(); } catch { position = instance.transform.position; } ZDOID uid = zdo.m_uid; bool flag = false; bool num = Plugin.Settings == null || !Plugin.Settings.PlayerBuiltOnly.Value || IsPlayerBuilt(zdo); string text = CoreUtil.PrefabName(val); CraftingStation val2 = FindStationComponent(instance); CraftingStation val3 = FindStationComponent(val); bool flag2 = string.Equals(text, "piece_mj_network_relay", StringComparison.OrdinalIgnoreCase); CraftingStation station; float num2; string text2; StationRef value; Vector3 val4; if (num && (flag2 || (Object)(object)val3 != (Object)null || (Object)(object)val2 != (Object)null)) { station = (flag2 ? null : (val2 ?? val3)); num2 = (flag2 ? 15f : GetBuildRange(station)); text2 = (flag2 ? string.Empty : GetStationName(station)); if (!_stations.TryGetValue(uid, out value)) { value = new StationRef(); _stations[uid] = value; flag = true; } else { if (value.GameObject == instance) { val4 = value.Position - position; if (!(((Vector3)(ref val4)).sqrMagnitude > 0.0001f) && !(Mathf.Abs(value.BuildRange - num2) > 0.001f) && string.Equals(value.StationName, text2, StringComparison.Ordinal)) { goto IL_0155; } } flag = true; } goto IL_0155; } goto IL_01a2; IL_02ea: StorageRef value2; value2.Zdo = zdo; value2.Id = uid; value2.GameObject = instance; Container val5; value2.Container = val5; StorageKind storageKind; value2.Kind = storageKind; value2.Position = position; value2.PrefabName = text; bool flag3; value2.RequiresNetworkOptIn = flag3; goto IL_032e; IL_0155: value.Zdo = zdo; value.Id = uid; value.GameObject = instance; value.Station = station; value.Position = position; value.BuildRange = num2; value.IsRelay = flag2; value.StationName = text2; value.PrefabName = text; goto IL_01a2; IL_01a2: flag3 = IsIncinerator(text, instance, val); val5 = instance.GetComponent<Container>(); Container val6 = val.GetComponent<Container>(); if (flag3) { if ((Object)(object)val5 == (Object)null) { val5 = instance.GetComponentInChildren<Container>(true); } if ((Object)(object)val6 == (Object)null) { val6 = val.GetComponentInChildren<Container>(true); } } bool flag4 = IsMakailDrawer(text); bool flag5 = (Object)(object)val.GetComponent<TombStone>() != (Object)null || (Object)(object)instance.GetComponent<TombStone>() != (Object)null; Piece val7 = val.GetComponent<Piece>() ?? instance.GetComponent<Piece>(); if (num && !flag5 && ((Object)(object)val5 != (Object)null || (Object)(object)val6 != (Object)null) && ((Object)(object)val7 != (Object)null || flag4)) { storageKind = (flag4 ? StorageKind.MakailItemDrawer : StorageKind.VanillaContainer); if (!_storages.TryGetValue(uid, out value2)) { value2 = new StorageRef(); value2.NetworkId = zdo.GetInt(CoreUtil.StorageNetworkIdentityHash, -1); _storages[uid] = value2; flag = true; } else { if (value2.GameObject == instance) { val4 = value2.Position - position; if (!(((Vector3)(ref val4)).sqrMagnitude > 0.0001f) && value2.Kind == storageKind && string.Equals(value2.PrefabName, text, StringComparison.Ordinal) && value2.RequiresNetworkOptIn == flag3) { goto IL_02ea; } } flag = true; } goto IL_02ea; } goto IL_032e; IL_032e: bool num3 = (Object)(object)val.GetComponent<ItemDrop>() != (Object)null || (Object)(object)instance.GetComponent<ItemDrop>() != (Object)null; bool flag6 = (Object)(object)(instance.GetComponent<Fish>() ?? val.GetComponent<Fish>()) != (Object)null; if (num3 && !flag6) { TrackedWorldObject trackedWorldObject = MakeTracked(zdo, instance, val, position); bool num4 = !_drops.ContainsKey(uid); _drops[uid] = trackedWorldObject; if (num4 && this.DropRegistered != null) { this.DropRegistered(trackedWorldObject); } } else if (flag6) { _drops.Remove(uid); } Tameable obj2 = instance.GetComponent<Tameable>() ?? val.GetComponent<Tameable>(); MonsterAI val8 = instance.GetComponent<MonsterAI>() ?? val.GetComponent<MonsterAI>(); if ((Object)(object)obj2 != (Object)null && (Object)(object)val8 != (Object)null) { TrackedWorldObject trackedWorldObject2 = MakeTracked(zdo, instance, val, position); bool num5 = !_creatures.ContainsKey(uid); _creatures[uid] = trackedWorldObject2; if (num5 && this.CreatureRegistered != null) { this.CreatureRegistered(trackedWorldObject2); } } if ((Object)(object)(instance.GetComponent<Smelter>() ?? val.GetComponent<Smelter>()) != (Object)null || (Object)(object)(instance.GetComponent<Fireplace>() ?? val.GetComponent<Fireplace>()) != (Object)null || (Object)(object)(instance.GetComponent<CookingStation>() ?? val.GetComponent<CookingStation>()) != (Object)null || (Object)(object)(instance.GetComponent<Fermenter>() ?? val.GetComponent<Fermenter>()) != (Object)null || (Object)(object)(instance.GetComponent<ShieldGenerator>() ?? val.GetComponent<ShieldGenerator>()) != (Object)null) { TrackedWorldObject trackedWorldObject3 = MakeTracked(zdo, instance, val, position); bool num6 = !_machines.ContainsKey(uid); _machines[uid] = trackedWorldObject3; if (num6 && this.MachineRegistered != null) { this.MachineRegistered(trackedWorldObject3); } } if (flag) { MarkDirty(); } } internal void Unregister(ZDOID id, GameObject instance) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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) if (_stations.TryGetValue(id, out var value) && ((Object)(object)instance == (Object)null || value.GameObject == instance)) { value.GameObject = null; value.Station = null; } if (_storages.TryGetValue(id, out var value2) && ((Object)(object)instance == (Object)null || value2.GameObject == instance)) { value2.GameObject = null; value2.Container = null; } if (_drops.TryGetValue(id, out var value3) && ((Object)(object)instance == (Object)null || value3.GameObject == instance)) { _drops.Remove(id); } if (_creatures.TryGetValue(id, out value3) && ((Object)(object)instance == (Object)null || value3.GameObject == instance)) { _creatures.Remove(id); } if (_machines.TryGetValue(id, out value3) && ((Object)(object)instance == (Object)null || value3.GameObject == instance)) { _machines.Remove(id); } } internal void ForgetDestroyed(ZDOID id) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0078: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) bool flag = false; bool flag2 = false; int num = 0; if (_stations.TryGetValue(id, out var value)) { flag2 = true; try { if (value.Zdo != null) { num = value.Zdo.GetInt(CoreUtil.NetworkIdentityHash, 0); } } catch { } flag |= _stations.Remove(id); } if (_storages.TryGetValue(id, out var _)) { flag |= _storages.Remove(id); } _drops.Remove(id); _creatures.Remove(id); _machines.Remove(id); if (num > 0) { _splitPendingNetworkIds.Add(num); } if (flag2) { NetworkApi.RaiseStationDestroyed(id); } if (flag) { MarkDirty(); } } internal void ForgetDrop(ZDOID id) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _drops.Remove(id); } internal void MarkDirty() { _dirty = true; _lastDirtyAt = Time.unscaledTime; NetworkApi.InvalidateSnapshots(); } internal void RebuildIfDirty(float now) { if (_dirty) { float num = ((Plugin.Settings == null) ? 0.2f : Mathf.Max(0f, Plugin.Settings.RebuildDebounceSeconds.Value)); if (!(now - _lastDirtyAt < num)) { Rebuild(); } } } internal NetworkInfo FindForStation(CraftingStation station) { //IL_0060: 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) if ((Object)(object)station == (Object)null) { return null; } try { ZNetView val = ((Component)station).GetComponent<ZNetView>() ?? ((Component)station).GetComponentInParent<ZNetView>(); ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null); if (val2 != null && _byStation.TryGetValue(val2.m_uid, out var value)) { return value; } } catch { } return FindForPosition(((Component)station).transform.position); } internal NetworkInfo FindForPosition(Vector3 point) { //IL_001a: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) NetworkInfo result = null; float num = float.MaxValue; for (int i = 0; i < _networks.Count; i++) { NetworkInfo networkInfo = _networks[i]; if (!networkInfo.ContainsXZ(point)) { continue; } for (int j = 0; j < networkInfo.MutableStations.Count; j++) { Vector3 position = networkInfo.MutableStations[j].Position; float num2 = position.x - point.x; float num3 = position.z - point.z; float num4 = num2 * num2 + num3 * num3; if (num4 < num) { num = num4; result = networkInfo; } } } return result; } internal NetworkInfo FindForBuildPiece(Piece piece, Vector3 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) NetworkInfo networkInfo = FindForPosition(point); if ((Object)(object)piece == (Object)null) { return networkInfo; } CraftingStation craftingStation = piece.m_craftingStation; if ((Object)(object)craftingStation == (Object)null) { return networkInfo; } if (networkInfo == null) { return null; } if (!SupportsStation(networkInfo, GetStationName(craftingStation))) { return null; } return networkInfo; } internal bool SupportsStation(NetworkInfo network, string wanted) { if (network == null || string.IsNullOrEmpty(wanted)) { return false; } string text = NormalizeStationKey(wanted); if (text.Length == 0) { return false; } if (network.KnownStationTypes.Contains(text)) { return true; } for (int i = 0; i < network.MutableStations.Count; i++) { if (StationMatchesName(network.MutableStations[i], wanted)) { return true; } } return false; } internal CraftingStation FindRepresentativeStation(NetworkInfo network, string wanted) { if (network == null || !SupportsStation(network, wanted)) { return null; } for (int i = 0; i < network.MutableStations.Count; i++) { StationRef stationRef = network.MutableStations[i]; if (!StationMatchesName(stationRef, wanted)) { continue; } if ((Object)(object)stationRef.Station != (Object)null) { return stationRef.Station; } try { CraftingStation val = FindStationComponent((stationRef.Zdo == null) ? null : CoreUtil.GetPrefab(stationRef.Zdo)); if ((Object)(object)val != (Object)null) { return val; } } catch { } } try { string text = NormalizeStationKey(wanted); CraftingStation[] array = Resources.FindObjectsOfTypeAll<CraftingStation>(); foreach (CraftingStation val2 in array) { if (!((Object)(object)val2 == (Object)null) && (NormalizeStationKey(GetStationName(val2)) == text || NormalizeStationKey(CoreUtil.PrefabName(((Component)val2).gameObject)) == text)) { return val2; } } } catch { } for (int k = 0; k < network.MutableStations.Count; k++) { if (network.MutableStations[k] != null && (Object)(object)network.MutableStations[k].Station != (Object)null) { return network.MutableStations[k].Station; } } return null; } private void Rebuild() { //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_058f: Unknown result type (might be due to invalid IL or missing references) //IL_059b: Unknown result type (might be due to invalid IL or missing references) //IL_05a8: Unknown result type (might be due to invalid IL or missing references) //IL_05b4: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) _dirty = false; _networks.Clear(); _byId.Clear(); _byStation.Clear(); List<StationRef> list = new List<StationRef>(_stations.Values); for (int i = 0; i < list.Count; i++) { StationRef stationRef = list[i]; if (stationRef == null) { continue; } if ((Object)(object)stationRef.Station != (Object)null) { stationRef.BuildRange = GetBuildRange(stationRef.Station); stationRef.StationName = GetStationName(stationRef.Station); if ((Object)(object)stationRef.GameObject != (Object)null) { stationRef.PrefabName = CoreUtil.PrefabName(stationRef.GameObject); } } if (stationRef.BuildRange <= 0f) { stationRef.BuildRange = 20f; } } UnionFind unionFind = new UnionFind(list.Count); for (int j = 0; j < list.Count; j++) { for (int k = j + 1; k < list.Count; k++) { StationRef stationRef2 = list[j]; StationRef stationRef3 = list[k]; float num = stationRef2.Position.x - stationRef3.Position.x; float num2 = stationRef2.Position.z - stationRef3.Position.z; float num3 = stationRef2.BuildRange + stationRef3.BuildRange; if (num * num + num2 * num2 <= num3 * num3) { unionFind.Union(j, k); } } } Dictionary<int, int> dictionary = new Dictionary<int, int>(); for (int l = 0; l < list.Count; l++) { int num4 = ReadInt((list[l] == null) ? null : list[l].Zdo, CoreUtil.NetworkIdentityHash, 0); if (num4 > 0 && !_splitPendingNetworkIds.Contains(num4)) { if (dictionary.TryGetValue(num4, out var value)) { unionFind.Union(value, l); } else { dictionary[num4] = l; } } } Dictionary<int, List<StationRef>> dictionary2 = new Dictionary<int, List<StationRef>>(); for (int m = 0; m < list.Count; m++) { int key = unionFind.Find(m); if (!dictionary2.TryGetValue(key, out var value2)) { value2 = (dictionary2[key] = new List<StationRef>()); } value2.Add(list[m]); } List<List<StationRef>> list3 = new List<List<StationRef>>(dictionary2.Values); list3.Sort((List<StationRef> a, List<StationRef> b) => string.CompareOrdinal(SmallestStationKey(a), SmallestStationKey(b))); HashSet<int> hashSet = new HashSet<int>(); for (int num5 = 0; num5 < list3.Count; num5++) { List<StationRef> list4 = list3[num5]; bool flag = false; for (int num6 = 0; num6 < list4.Count; num6++) { if (list4[num6] != null && !list4[num6].IsRelay) { flag = true; break; } } if (!flag) { continue; } int num7 = ChoosePersistentNetworkId(list4); if (num7 <= 0 || hashSet.Contains(num7)) { num7 = DeriveUniqueNetworkId(list4, hashSet); } hashSet.Add(num7); NetworkInfo networkInfo = new NetworkInfo { Id = num7, Name = string.Empty }; _networks.Add(networkInfo); _byId[num7] = networkInfo; for (int num8 = 0; num8 < list4.Count; num8++) { StationRef stationRef4 = list4[num8]; if (stationRef4 != null) { networkInfo.MutableStations.Add(stationRef4); _byStation[stationRef4.Id] = networkInfo; if (!stationRef4.IsRelay) { AddStationType(networkInfo.KnownStationTypes, stationRef4.StationName); AddStationType(networkInfo.KnownStationTypes, stationRef4.PrefabName); AddPersistedStationTypes(networkInfo.KnownStationTypes, stationRef4.Zdo); } } } string text = SerializeStationTypes(networkInfo.KnownStationTypes); if (!CanPersistMetadata()) { continue; } for (int num9 = 0; num9 < list4.Count; num9++) { StationRef stationRef5 = list4[num9]; if (stationRef5 == null || stationRef5.Zdo == null) { continue; } try { bool flag2 = false; if (stationRef5.Zdo.GetInt(CoreUtil.NetworkIdentityHash, 0) != num7) { stationRef5.Zdo.Set(CoreUtil.NetworkIdentityHash, num7, false); flag2 = true; } if (!string.Equals(stationRef5.Zdo.GetString(CoreUtil.NetworkStationTypesHash, string.Empty), text, StringComparison.Ordinal)) { stationRef5.Zdo.Set(CoreUtil.NetworkStationTypesHash, text); flag2 = true; } if (flag2) { CoreUtil.ForceSend(stationRef5.Zdo); } } catch { } } } for (int num10 = 0; num10 < _networks.Count; num10++) { _networks[num10].Name = ResolveName(_networks[num10]); } float num11 = ((Plugin.Settings == null) ? 0f : Mathf.Max(0f, Plugin.Settings.StorageAttachExtraRange.Value)); foreach (StorageRef value4 in _storages.Values) { if (value4 == null) { continue; } value4.NetworkId = -1; if (value4.RequiresNetworkOptIn && !value4.NetworkOptInEnabled) { continue; } NetworkInfo value3 = null; float num12 = float.MaxValue; for (int num13 = 0; num13 < _networks.Count; num13++) { NetworkInfo networkInfo2 = _networks[num13]; for (int num14 = 0; num14 < networkInfo2.MutableStations.Count; num14++) { StationRef stationRef6 = networkInfo2.MutableStations[num14]; float num15 = value4.Position.x - stationRef6.Position.x; float num16 = value4.Position.z - stationRef6.Position.z; float num17 = num15 * num15 + num16 * num16; float num18 = stationRef6.BuildRange + num11; if (num17 <= num18 * num18 && num17 < num12) { num12 = num17; value3 = networkInfo2; } } } if (value3 == null) { int num19 = ReadInt(value4.Zdo, CoreUtil.StorageNetworkIdentityHash, -1); if (num19 > 0) { _byId.TryGetValue(num19, out value3); } } if (value3 == null) { continue; } value4.NetworkId = value3.Id; value3.MutableStorages.Add(value4); if (!CanPersistMetadata() || value4.Zdo == null) { continue; } try { if (value4.Zdo.GetInt(CoreUtil.StorageNetworkIdentityHash, -1) != value3.Id) { value4.Zdo.Set(CoreUtil.StorageNetworkIdentityHash, value3.Id, false); CoreUtil.ForceSend(value4.Zdo); } } catch { } } _splitPendingNetworkIds.Clear(); _revision++; NetworkApi.InvalidateSnapshots(); NetworkApi.RaiseNetworksChanged(); Plugin.LogDebug("Network rebuild: stations=" + list.Count + ", storages=" + _storages.Count + ", networks=" + _networks.Count + ", rev=" + _revision); } private static string SmallestStationKey(List<StationRef> members) { //IL_0015: 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) string text = null; if (members != null) { for (int i = 0; i < members.Count; i++) { StationRef stationRef = members[i]; if (stationRef != null) { string text2 = ((object)stationRef.Id/*cast due to .constrained prefix*/).ToString(); if (text == null || string.CompareOrdinal(text2, text) < 0) { text = text2; } } } } return text ?? string.Empty; } private static int DeriveUniqueNetworkId(List<StationRef> members, HashSet<int> assigned) { string text = SmallestStationKey(members); int num = 0; int num2; while (true) { num2 = StringExtensionMethods.GetStableHashCode("mjnc-network|" + text + ((num == 0) ? string.Empty : ("|" + num))) & 0x7FFFFFFF; if (num2 == 0) { num2 = 1; } if (assigned == null || !assigned.Contains(num2)) { break; } num++; } return num2; } private static int ChoosePersistentNetworkId(List<StationRef> members) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) int num = 0; string text = null; for (int i = 0; i < members.Count; i++) { StationRef stationRef = members[i]; if (stationRef != null) { int num2 = ReadInt(stationRef.Zdo, CoreUtil.NetworkIdentityHash, 0); if (num2 > 0 && (num == 0 || num2 < num)) { num = num2; } string text2 = ((object)stationRef.Id/*cast due to .constrained prefix*/).ToString(); if (text == null || string.CompareOrdinal(text2, text) < 0) { text = text2; } } } if (num > 0) { return num; } int num3 = StringExtensionMethods.GetStableHashCode("mjnc-network|" + (text ?? Guid.NewGuid().ToString("N"))) & 0x7FFFFFFF; if (num3 != 0) { return num3; } return 1; } private static int ReadInt(ZDO zdo, int hash, int fallback) { if (zdo == null) { return fallback; } try { return zdo.GetInt(hash, fallback); } catch { return fallback; } } private static bool CanPersistMetadata() { try { return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer(); } catch { return false; } } private static void AddStationType(HashSet<string> set, string value) { if (set != null) { string text = NormalizeStationKey(value); if (text.Length > 0) { set.Add(text); } } } private static void AddPersistedStationTypes(HashSet<string> set, ZDO zdo) { if (set == null || zdo == null) { return; } try { string text = zdo.GetString(CoreUtil.NetworkStationTypesHash, string.Empty); if (!string.IsNullOrEmpty(text)) { string[] array = text.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { AddStationType(set, array[i]); } } } catch { } } private static string SerializeStationTypes(HashSet<string> set) { if (set == null || set.Count == 0) { return string.Empty; } List<string> list = new List<string>(set); list.Sort(StringComparer.Ordinal); return string.Join(";", list.ToArray()); } private string ResolveName(NetworkInfo n) { for (int i = 0; i < n.MutableStations.Count; i++) { string text = n.MutableStations[i].Zdo.GetString(CoreUtil.NetworkNameHash, string.Empty); if (!string.IsNullOrWhiteSpace(text)) { return text.Trim(); } } return string.Empty; } private static TrackedWorldObject MakeTracked(ZDO zdo, GameObject instance, GameObject prefab, Vector3 pos) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) return new TrackedWorldObject { Zdo = zdo, Id = zdo.m_uid, GameObject = instance, Position = pos, PrefabName = CoreUtil.PrefabName(prefab) }; } private static bool IsIncinerator(string prefabName, GameObject instance, GameObject prefab) { string text = (prefabName ?? string.Empty).ToLowerInvariant(); if (text.Contains("incinerator") || text.Contains("obliterator") || text.Contains("vernichter")) { return true; } try { Type type = typeof(Player).Assembly.GetType("Incinerator"); if (type != null && (((Object)(object)instance != (Object)null && (Object)(object)instance.GetComponent(type) != (Object)null) || ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent(type) != (Object)null))) { return true; } } catch { } return false; } private static bool IsPlayerBuilt(ZDO zdo) { if (zdo == null) { return false; } try { if (!_creatorHash.HasValue) { int value = StringExtensionMethods.GetStableHashCode("creator"); Type type = typeof(ZDO).Assembly.GetType("ZDOVars"); if (type != null) { _creatorHashField = _creatorHashField ?? type.GetField("s_creator", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (_creatorHashField != null && _creatorHashField.FieldType == typeof(int)) { value = (int)_creatorHashField.GetValue(null); } } _creatorHash = value; } return zdo.GetLong(_creatorHash.Value, 0L) != 0; } catch { return true; } } private static bool IsMakailDrawer(string prefabName) { return string.Equals(prefabName, "piece_drawer", StringComparison.OrdinalIgnoreCase); } internal static float GetBuildRange(CraftingStation station) { if ((Object)(object)station == (Object)null) { return 20f; } try { _getStationBuildRange = _getStationBuildRange ?? AccessTools.Method(typeof(CraftingStation), "GetStationBuildRange", Type.EmptyTypes, (Type[])null); if (_getStationBuildRange != null) { object obj = _getStationBuildRange.Invoke(station, null); if (obj != null) { return Mathf.Max(1f, Convert.ToSingle(obj)); } } _rangeBuild = _rangeBuild ?? AccessTools.Field(typeof(CraftingStation), "m_rangeBuild"); float num = ((_rangeBuild != null) ? Convert.ToSingle(_rangeBuild.GetValue(station)) : 20f); _getExtensionCount = _getExtensionCount ?? AccessTools.Method(typeof(CraftingStation), "GetExtentionCount", new Type[1] { typeof(bool) }, (Type[])null); _extraRangePerLevel = _extraRangePerLevel ?? AccessTools.Field(typeof(CraftingStation), "m_extraRangePerLevel"); if (_getExtensionCount != null && _extraRangePerLevel != null) { object obj2 = _getExtensionCount.Invoke(station, new object[1] { false }); int num2 = ((obj2 is int) ? ((int)obj2) : 0); num += (float)num2 * Convert.ToSingle(_extraRangePerLevel.GetValue(station)); } return Mathf.Max(1f, num); } catch { return 20f; } } private static CraftingStation FindStationComponent(GameObject go) { if ((Object)(object)go == (Object)null) { return null; } CraftingStation component = go.GetComponent<CraftingStation>(); if ((Object)(object)component != (Object)null) { return component; } try { return go.GetComponentInChildren<CraftingStation>(true); } catch { return null; } } internal static bool StationMatchesName(StationRef station, string wanted) { if (station == null || string.IsNullOrEmpty(wanted)) { return false; } if (string.Equals(station.StationName, wanted, StringComparison.Ordinal)) { return true; } string text = NormalizeStationKey(wanted); if (text.Length == 0) { return false; } if (string.Equals(NormalizeStationKey(station.StationName), text, StringComparison.Ordinal)) { return true; } if (string.Equals(NormalizeStationKey(station.PrefabName), text, StringComparison.Ordinal)) { return true; } try { CraftingStation station2 = station.Station; if ((Object)(object)station2 != (Object)null) { string stationName = GetStationName(station2); if (string.Equals(stationName, wanted, StringComparison.Ordinal) || string.Equals(NormalizeStationKey(stationName), text, StringComparison.Ordinal)) { return true; } } } catch { } try { GameObject gameObject = station.GameObject; if ((Object)(object)gameObject != (Object)null) { string text2 = CoreUtil.PrefabName(gameObject); if (string.Equals(text2, wanted, StringComparison.Ordinal) || string.Equals(NormalizeStationKey(text2), text, StringComparison.Ordinal)) { return true; } } } catch { } return false; } internal static string NormalizeStationKey(string value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } string text = value.Trim(); if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - 7); } text = text.Trim().ToLowerInvariant(); if (text.StartsWith("$piece_", StringComparison.Ordinal)) { text = text.Substring(7); } else if (text.StartsWith("piece_", StringComparison.Ordinal)) { text = text.Substring(6); } else if (text.StartsWith("$", StringComparison.Ordinal)) { text = text.Substring(1); } char[] array = text.ToCharArray(); StringBuilder stringBuilder = new StringBuilder(array.Length); foreach (char c in array) { if (char.IsLetterOrDigit(c)) { stringBuilder.Append(c); } } string text2 = stringBuilder.ToString(); switch (text2) { case "steinmetz": case "stonecutter": case "stonemason": return "stonecutter"; case "werkbank": case "workbench": return "workbench"; case "schmiede": case "forge": return "forge"; case "schwarzschmiede": case "blackforge": return "blackforge"; default: return text2; } } internal static string GetStationName(CraftingStation station) { if ((Object)(object)station == (Object)null) { return string.Empty; } try { return station.m_name ?? string.Empty; } catch { return ((Object)(object)((Component)station).gameObject != (Object)null) ? ((Object)((Component)station).gameObject).name : string.Empty; } } } internal static class PatchBootstrap { internal static void Install(Harmony harmony) { Patch(harmony, AccessTools.Method(typeof(ZNetView), "Awake", (Type[])null, (Type[])null), null, AccessTools.Method(typeof(ZNetViewAwakePatch), "Postfix", (Type[])null, (Type[])null), "ZNetView.Awake"); Patch(harmony, AccessTools.Method(typeof(ZNetView), "OnDestroy", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZNetViewDestroyPatch), "Prefix", (Type[])null, (Type[])null), null, "ZNetView.OnDestroy"); Patch(harmony, AccessTools.Method(typeof(Container), "OnContainerChanged", (Type[])null, (Type[])null), null, AccessTools.Method(typeof(ContainerChangedPatch), "Postfix", (Type[])null, (Type[])null), "Container.OnContainerChanged", optional: true); MethodInfo postfix = AccessTools.Method(typeof(PieceSetCreatorPatch), "Postfix", (Type[])null, (Type[])null); MethodInfo[] methods = typeof(Piece).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "SetCreator" && methodInfo.ReturnType == typeof(void)) { Patch(harmony, methodInfo, null, postfix, "Piece.SetCreator", optional: true); } } MethodInfo postfix2 = AccessTools.Method(typeof(CraftingStationHoverPatch), "Postfix", (Type[])null, (Type[])null); MethodInfo[] methods2 = typeof(CraftingStation).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in methods2) { if (methodInfo2.Name == "GetHoverText" && methodInfo2.ReturnType == typeof(string) && methodInfo2.GetParameters().Length == 0) { Patch(harmony, methodInfo2, null, postfix2, "CraftingStation.GetHoverText", optional: true); } } MethodInfo postfix3 = AccessTools.Method(typeof(NetworkWideBuildStationPatch), "Postfix", (Type[])null, (Type[])null); MethodInfo[] methods3 = typeof(CraftingStation).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo3 in methods3) { if (methodInfo3.Name == "HaveBuildStationInRange" && methodInfo3.ReturnType == typeof(CraftingStation)) { Patch(harmony, methodInfo3, null, postfix3, "CraftingStation.HaveBuildStationInRange(network-wide)", optional: true); } } MethodInfo prefix = AccessTools.Method(typeof(ZdoDestroyedPatch), "Prefix", (Type[])null, (Type[])null); MethodInfo[] methods4 = typeof(ZDOMan).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo4 in methods4) { if (methodInfo4.Name != "DestroyZDO") { continue; } ParameterInfo[] parameters = methodInfo4.GetParameters(); bool flag = false; for (int m = 0; m < parameters.Length; m++) { if (parameters[m].ParameterType == typeof(ZDOID) || parameters[m].ParameterType == typeof(ZDO)) { flag = true; break; } } if (flag) { Patch(harmony, methodInfo4, prefix, null, "ZDOMan.DestroyZDO(persistent-network cleanup)", optional: true); } } MethodInfo prefix2 = AccessTools.Method(typeof(WearNTearRemovePatch), "Prefix", (Type[])null, (Type[])null); MethodInfo[] methods5 = typeof(WearNTear).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo5 in methods5) { if (methodInfo5.Name == "Remove") { Patch(harmony, methodInfo5, prefix2, null, "WearNTear.Remove(real station removal)", optional: true); } } MethodInfo postfix4 = AccessTools.Method(typeof(ContainerNetworkHoverPatch), "Postfix", (Type[])null, (Type[])null); MethodInfo[] methods6 = typeof(Container).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo6 in methods6) { if (methodInfo6.Name == "GetHoverText" && methodInfo6.ReturnType == typeof(string) && methodInfo6.GetParameters().Length == 0) { Patch(harmony, methodInfo6, null, postfix4, "Container.GetHoverText(network opt-in)", optional: true); } } } private static void Patch(Harmony harmony, MethodBase original, MethodInfo prefix, MethodInfo postfix, string label, bool optional = false) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (original == null) { if (!optional) { Plugin.LogWarning("Core patch target missing: " + label); } else { Plugin.LogDebug("Optional core patch target missing: " + label); } return; } try { HarmonyMethod val = ((prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(prefix)); HarmonyMethod val2 = ((postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(postfix)); harmony.Patch(original, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.LogDebug("Patched core target: " + label); } catch (Exception ex) { Plugin.LogWarning("Core patch failed " + label + ": " + ex.Message); } } } internal static class ZNetViewAwakePatch { private static void Postfix(ZNetView __instance) { ActiveObjectHooks.RegisterView(__instance); } } internal static class ZNetViewDestroyPatch { private static void Prefix(ZNetView __instance) { ActiveObjectHooks.UnregisterView(__instance); } } internal static class ContainerChangedPatch { private static void Postfix(Container __instance) { NetworkApi.InvalidateSnapshots(); } } internal static class PieceSetCreatorPatch { [HarmonyPriority(0)] private static void Postfix(Piece __instance) { try { if ((Object)(object)__instance == (Object)null || Plugin.Registry == null) { return; } ZNetView val = ((Component)__instance).GetComponent<ZNetView>() ?? ((Component)__instance).GetComponentInParent<ZNetView>(); if ((Object)(object)val == (Object)null || !val.IsValid()) { return; } bool flag = (Object)(object)((Component)__instance).GetComponent<CraftingStation>() != (Object)null || (Object)(object)((Component)__instance).GetComponentInChildren<CraftingStation>(true) != (Object)null; bool flag2 = (Object)(object)((Component)__instance).GetComponent<Container>() != (Object)null; bool flag3 = ((Object)((Component)__instance).gameObject).name.StartsWith("piece_mj_network_relay", StringComparison.OrdinalIgnoreCase); if (flag || flag2 || flag3) { ActiveObjectHooks.RegisterView(val); if (flag || flag3) { Plugin.Registry.RebuildIfDirty(float.MaxValue); } } } catch { } } } internal static class CraftingStationHoverPatch { [HarmonyPriority(0)] private static void Postfix(CraftingStation __instance, ref string __result) { try { __result = CoreClientControls.AppendStationHover(__instance, __result); } catch { } } } internal static class ContainerNetworkHoverPatch { [HarmonyPriority(0)] private static void Postfix(Container __instance, ref string __result) { try { if ((Object)(object)__instance != (Object)null) { __result = CoreClientControls.AppendStorageHover(((Component)__instance).gameObject, __result); } } catch { } } } internal static class NetworkWideBuildStationPatch { private static readonly Dictionary<string, CraftingStation> VirtualStations = new Dictionary<string, CraftingStation>(StringComparer.Ordinal); [HarmonyPriority(0)] private unsafe static void Postfix(object[] __args, ref CraftingStation __result) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__result != (Object)null || Plugin.Settings == null || !Plugin.Settings.NetworkWideBuildStations.Value || Plugin.Registry == null) { return; } string text = null; Vector3 val = Vector3.zero; bool flag = false; if (__args != null) { for (int i = 0; i < __args.Length; i++) { if (text == null && __args[i] is string) { text = (string)__args[i]; } if (!flag && __args[i] is Vector3) { val = (Vector3)__args[i]; flag = true; } } } if (string.IsNullOrEmpty(text) || !flag) { return; } Plugin.Registry.RebuildIfDirty(float.MaxValue); NetworkInfo networkAt = NetworkApi.GetNetworkAt(val); if (networkAt == null || !Plugin.Registry.SupportsStation(networkAt, text)) { CraftingStation[] array = Object.FindObjectsOfType<CraftingStation>(); foreach (CraftingStation val2 in array) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null) && !(NetworkRegistry.NormalizeStationKey(NetworkRegistry.GetStationName(val2)) != NetworkRegistry.NormalizeStationKey(text))) { float num = val.x - ((Component)val2).transform.position.x; float num2 = val.z - ((Component)val2).transform.position.z; if (!(num * num + num2 * num2 > 100f)) { __result = val2; break; } } } } else { __result = GetVirtualStation(text); string[] obj = new string[6] { "Network-wide station satisfied: ", text, " at ", null, null, null }; Vector3 val3 = val; obj[3] = ((object)(*(Vector3*)(&val3))/*cast due to .constrained prefix*/).ToString(); obj[4] = " via network "; obj[5] = networkAt.Id.ToString(); Plugin.LogDebug(string.Concat(obj)); } } catch (Exception ex) { Plugin.LogDebug("Network-wide station patch failed: " + ex.Message); } } private static CraftingStation GetVirtualStation(string name) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) string text = NetworkRegistry.NormalizeStationKey(name); if (VirtualStations.TryGetValue(text, out var value) && (Object)(object)value != (Object)null) { value.m_name = name; return value; } GameObject val = new GameObject("MJNC_VirtualBuildStation_" + (string.IsNullOrEmpty(text) ? "station" : text)) { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)val); val.SetActive(false); value = val.AddComponent<CraftingStation>(); value.m_name = name; VirtualStations[text] = value; return value; } } internal static class WearNTearRemovePatch { [HarmonyPriority(800)] private static void Prefix(WearNTear __instance) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null || Plugin.Registry == null) { return; } GameObject gameObject = ((Component)__instance).gameObject; CraftingStation val = gameObject.GetComponent<CraftingStation>(); if ((Object)(object)val == (Object)null) { val = gameObject.GetComponentInChildren<CraftingStation>(true); } if ((Object)(object)val == (Object)null) { return; } ZNetView val2 = gameObject.GetComponent<ZNetView>(); if ((Object)(object)val2 == (Object)null) { val2 = gameObject.GetComponentInParent<ZNetView>(); } if (!((Object)(object)val2 == (Object)null) && val2.IsValid()) { ZDO zDO = val2.GetZDO(); if (zDO != null) { Plugin.Registry.ForgetDestroyed(zDO.m_uid); } } } catch { } } } internal static class ZdoDestroyedPatch { [HarmonyPriority(800)] private static void Prefix(object[] __args) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (Plugin.Registry == null || __args == null) { return; } try { foreach (object obj in __args) { if (obj is ZDOID) { Plugin.Registry.ForgetDestroyed((ZDOID)obj); break; } ZDO val = (ZDO)((obj is ZDO) ? obj : null); if (val != null) { Plugin.Registry.ForgetDestroyed(val.m_uid); break; } } } catch { } } } public static class PlayerInventoryApi { private static MethodInfo _changed; public static int Count(Player player, string prefabName) { if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(prefabName)) { return 0; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return 0; } int num = 0; List<ItemData> allItems = inventory.GetAllItems(); for (int i = 0; i < allItems.Count; i++) { if (StorageApi.MatchesResource(allItems[i], prefabName)) { num += allItems[i].m_stack; } } return num; } public static bool Remove(Player player, string prefabName, int amount) { if (amount <= 0) { return true; } if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(prefabName)) { return false; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null || Count(player, prefabName) < amount) { return false; } int num = amount; List<ItemData> allItems = inventory.GetAllItems(); int num2 = allItems.Count - 1; while (num2 >= 0 && num > 0) { ItemData val = allItems[num2]; if (StorageApi.MatchesResource(val, prefabName)) { int num3 = Math.Min(val.m_stack, num); val.m_stack -= num3; num -= num3; if (val.m_stack <= 0) { allItems.RemoveAt(num2); } } num2--; } if (num != 0) { return false; } try { _changed = _changed ?? typeof(Inventory).GetMethod("Changed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (_changed != null) { _changed.Invoke(inventory, null); } } catch { } return true; } } [BepInPlugin("marcojudith.networkcore", "MJ Network Core", "0.1.18")] [BepInDependency("com.maxsch.valheim.MultiUserChest", "0.6.2")] public sealed class Plugin : BaseUnityPlugin { private sealed class PendingTopologyRefresh { internal ZNetView View; internal float At; internal int Passes; } public const string PluginGuid = "marcojudith.networkcore"; public const string PluginName = "MJ Network Core"; public const string PluginVersion = "0.1.18"; private ZDOMan _lastZdoMan; private readonly List<PendingTopologyRefresh> _pendingTopology = new List<PendingTopologyRefresh>(); internal static Plugin Instance { get; private set; } internal static Harmony Harmony { get; private set; } internal static CoreConfig Settings { get; private set; } internal static NetworkRegistry Registry { get; private set; } private void Awake() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown Instance = this; Settings = new CoreConfig(((BaseUnityPlugin)this).Config); Registry = new NetworkRegistry(); NetworkApi.Initialize(Registry, Settings); Harmony = new Harmony("marcojudith.networkcore"); PatchBootstrap.Install(Harmony); CoreRpc.EnsureRegistere