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 Wardrobe Portal v1.0.0
plugins/WardrobePortal.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using HeaveHo.Shared; using Microsoft.CodeAnalysis; using Nick.Shared; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI.")] [assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")] [assembly: AssemblyMetadata("ClaudeTools.Reload", "menu")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [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 HeaveHo.Shared { internal sealed class ServerSettings : IDisposable { public enum ServerMod { NotConnected, Checking, Installed, Missing } private sealed class ConfigurationManagerAttributes { public bool? ReadOnly; } private sealed class SyncedText { public string Key; public Func<string> Own; public Action<string> Use; public string Given; public bool FromServer; public bool Pending; public byte[] Packed; public bool TooBig; public MemoryStream Incoming; public int NextPart; } private sealed class Sending { public ZRpc Rpc; public string Key; public byte[] Data; public int Next; public int Parts; } private const int Protocol = 2; private const float ChangeSendGap = 0.5f; private const float AnswerWait = 20f; private const float FileWait = 1f; private const int PartSize = 65536; private const int CompressFrom = 1024; private const int WarnBytes = 262144; private const int MaxBytes = 8388608; private const int PaceBelow = 10240; private readonly string _send; private readonly string _ask; private readonly string _dAsk; private readonly string _dHello; private readonly string _dSend; private readonly string _edit; private readonly string _dTextAsk; private readonly string _dText; private readonly string _dAgain; private readonly ConfigFile _config; private readonly ManualLogSource _log; private readonly string _name; private readonly List<ConfigEntryBase> _entries = new List<ConfigEntryBase>(); private readonly Dictionary<ConfigEntryBase, object> _own = new Dictionary<ConfigEntryBase, object>(); private readonly Dictionary<ConfigEntryBase, object> _server = new Dictionary<ConfigEntryBase, object>(); private readonly List<GameObject> _guardedPieces = new List<GameObject>(); private readonly List<Recipe> _guardedRecipes = new List<Recipe>(); private ZRoutedRpc _registeredOn; private bool _applying; private bool _reloading; private bool _changePending; private float _nextChangeSend; private float _askedAt = -1f; private int _serverProtocol; private bool _directSeen; private readonly HashSet<ZRpc> _directPeers = new HashSet<ZRpc>(); private readonly List<SyncedText> _texts = new List<SyncedText>(); private readonly Dictionary<ZRpc, HashSet<string>> _textPeers = new Dictionary<ZRpc, HashSet<string>>(); private bool _textPending; private float _nextTextSend; private bool _readOnlyShown; private float _nextAdminCheck; private FileSystemWatcher _watcher; private volatile bool _fileTouched; private float _reloadAt = -1f; private string _fileText; private readonly List<Sending> _outbox = new List<Sending>(); private static readonly MethodInfo UpdateAvailablePieces = AccessTools.Method(typeof(Player), "UpdateAvailablePiecesList", (Type[])null, (Type[])null); private static readonly List<ServerSettings> Live = new List<ServerSettings>(); private static Harmony _saveHarmony; public string Version { get; } public bool FromServer => _server.Count > 0; public ServerMod Server { get; private set; } public string ServerVersion { get; private set; } public bool CanEditServer { get { if (!IsServer) { if (Server == ServerMod.Installed && _serverProtocol >= 1 && (Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.LocalPlayerIsAdminOrHost(); } return false; } return true; } } private static bool IsServer { get { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } } public event Action ServerChanged; public ServerSettings(string guid, ConfigFile config, ManualLogSource log) { _send = guid + ".settings"; _ask = guid + ".settings.ask"; _dAsk = guid + ".settings.d.ask"; _dHello = guid + ".settings.d.hello"; _dSend = guid + ".settings.d.values"; _edit = guid + ".settings.d.edit"; _dTextAsk = guid + ".settings.d.textask"; _dAgain = guid + ".settings.d.again"; _dText = guid + ".settings.d.text"; _config = config; _log = log; BepInPlugin val = PluginOf(guid); _name = ((val != null) ? val.Name : null) ?? guid; Version = ((val == null) ? null : val.Version?.ToString()) ?? ""; Live.Add(this); if (Live.Count == 1) { PatchSave(); } WatchFile(); } public ConfigEntry<T> Add<T>(ConfigEntry<T> entry) { if (entry == null || _entries.Contains((ConfigEntryBase)(object)entry)) { return entry; } _entries.Add((ConfigEntryBase)(object)entry); entry.SettingChanged += OnChanged; GiveManagerAttributes((ConfigEntryBase)(object)entry); return entry; } private static void GiveManagerAttributes(ConfigEntryBase entry) { ConfigDescription description = entry.Description; if (description == null || description == ConfigDescription.Empty || (description.Tags ?? new object[0]).Any(IsManagerAttributes)) { return; } try { object[] value = new object[1] { new ConfigurationManagerAttributes() }.Concat(description.Tags ?? new object[0]).ToArray(); AccessTools.Field(typeof(ConfigDescription), "<Tags>k__BackingField")?.SetValue(description, value); } catch (Exception) { } } public ConfigEntry<T> Bind<T>(string section, string key, T value, string description, AcceptableValueBase range = null, params object[] tags) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown if (!description.Contains("[Synced with Server]")) { description += " [Synced with Server]"; } return Add<T>(_config.Bind<T>(section, key, value, new ConfigDescription(description, range, tags ?? new object[0]))); } public void NeedsServer(GameObject piecePrefab) { if (!((Object)(object)piecePrefab == (Object)null)) { _guardedPieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null || ((Object)p).name == ((Object)piecePrefab).name); _guardedPieces.Add(piecePrefab); Guard(); } } public void NeedsServer(Recipe recipe) { if (!((Object)(object)recipe == (Object)null)) { _guardedRecipes.RemoveAll((Recipe r) => (Object)(object)r == (Object)null || (Object)(object)r == (Object)(object)recipe || (!string.IsNullOrEmpty(((Object)recipe).name) && ((Object)r).name == ((Object)recipe).name)); _guardedRecipes.Add(recipe); Guard(); } } public void AddText(string key, Func<string> own, Action<string> use) { if (string.IsNullOrEmpty(key) || own == null || use == null) { ManualLogSource log = _log; if (log != null) { log.LogError((object)"AddText needs a key, own and use"); } return; } _texts.RemoveAll((SyncedText x) => x.Key == key); SyncedText syncedText = new SyncedText { Key = key, Own = own, Use = use }; _texts.Add(syncedText); Give(syncedText, OwnText(syncedText)); ZRpc val = ((!((Object)(object)ZNet.instance != (Object)null) || IsServer) ? null : ZNet.instance.GetServerPeer()?.m_rpc); if (_registeredOn != null && val != null) { val.Register<ZPackage>(_dText, (Action<ZRpc, ZPackage>)OnText); AskTexts(val); } } public void TextChanged(string key) { SyncedText syncedText = _texts.FirstOrDefault((SyncedText x) => x.Key == key); if (syncedText != null) { syncedText.Packed = null; if (!syncedText.FromServer) { Give(syncedText, OwnText(syncedText)); } if (IsServer) { syncedText.Pending = true; _textPending = true; } } } public bool TextFromServer(string key) { return _texts.Any((SyncedText x) => x.Key == key && x.FromServer); } public void Update() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != _registeredOn) { Unregister(); Restore(); RestoreTexts(give: true); _changePending = false; _textPending = false; SetServer(ServerMod.NotConnected, null, 0); if (instance != null) { Register(instance); } } float unscaledTime = Time.unscaledTime; if (_changePending && unscaledTime >= _nextChangeSend) { SendChange(); } if (_textPending && unscaledTime >= _nextTextSend) { SendTexts(); } if (_outbox.Count > 0) { Pump(); } if (Server == ServerMod.Checking && _askedAt >= 0f && unscaledTime - _askedAt > 20f) { if (_guardedPieces.Count + _guardedRecipes.Count > 0) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("The server didn't answer: " + _name + " isn't installed there (or its copy is older than 2026-10-11), so its pieces and items can't be made on this server.")); } } else { ManualLogSource log2 = _log; if (log2 != null) { log2.LogInfo((object)("The server didn't answer: " + _name + " isn't installed there, or its copy is older" + (FromServer ? " (its settings apply)." : " (your own settings apply)."))); } } SetServer(ServerMod.Missing, null, 0); } if (_fileTouched) { _fileTouched = false; _reloadAt = unscaledTime + 1f; } if (_reloadAt >= 0f && unscaledTime >= _reloadAt) { _reloadAt = -1f; ReloadFile(); } if (FromServer && unscaledTime >= _nextAdminCheck) { _nextAdminCheck = unscaledTime + 1f; ShowReadOnly(); } } public void Dispose() { Unregister(); Restore(); RestoreTexts(give: false); SetServer(ServerMod.NotConnected, null, 0); foreach (ConfigEntryBase entry in _entries) { Unsubscribe(entry); } _entries.Clear(); _texts.Clear(); try { _watcher?.Dispose(); } catch (Exception) { } _watcher = null; Live.Remove(this); if (Live.Count == 0) { UnpatchSave(); } } private void Register(ZRoutedRpc rpc) { Forget(rpc, _send); Forget(rpc, _ask); rpc.Register<ZPackage>(_send, (Action<long, ZPackage>)OnRoutedValues); rpc.Register(_ask, (Action<long>)OnRoutedAsk); rpc.m_onNewPeer = (Action<long>)Delegate.Combine(rpc.m_onNewPeer, new Action<long>(OnNewPeer)); _registeredOn = rpc; if (IsServer) { foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { ListenTo(peer); if (peer != null) { ZRpc rpc2 = peer.m_rpc; if (rpc2 != null) { rpc2.Invoke(_dAgain, Array.Empty<object>()); } } } return; } if ((Object)(object)ZNet.instance != (Object)null) { SetServer(ServerMod.Checking, null, 0); if (ZNet.instance.GetServerPeer() != null) { AskServer(); } } } private void Unregister() { if (_registeredOn == null) { return; } ZRoutedRpc registeredOn = _registeredOn; registeredOn.m_onNewPeer = (Action<long>)Delegate.Remove(registeredOn.m_onNewPeer, new Action<long>(OnNewPeer)); Forget(_registeredOn, _send); Forget(_registeredOn, _ask); if ((Object)(object)ZNet.instance != (Object)null) { foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer?.m_rpc != null) { string[] array = new string[7] { _dAsk, _dHello, _dSend, _edit, _dTextAsk, _dText, _dAgain }; foreach (string name in array) { ForgetDirect(peer.m_rpc, name); } } } } _directPeers.Clear(); _textPeers.Clear(); _outbox.Clear(); _directSeen = false; _registeredOn = null; } private static void Forget(ZRoutedRpc rpc, string name) { if (AccessTools.Field(typeof(ZRoutedRpc), "m_functions")?.GetValue(rpc) is IDictionary dictionary) { dictionary.Remove(StringExtensionMethods.GetStableHashCode(name)); } } private static void ForgetDirect(ZRpc rpc, string name) { if (AccessTools.Field(typeof(ZRpc), "m_functions")?.GetValue(rpc) is IDictionary dictionary) { dictionary.Remove(StringExtensionMethods.GetStableHashCode(name)); } } private void OnNewPeer(long uid) { if (IsServer) { ZNetPeer peer = ZNet.instance.GetPeer(uid); ListenTo(peer); if (peer?.m_rpc != null) { SendDirect(peer.m_rpc); } SendRouted(uid); } else if ((Object)(object)ZNet.instance != (Object)null) { ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null && serverPeer.m_uid == uid) { AskServer(); } } } private void ListenTo(ZNetPeer peer) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (peer?.m_rpc != null) { peer.m_rpc.Register(_dAsk, new Method(OnDirectAsk)); peer.m_rpc.Register<ZPackage>(_edit, (Action<ZRpc, ZPackage>)OnEdit); peer.m_rpc.Register<ZPackage>(_dTextAsk, (Action<ZRpc, ZPackage>)OnTextAsk); } } private void OnDirectAsk(ZRpc rpc) { if (IsServer) { _directPeers.Add(rpc); SendDirect(rpc); } } private void OnRoutedAsk(long sender) { if (IsServer) { SendRouted(sender); } } private void SendDirect(ZRpc rpc) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(2); val.Write(Version); rpc.Invoke(_dHello, new object[1] { val }); if (_entries.Count > 0) { rpc.Invoke(_dSend, new object[1] { Values() }); } } private void SendRouted(long target) { if (ZRoutedRpc.instance != null && _entries.Count > 0) { ZRoutedRpc.instance.InvokeRoutedRPC(target, _send, new object[1] { Values() }); } } private ZPackage Values() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(_entries.Count); foreach (ConfigEntryBase entry in _entries) { val.Write(entry.Definition.Section); val.Write(entry.Definition.Key); val.Write(TomlTypeConverter.ConvertToString(entry.BoxedValue, entry.SettingType)); } return val; } private void AskServer() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null); if (val?.m_rpc == null) { return; } _askedAt = Time.unscaledTime; val.m_rpc.Register<ZPackage>(_dHello, (Action<ZRpc, ZPackage>)OnDirectHello); val.m_rpc.Register<ZPackage>(_dSend, (Action<ZRpc, ZPackage>)OnDirectValues); val.m_rpc.Register<ZPackage>(_dText, (Action<ZRpc, ZPackage>)OnText); val.m_rpc.Register(_dAgain, new Method(OnAskAgain)); val.m_rpc.Invoke(_dAsk, Array.Empty<object>()); AskTexts(val.m_rpc); try { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(val.m_uid, _ask, Array.Empty<object>()); } } catch (Exception) { } } private static bool IsServerConnection(ZRpc rpc) { if (!IsServer) { ZNet instance = ZNet.instance; return ((instance == null) ? null : instance.GetServerPeer()?.m_rpc) == rpc; } return false; } private void OnAskAgain(ZRpc rpc) { if (IsServerConnection(rpc)) { rpc.Invoke(_dAsk, Array.Empty<object>()); AskTexts(rpc); } } private void OnDirectHello(ZRpc rpc, ZPackage pkg) { if (!IsServerConnection(rpc)) { return; } try { int protocol = pkg.ReadInt(); string text = pkg.ReadString(); if (text != Version && text != ServerVersion) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("The server has " + _name + " " + text + ", you have " + Version + ": some things may not match. Use the same version as the server.")); } } _directSeen = true; SetServer(ServerMod.Installed, text, protocol); } catch (Exception ex) { ManualLogSource log2 = _log; if (log2 != null) { log2.LogWarning((object)("Could not read the server's hello: " + ex.Message)); } } } private void OnDirectValues(ZRpc rpc, ZPackage pkg) { if (IsServerConnection(rpc)) { TakeValues(pkg); } } private void OnRoutedValues(long sender, ZPackage pkg) { if (!_directSeen && !IsServer) { ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null); if (val != null && val.m_uid == sender) { TakeValues(pkg); } } } private void TakeValues(ZPackage pkg) { try { int num = pkg.ReadInt(); List<string> list = new List<string>(); for (int i = 0; i < num; i++) { string section = pkg.ReadString(); string key = pkg.ReadString(); string text = pkg.ReadString(); ConfigEntryBase val = ((IEnumerable<ConfigEntryBase>)_entries).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase x) => x.Definition.Section == section && x.Definition.Key == key)); if (val != null) { object obj; try { obj = TomlTypeConverter.ConvertToValue(text, val.SettingType); } catch (Exception) { continue; } if (!_own.ContainsKey(val)) { _own[val] = val.BoxedValue; } _server[val] = obj; if (!object.Equals(val.BoxedValue, obj)) { Apply(val, obj); list.Add(section + "/" + key + " = " + text); } } } ManualLogSource log = _log; if (log != null) { log.LogInfo((object)($"Settings from the server apply while you play here ({_server.Count})" + ((list.Count > 0) ? (": " + string.Join(", ", list.ToArray())) : ""))); } ShowReadOnly(); } catch (Exception ex2) { ManualLogSource log2 = _log; if (log2 != null) { log2.LogWarning((object)("Could not read the server's settings: " + ex2.Message)); } } } private void Apply(ConfigEntryBase e, object value) { bool saveOnConfigSet = _config.SaveOnConfigSet; _applying = true; try { _config.SaveOnConfigSet = false; e.BoxedValue = value; } finally { _config.SaveOnConfigSet = saveOnConfigSet; _applying = false; } } private void Restore() { if (_server.Count == 0) { return; } foreach (KeyValuePair<ConfigEntryBase, object> item in _own) { Apply(item.Key, item.Value); } _own.Clear(); _server.Clear(); ShowReadOnly(); ManualLogSource log = _log; if (log != null) { log.LogInfo((object)"Your own settings apply again"); } } private void OnChanged(object sender, EventArgs args) { if (_applying) { return; } ConfigEntryBase val = (ConfigEntryBase)((sender is ConfigEntryBase) ? sender : null); if (val == null) { return; } if (_server.TryGetValue(val, out var value)) { if (!_reloading && CanEditServer) { SendEdit(val); } else { _own[val] = val.BoxedValue; } Apply(val, value); } else if (IsServer) { _changePending = true; if (Time.unscaledTime >= _nextChangeSend) { SendChange(); } } } private void SendChange() { _changePending = false; _nextChangeSend = Time.unscaledTime + 0.5f; if (!IsServer) { return; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer?.m_rpc == null) { continue; } if (_directPeers.Contains(peer.m_rpc)) { if (_entries.Count > 0) { peer.m_rpc.Invoke(_dSend, new object[1] { Values() }); } } else { SendRouted(peer.m_uid); } } } private void SendEdit(ConfigEntryBase e) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown ZNet instance = ZNet.instance; ZNetPeer val = ((instance != null) ? instance.GetServerPeer() : null); if (val?.m_rpc != null) { ZPackage val2 = new ZPackage(); val2.Write(e.Definition.Section); val2.Write(e.Definition.Key); val2.Write(TomlTypeConverter.ConvertToString(e.BoxedValue, e.SettingType)); val.m_rpc.Invoke(_edit, new object[1] { val2 }); ManualLogSource log = _log; if (log != null) { log.LogInfo((object)("Asked the server to set " + e.Definition.Section + "/" + e.Definition.Key)); } } } private void OnEdit(ZRpc rpc, ZPackage pkg) { try { if (!IsServer) { return; } ISocket socket = rpc.GetSocket(); string text = ((socket != null) ? socket.GetHostName() : null) ?? ""; ZNetPeer val = ((IEnumerable<ZNetPeer>)ZNet.instance.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => p.m_rpc == rpc)); string section = pkg.ReadString(); string key = pkg.ReadString(); string text2 = pkg.ReadString(); if (!ZNet.instance.IsAdmin(text)) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)((val?.m_playerName ?? text) + " tried to change " + section + "/" + key + " but isn't on the admin list")); } if (_entries.Count > 0) { rpc.Invoke(_dSend, new object[1] { Values() }); } return; } ConfigEntryBase val2 = ((IEnumerable<ConfigEntryBase>)_entries).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase x) => x.Definition.Section == section && x.Definition.Key == key)); if (val2 != null) { val2.BoxedValue = TomlTypeConverter.ConvertToValue(text2, val2.SettingType); ManualLogSource log2 = _log; if (log2 != null) { log2.LogInfo((object)("Admin " + (val?.m_playerName ?? text) + " set " + section + "/" + key + " = " + text2)); } } } catch (Exception ex) { ManualLogSource log3 = _log; if (log3 != null) { log3.LogWarning((object)("Could not take an admin's change: " + ex.Message)); } } } private void ShowReadOnly() { bool flag = FromServer && !CanEditServer; if (flag == _readOnlyShown) { return; } _readOnlyShown = flag; foreach (ConfigEntryBase entry in _entries) { ConfigDescription description = entry.Description; object[] array = ((description != null) ? description.Tags : null) ?? new object[0]; foreach (object obj in array) { if (IsManagerAttributes(obj)) { try { AccessTools.Field(obj.GetType(), "ReadOnly")?.SetValue(obj, flag ? ((object)true) : null); } catch (Exception) { } } } } } private static bool IsManagerAttributes(object tag) { if (tag != null) { return tag.GetType().Name == "ConfigurationManagerAttributes"; } return false; } private string OwnText(SyncedText t) { try { return t.Own() ?? ""; } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Could not read " + t.Key + ": " + ex.Message)); } return t.Given ?? ""; } } private void Give(SyncedText t, string text) { if (t.Given != null && t.Given == text) { return; } t.Given = text; try { t.Use(text); } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Could not use " + t.Key + ": " + ex)); } } } private void RestoreTexts(bool give) { foreach (SyncedText text in _texts) { text.Incoming = null; if (!text.FromServer) { continue; } text.FromServer = false; if (give) { Give(text, OwnText(text)); ManualLogSource log = _log; if (log != null) { log.LogInfo((object)("Your own " + text.Key + " applies again")); } } } } private void AskTexts(ZRpc server) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown if (_texts.Count == 0 || server == null) { return; } ZPackage val = new ZPackage(); val.Write(_texts.Count); foreach (SyncedText text in _texts) { val.Write(text.Key); } server.Invoke(_dTextAsk, new object[1] { val }); } private void OnTextAsk(ZRpc rpc, ZPackage pkg) { try { if (!IsServer) { return; } int num = pkg.ReadInt(); HashSet<string> hashSet = new HashSet<string>(); for (int i = 0; i < num && i < 1000; i++) { string key = pkg.ReadString(); if (_texts.Any((SyncedText x) => x.Key == key)) { hashSet.Add(key); } } if (_textPeers.TryGetValue(rpc, out var value)) { hashSet.UnionWith(value); } foreach (ZRpc item in _textPeers.Keys.Where((ZRpc r) => !r.IsConnected()).ToList()) { _textPeers.Remove(item); } _textPeers[rpc] = hashSet; foreach (SyncedText text in _texts) { if (hashSet.Contains(text.Key)) { SendText(rpc, text); } } } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Could not answer a player's ask for server data: " + ex.Message)); } } } private void SendTexts() { _textPending = false; _nextTextSend = Time.unscaledTime + 0.5f; if (!IsServer) { return; } foreach (SyncedText text in _texts) { if (!text.Pending) { continue; } text.Pending = false; foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer?.m_rpc != null && _textPeers.TryGetValue(peer.m_rpc, out var value) && value.Contains(text.Key)) { SendText(peer.m_rpc, text); } } } } private void SendText(ZRpc rpc, SyncedText t) { byte[] array = Packed(t); if (array != null) { _outbox.RemoveAll((Sending s) => s.Rpc == rpc && s.Key == t.Key); _outbox.Add(new Sending { Rpc = rpc, Key = t.Key, Data = array, Parts = Math.Max(1, (array.Length + 65536 - 1) / 65536) }); Pump(); } } private void Pump() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown for (int num = _outbox.Count - 1; num >= 0; num--) { Sending sending = _outbox[num]; try { while (sending.Next < sending.Parts && sending.Rpc.IsConnected() && sending.Rpc.GetSocket().GetSendQueueSize() < 10240) { int num2 = sending.Next * 65536; int num3 = Math.Min(65536, sending.Data.Length - num2); byte[] array = new byte[num3]; Buffer.BlockCopy(sending.Data, num2, array, 0, num3); ZPackage val = new ZPackage(); val.Write(sending.Key); val.Write(sending.Next); val.Write(sending.Parts); val.Write(array); sending.Rpc.Invoke(_dText, new object[1] { val }); sending.Next++; } if (sending.Next >= sending.Parts || !sending.Rpc.IsConnected()) { _outbox.RemoveAt(num); } } catch (Exception ex) { _outbox.RemoveAt(num); ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Could not send " + sending.Key + " to a player: " + ex.Message)); } } } } private byte[] Packed(SyncedText t) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if (t.Packed == null) { string text = OwnText(t); ZPackage val = new ZPackage(); val.Write(text); ZPackage val2 = new ZPackage(); bool flag = text.Length > 1024; val2.Write(flag); if (flag) { val2.WriteCompressed(val); } else { val2.Write(val); } t.Packed = val2.GetArray(); t.TooBig = t.Packed.Length > 8388608; string arg = $"{t.Packed.Length / 1024} KB" + (flag ? $" gzipped ({text.Length / 1024} KB of text)" : ""); if (t.TooBig) { ManualLogSource log = _log; if (log != null) { log.LogError((object)$"{t.Key} is too big to send to players ({arg}, at most {8} MB): they keep their own."); } } else if (t.Packed.Length > 262144) { ManualLogSource log2 = _log; if (log2 != null) { log2.LogWarning((object)$"{t.Key} is big to send to every player who joins ({arg}): it takes about {(float)t.Packed.Length / 153600f:0} s of their connection, and their world loads slower meanwhile."); } } } if (!t.TooBig) { return t.Packed; } return null; } private void OnText(ZRpc rpc, ZPackage pkg) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown if (!IsServerConnection(rpc)) { return; } SyncedText syncedText = null; try { string key = pkg.ReadString(); int num = pkg.ReadInt(); int num2 = pkg.ReadInt(); byte[] array = pkg.ReadByteArray(); syncedText = _texts.FirstOrDefault((SyncedText x) => x.Key == key); if (syncedText == null) { return; } if (num2 < 1 || num2 > 129 || num < 0 || num >= num2) { throw new InvalidDataException($"part {num} of {num2}"); } if (num == 0) { syncedText.Incoming = new MemoryStream(); syncedText.NextPart = 0; } if (syncedText.Incoming == null || num != syncedText.NextPart) { throw new InvalidDataException($"part {num} came out of order"); } syncedText.Incoming.Write(array, 0, array.Length); syncedText.NextPart = num + 1; if (num >= num2 - 1) { ZPackage val = new ZPackage(syncedText.Incoming.ToArray()); syncedText.Incoming = null; ZPackage val2 = (val.ReadBool() ? val.ReadCompressedPackage() : val.ReadPackage()); string text = val2.ReadString(); syncedText.FromServer = true; Give(syncedText, text); ManualLogSource log = _log; if (log != null) { log.LogInfo((object)$"The server's {key} applies while you play here ({text.Length / 1024} KB)"); } } } catch (Exception ex) { if (syncedText != null) { syncedText.Incoming = null; } ManualLogSource log2 = _log; if (log2 != null) { log2.LogWarning((object)("Could not read the server's data" + ((syncedText != null) ? (" for " + syncedText.Key) : "") + ": " + ex.Message)); } } } private void SetServer(ServerMod state, string version, int protocol) { if (state != ServerMod.Checking) { _askedAt = -1f; } bool flag = state != Server || version != ServerVersion; Server = state; ServerVersion = version; _serverProtocol = protocol; if (!flag) { return; } Guard(); try { this.ServerChanged?.Invoke(); } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("ServerChanged: " + ex)); } } } private void Guard() { bool flag = Server == ServerMod.NotConnected || Server == ServerMod.Installed; bool flag2 = false; foreach (GameObject guardedPiece in _guardedPieces) { Piece val = (((Object)(object)guardedPiece != (Object)null) ? guardedPiece.GetComponent<Piece>() : null); if ((Object)(object)val != (Object)null && val.m_enabled != flag) { val.m_enabled = flag; flag2 = true; } } foreach (Recipe guardedRecipe in _guardedRecipes) { if ((Object)(object)guardedRecipe != (Object)null && guardedRecipe.m_enabled != flag) { guardedRecipe.m_enabled = flag; flag2 = true; } } if (flag2 && (Object)(object)Player.m_localPlayer != (Object)null) { try { UpdateAvailablePieces?.Invoke(Player.m_localPlayer, null); } catch (Exception) { } } } private void WatchFile() { try { string configFilePath = _config.ConfigFilePath; _watcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath)) { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite) }; FileSystemEventHandler value = delegate { _fileTouched = true; }; _watcher.Changed += value; _watcher.Created += value; _watcher.Renamed += delegate { _fileTouched = true; }; _watcher.EnableRaisingEvents = true; } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Edits to the config file apply after a restart (can't watch it: " + ex.Message + ")")); } } } private void ReloadFile() { string text = ReadFile(_config.ConfigFilePath); if (text == null) { if (File.Exists(_config.ConfigFilePath)) { _reloadAt = Time.unscaledTime + 1f; } } else { if (text == _fileText) { return; } _fileText = text; bool saveOnConfigSet = _config.SaveOnConfigSet; _reloading = true; try { _config.SaveOnConfigSet = false; _config.Reload(); } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Could not read the edited config file (check the line you changed): " + ex.Message)); } } finally { _config.SaveOnConfigSet = saveOnConfigSet; _reloading = false; } } } private void PatchSave() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_0067: Expected O, but got Unknown try { _saveHarmony = new Harmony(_send + ".save"); _saveHarmony.Patch((MethodBase)AccessTools.Method(typeof(ConfigFile), "Save", (Type[])null, (Type[])null), new HarmonyMethod(typeof(ServerSettings), "BeforeSave", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ServerSettings), "AfterSave", (Type[])null), (HarmonyMethod)null); } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Could not keep the server's values out of your config file: " + ex.Message)); } } } private static void UnpatchSave() { try { Harmony saveHarmony = _saveHarmony; if (saveHarmony != null) { saveHarmony.UnpatchSelf(); } } catch (Exception) { } _saveHarmony = null; } private static void BeforeSave(ConfigFile __instance) { foreach (ServerSettings item in Live) { if (item._config != __instance) { continue; } foreach (KeyValuePair<ConfigEntryBase, object> item2 in item._own) { SetQuietly(item2.Key, item2.Value); } } } private static Exception AfterSave(ConfigFile __instance, Exception __exception) { foreach (ServerSettings item in Live) { if (item._config != __instance) { continue; } foreach (KeyValuePair<ConfigEntryBase, object> item2 in item._server) { SetQuietly(item2.Key, item2.Value); } item._fileText = ReadFile(__instance.ConfigFilePath); } return __exception; } private static string ReadFile(string path) { try { return File.Exists(path) ? File.ReadAllText(path) : null; } catch (Exception) { return null; } } private static void SetQuietly(ConfigEntryBase e, object value) { AccessTools.Field(((object)e).GetType(), "_typedValue")?.SetValue(e, value); } private static BepInPlugin PluginOf(string guid) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown Type[] array; try { array = typeof(ServerSettings).Assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type t) => t != null).ToArray(); } Type[] array2 = array; foreach (Type type in array2) { object[] customAttributes = type.GetCustomAttributes(typeof(BepInPlugin), inherit: false); for (int num2 = 0; num2 < customAttributes.Length; num2++) { BepInPlugin val = (BepInPlugin)customAttributes[num2]; if (val.GUID == guid || guid.StartsWith(val.GUID + ".")) { return val; } } } return null; } private void Unsubscribe(ConfigEntryBase e) { ((object)e).GetType().GetEvent("SettingChanged")?.RemoveEventHandler(e, new EventHandler(OnChanged)); } } } namespace WardrobePortal { internal static class Cabinet { public const string DoorPrefix = "door_hinge"; private const float HingeX = 0.635f; private const float HingeZ = 0.45f; private static readonly Bounds RightDoor = Box(-0.645f, 0.01f, 0.1f, 2.58f, 0.34f, 0.6f); private static readonly Bounds Shelves = Box(-0.72f, 0.72f, 0.3f, 2.4f, -0.5f, 0.4f); private static Mesh _cut; private static bool _tried; private const float InnerSide = 0.64f; private const float InnerBack = -0.34f; private static Bounds Box(float x0, float x1, float y0, float y1, float z0, float z1) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Bounds result = default(Bounds); ((Bounds)(ref result)).SetMinMax(new Vector3(x0, y0, z0), new Vector3(x1, y1, z1)); return result; } public static MeshRenderer Build(Transform parent, GameObject wardrobe) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown Transform val = wardrobe.transform.Find("New"); object obj; if (val == null) { obj = null; } else { Transform obj2 = val.Find("blackmetalchest"); obj = ((obj2 != null) ? ((Component)obj2).GetComponent<MeshFilter>() : null); } MeshFilter val2 = (MeshFilter)obj; object obj3; if (val == null) { obj3 = null; } else { Transform obj4 = val.Find("Closed/blackmetalchesttop_closed"); obj3 = ((obj4 != null) ? ((Component)obj4).GetComponent<MeshFilter>() : null); } MeshFilter val3 = (MeshFilter)obj3; if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null) { throw new Exception("the wardrobe's model has changed (no blackmetalchest or its door)"); } Mesh val4 = CutBody(val2.sharedMesh); bool flag = (Object)(object)val4 != (Object)(object)val2.sharedMesh; GameObject val5 = new GameObject("cabinet"); val5.transform.SetParent(parent, false); val5.AddComponent<MeshFilter>().sharedMesh = val4; MeshRenderer val6 = val5.AddComponent<MeshRenderer>(); ((Renderer)val6).sharedMaterials = ((Renderer)((Component)val2).GetComponent<MeshRenderer>()).sharedMaterials; Material[] sharedMaterials = ((Renderer)((Component)val3).GetComponent<MeshRenderer>()).sharedMaterials; AddDoor(parent, val3.sharedMesh, sharedMaterials, 1f); if (flag) { AddDoor(parent, val3.sharedMesh, sharedMaterials, -1f); } return val6; } private static void AddDoor(Transform parent, Mesh mesh, Material[] mats, float side) { //IL_001e: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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) Transform transform = new GameObject("door_hinge_" + ((side > 0f) ? "left" : "right")).transform; transform.SetParent(parent, false); transform.localPosition = new Vector3(side * 0.635f, 0f, 0.45f); GameObject val = new GameObject("door"); val.transform.SetParent(transform, false); val.transform.localScale = new Vector3(side, 1f, 1f); val.transform.localPosition = new Vector3((0f - side) * 0.635f, 0f, -0.45f); val.AddComponent<MeshFilter>().sharedMesh = mesh; ((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterials = mats; ((Component)transform).gameObject.layer = LayerMask.NameToLayer("piece"); BoxCollider val2 = ((Component)transform).gameObject.AddComponent<BoxCollider>(); val2.center = new Vector3((0f - side) * 0.315f, 1.34f, 0f); val2.size = new Vector3(0.62f, 2.4f, 0.08f); } private static Mesh CutBody(Mesh src) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 if ((Object)(object)_cut != (Object)null) { return _cut; } if (_tried || (int)SystemInfo.graphicsDeviceType == 4) { return src; } _tried = true; try { _cut = Cut(src, Remove, out var kept, out var removed); Plugin.Log.LogInfo((object)$"Wardrobe cabinet: kept {kept} triangles, cut {removed} (the right door and the shelves)"); return _cut; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't read the wardrobe's mesh, so it keeps its one door: " + ex.Message)); return src; } } private static bool Remove(Vector3 a, Vector3 b, Vector3 c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_001a: 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_004b: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) Bounds val = RightDoor; if (((Bounds)(ref val)).Contains(a)) { val = RightDoor; if (((Bounds)(ref val)).Contains(b)) { val = RightDoor; if (((Bounds)(ref val)).Contains(c)) { return true; } } } val = Shelves; if (((Bounds)(ref val)).Contains(a)) { val = Shelves; if (((Bounds)(ref val)).Contains(b)) { val = Shelves; if (((Bounds)(ref val)).Contains(c)) { Vector3 val2 = Vector3.Cross(b - a, c - a); Vector3 normalized = ((Vector3)(ref val2)).normalized; float num = Mathf.Min(Mathf.Abs(a.x), Mathf.Min(Mathf.Abs(b.x), Mathf.Abs(c.x))); float num2 = Mathf.Max(a.z, Mathf.Max(b.z, c.z)); bool flag = Mathf.Abs(normalized.x) > 0.9f && num > 0.64f; bool flag2 = Mathf.Abs(normalized.z) > 0.9f && num2 < -0.34f; if (!flag) { return !flag2; } return false; } } } return false; } private static Mesh Cut(Mesh src, Func<Vector3, Vector3, Vector3, bool> remove, out int kept, out int removed) { //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_002e: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Invalid comparison between Unknown and I4 //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: 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) if (src.subMeshCount != 1) { throw new Exception($"{src.subMeshCount} submeshes"); } SubMeshDescriptor subMesh = src.GetSubMesh(0); if ((int)((SubMeshDescriptor)(ref subMesh)).topology != 0) { throw new Exception("not triangles"); } GraphicsBuffer indexBuffer = src.GetIndexBuffer(); if (indexBuffer == null) { throw new Exception("its triangle list isn't on the graphics card"); } byte[] ib = Read(indexBuffer); VertexAttributeDescriptor[] vertexAttributes = src.GetVertexAttributes(); int vertexCount = src.vertexCount; int vertexAttributeStream = src.GetVertexAttributeStream((VertexAttribute)0); int vertexAttributeOffset = src.GetVertexAttributeOffset((VertexAttribute)0); if ((int)src.GetVertexAttributeFormat((VertexAttribute)0) != 0) { throw new Exception("positions not 32-bit floats"); } Mesh val = new Mesh { name = ((Object)src).name + "_wardrobeportal" }; val.indexFormat = src.indexFormat; val.SetVertexBufferParams(vertexCount, vertexAttributes); Vector3[] array = (Vector3[])(object)new Vector3[vertexCount]; int vertexBufferCount = src.vertexBufferCount; for (int i = 0; i < vertexBufferCount; i++) { byte[] array2 = Read(src.GetVertexBuffer(i)); int vertexBufferStride = src.GetVertexBufferStride(i); if (array2.Length < vertexBufferStride * vertexCount) { throw new Exception($"vertex stream {i}: {array2.Length} bytes, wanted {vertexBufferStride * vertexCount}"); } val.SetVertexBufferData<byte>(array2, 0, 0, vertexBufferStride * vertexCount, i, (MeshUpdateFlags)1); if (i == vertexAttributeStream) { for (int j = 0; j < vertexCount; j++) { int num = j * vertexBufferStride + vertexAttributeOffset; array[j] = new Vector3(BitConverter.ToSingle(array2, num), BitConverter.ToSingle(array2, num + 4), BitConverter.ToSingle(array2, num + 8)); } } } bool wide = (int)src.indexFormat == 1; List<int> list = new List<int>(((SubMeshDescriptor)(ref subMesh)).indexCount); removed = 0; for (int k = ((SubMeshDescriptor)(ref subMesh)).indexStart; k + 2 < ((SubMeshDescriptor)(ref subMesh)).indexStart + ((SubMeshDescriptor)(ref subMesh)).indexCount; k += 3) { int num2 = Index(k) + ((SubMeshDescriptor)(ref subMesh)).baseVertex; int num3 = Index(k + 1) + ((SubMeshDescriptor)(ref subMesh)).baseVertex; int num4 = Index(k + 2) + ((SubMeshDescriptor)(ref subMesh)).baseVertex; if (remove(array[num2], array[num3], array[num4])) { removed++; continue; } list.Add(num2); list.Add(num3); list.Add(num4); } kept = list.Count / 3; val.SetIndexBufferParams(list.Count, val.indexFormat); if (wide) { val.SetIndexBufferData<uint>(list.ConvertAll((int t) => (uint)t), 0, 0, list.Count, (MeshUpdateFlags)0); } else { val.SetIndexBufferData<ushort>(list.ConvertAll((int t) => (ushort)t), 0, 0, list.Count, (MeshUpdateFlags)0); } val.SetSubMesh(0, new SubMeshDescriptor(0, list.Count, (MeshTopology)0), (MeshUpdateFlags)0); val.RecalculateBounds(); val.UploadMeshData(false); return val; int Index(int num5) { if (!wide) { return BitConverter.ToUInt16(ib, num5 * 2); } return (int)BitConverter.ToUInt32(ib, num5 * 4); } } private static byte[] Read(GraphicsBuffer buffer) { try { int num = buffer.count * buffer.stride; int[] array = new int[(num + 3) / 4]; buffer.GetData((Array)array); byte[] array2 = new byte[num]; Buffer.BlockCopy(array, 0, array2, 0, num); return array2; } finally { ((IDisposable)buffer)?.Dispose(); } } } internal static class Costs { public const string Help = "Item prefab names and amounts, separated by commas, like FineWood:12, BronzeNails:30 (Claude Tools' `prefabs <text>` shows exact names). A cost with a mistake in it keeps the last good one."; public const string StationHelp = "The crafting station's prefab name (piece_workbench, forge, piece_stonecutter, piece_artisanstation, blackforge, piece_magetable), or none."; public static Requirement[] Parse(string text, List<string> problems, bool forRecipe) { //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Expected O, but got Unknown problems = problems ?? new List<string>(); int count = problems.Count; List<Requirement> list = new List<Requirement>(); string[] array = (text ?? "").Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text2 in array) { string text3 = text2.Trim(); if (text3.Length == 0) { continue; } string[] array2 = (from b in text3.Split(new char[1] { ':' }) select b.Trim()).ToArray(); if (array2.Length < 2 || array2.Length > 3 || !Whole(array2[1], out var value) || value < 1) { problems.Add("\"" + text3 + "\" isn't Name:amount"); continue; } int value2 = 0; bool result = true; if (array2.Length == 3) { bool num; if (!forRecipe) { num = bool.TryParse(array2[2], out result); } else { if (!Whole(array2[2], out value2)) { goto IL_0116; } num = value2 >= 0; } if (!num) { goto IL_0116; } } ItemDrop item = FindItem(array2[0]); if ((Object)(object)item == (Object)null) { problems.Add("no item called \"" + array2[0] + "\""); continue; } if (list.Any((Requirement r) => (Object)(object)r.m_resItem == (Object)(object)item)) { problems.Add(array2[0] + " is listed twice"); continue; } list.Add(new Requirement { m_resItem = item, m_amount = value, m_amountPerLevel = value2, m_recover = result }); continue; IL_0116: problems.Add(forRecipe ? ("\"" + text3 + "\": the upgrade amount isn't a number") : ("\"" + text3 + "\": the last part isn't true or false")); } if (list.Count == 0 && problems.Count == count) { problems.Add("it's empty (nothing would be free: write at least one item)"); } if (problems.Count != count) { return null; } return list.ToArray(); } private static bool Whole(string text, out int value) { return int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out value); } public static string Write(IEnumerable<Requirement> cost, bool forRecipe) { return string.Join(", ", (from r in cost ?? Enumerable.Empty<Requirement>() where (Object)(object)r?.m_resItem != (Object)null select ((Object)r.m_resItem).name + ":" + r.m_amount + ((!forRecipe) ? (r.m_recover ? "" : ":false") : ((r.m_amountPerLevel > 0) ? (":" + r.m_amountPerLevel) : ""))).ToArray()); } public static ItemDrop FindItem(string name) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(name) : null); if ((Object)(object)val == (Object)null && (Object)(object)ObjectDB.instance != (Object)null) { val = ObjectDB.instance.GetItemPrefab(name); } if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<ItemDrop>(); } public static CraftingStation FindStation(string name, out bool found) { name = (name ?? "").Trim(); found = true; if (name.Length == 0 || name.Equals("none", StringComparison.OrdinalIgnoreCase)) { return null; } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(name) : null); CraftingStation val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<CraftingStation>() : null); found = (Object)(object)val2 != (Object)null; return val2; } public static bool Apply(Piece piece, string text, ManualLogSource log) { if ((Object)(object)piece == (Object)null) { return false; } List<string> problems = new List<string>(); Requirement[] array = Parse(text, problems, forRecipe: false); Report(log, ((Object)piece).name, problems); if (array == null) { return false; } piece.m_resources = array; return true; } public static bool Apply(Recipe recipe, string text, ManualLogSource log) { if ((Object)(object)recipe == (Object)null) { return false; } List<string> problems = new List<string>(); Requirement[] array = Parse(text, problems, forRecipe: true); Report(log, ((Object)recipe).name, problems); if (array == null) { return false; } recipe.m_resources = array; return true; } public static bool ApplyStation(Piece piece, string text, ManualLogSource log) { if ((Object)(object)piece == (Object)null) { return false; } bool found; CraftingStation craftingStation = FindStation((text ?? "").Split(new char[1] { ':' })[0], out found); if (!found) { if (log != null) { log.LogWarning((object)(((Object)piece).name + ": no crafting station called \"" + text + "\", it keeps its station")); } return false; } piece.m_craftingStation = craftingStation; return true; } public static bool ApplyStation(Recipe recipe, string text, ManualLogSource log) { if ((Object)(object)recipe == (Object)null) { return false; } string[] array = (text ?? "").Split(new char[1] { ':' }); bool found; CraftingStation craftingStation = FindStation(array[0], out found); int value = 1; if (!found || (array.Length > 1 && (!Whole(array[1].Trim(), out value) || value < 1))) { if (log != null) { log.LogWarning((object)(((Object)recipe).name + ": \"" + text + "\" isn't a crafting station (and level), it keeps its station")); } return false; } recipe.m_craftingStation = craftingStation; recipe.m_minStationLevel = value; return true; } private static void Report(ManualLogSource log, string what, List<string> problems) { if (problems.Count > 0 && log != null) { log.LogWarning((object)(what + "'s cost setting has a mistake, so it keeps its last cost: " + string.Join("; ", problems.ToArray()))); } } } internal static class Icon { private const int Size = 128; private static readonly Vector3 DefaultView = new Vector3(0.42f, 0.28f, -1f); private static int _layer = -1; private static readonly MethodInfo LoadImageMethod = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); private static int Layer { get { if (_layer < 0) { _layer = 31; for (int num = 31; num >= 8; num--) { if (string.IsNullOrEmpty(LayerMask.LayerToName(num))) { _layer = num; break; } } } return _layer; } } private static bool CanDraw => (int)SystemInfo.graphicsDeviceType != 4; private static string ModName => typeof(Icon).Assembly.GetName().Name; internal static Sprite Make(GameObject prefab, Vector3? view = null, Action<GameObject> pose = null, string fallback = "icon.png") { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) Sprite val = null; try { val = DrawPiece(prefab, (Vector3)(((??)view) ?? DefaultView), pose); } catch (Exception ex) { Debug.LogWarning((object)("[" + ModName + "] could not draw the build icon: " + ex.Message)); } if (!((Object)(object)val != (Object)null)) { return LoadSprite(fallback); } return val; } internal static Sprite MakeItem(GameObject itemPrefab, bool setIcon = false, string fallback = null, Quaternion? look = null) { Sprite val = null; try { val = DrawItem(itemPrefab, look); } catch (Exception ex) { Debug.LogWarning((object)("[" + ModName + "] could not draw the icon of " + (((Object)(object)itemPrefab != (Object)null) ? ((Object)itemPrefab).name : "an item") + ": " + ex.Message)); } Sprite val2 = (((Object)(object)val != (Object)null) ? val : LoadSprite(fallback)); if (setIcon && (Object)(object)val2 != (Object)null && (Object)(object)itemPrefab != (Object)null) { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { SharedData shared = component.m_itemData.m_shared; Sprite[] array = (Sprite[])((shared.m_icons != null && shared.m_icons.Length > 1) ? ((Array)(Sprite[])shared.m_icons.Clone()) : ((Array)new Sprite[1])); array[0] = val2; shared.m_icons = array; } } return val2; } private static Sprite DrawPiece(GameObject prefab, Vector3 view, Action<GameObject> pose) { //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_0049: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null || !CanDraw) { return null; } Transform val = prefab.transform.Find("Model"); return Draw(((Object)(object)val != (Object)null) ? ((Component)val).gameObject : prefab, (Object)(object)val == (Object)null, Quaternion.identity, pose, delegate(GameObject stage, Bounds bounds) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) Camera val2 = AddCamera(stage); val2.fieldOfView = 24f; val2.nearClipPlane = 0.1f; val2.farClipPlane = 60f; Vector3 extents = ((Bounds)(ref bounds)).extents; float magnitude = ((Vector3)(ref extents)).magnitude; ((Component)val2).transform.position = ((Bounds)(ref bounds)).center + ((Vector3)(ref view)).normalized * (magnitude / Mathf.Sin(val2.fieldOfView * 0.5f * ((float)Math.PI / 180f))) * 1.02f; ((Component)val2).transform.LookAt(((Bounds)(ref bounds)).center); AddLight(stage, Quaternion.Euler(38f, 28f, 0f), 1.25f); return val2; }, 0.08f); } private static Sprite DrawItem(GameObject itemPrefab, Quaternion? look) { //IL_0054: 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) if ((Object)(object)itemPrefab == (Object)null || !CanDraw) { return null; } Transform val = itemPrefab.transform.Find("attach"); return Draw(((Object)(object)val != (Object)null) ? ((Component)val).gameObject : itemPrefab, bare: true, ((Object)(object)val != (Object)null) ? val.localRotation : Quaternion.identity, null, delegate(GameObject stage, Bounds bounds) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017c: 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_018a: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022b: 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_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0149: 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) Camera val2 = AddCamera(stage); val2.orthographic = true; Vector3 size = ((Bounds)(ref bounds)).size; Quaternion val3 = (look.HasValue ? look.Value : ((size.y <= size.x * 1.15f && size.y <= size.z * 1.15f) ? Quaternion.LookRotation(Vector3.down, Vector3.forward) : ((!(size.x <= size.z)) ? Quaternion.LookRotation(Vector3.forward, Vector3.up) : Quaternion.LookRotation(Vector3.right, Vector3.up)))); if (!look.HasValue) { val3 *= Quaternion.Euler(0f, 0f, 45f); } ((Component)val2).transform.rotation = val3; Vector3 val4 = Vector3.positiveInfinity; Vector3 val5 = Vector3.negativeInfinity; for (int i = 0; i < 8; i++) { Vector3 val6 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((i & 1) != 0) ? 1 : (-1)), (float)(((i & 2) != 0) ? 1 : (-1)), (float)(((i & 4) != 0) ? 1 : (-1)))); Vector3 val7 = Quaternion.Inverse(val3) * (val6 - ((Bounds)(ref bounds)).center); val4 = Vector3.Min(val4, val7); val5 = Vector3.Max(val5, val7); } Vector3 val8 = (val4 + val5) * 0.5f; val2.orthographicSize = Mathf.Max(0.01f, Mathf.Max(val5.x - val4.x, val5.y - val4.y) * 0.5f * 1.08f); float num = val5.z - val4.z; ((Component)val2).transform.position = ((Bounds)(ref bounds)).center + val3 * new Vector3(val8.x, val8.y, val4.z - 1f); val2.nearClipPlane = 0.01f; val2.farClipPlane = num + 2f; Vector3 val9 = val3 * new Vector3(0.4f, -0.5f, 1f); AddLight(stage, Quaternion.LookRotation(val9, val3 * Vector3.up), 1.3f); return val2; }, 0.02f); } private static Sprite Draw(GameObject source, bool bare, Quaternion turn, Action<GameObject> pose, Func<GameObject, Bounds, Camera> frame, float minCover) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_018a: 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_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: 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_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Expected O, but got Unknown //IL_0254: 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_029d: Unknown result type (might be due to invalid IL or missing references) int layer = Layer; bool forceDisableInit = ZNetView.m_forceDisableInit; bool forceDisableTerrainOps = TerrainOp.m_forceDisableTerrainOps; RenderTexture active = RenderTexture.active; RenderTexture val = null; Camera val2 = null; GameObject val3 = new GameObject(ModName + "IconStage"); val3.SetActive(false); val3.transform.position = new Vector3(0f, -3000f, 0f); try { ZNetView.m_forceDisableInit = true; TerrainOp.m_forceDisableTerrainOps = true; GameObject val4 = Object.Instantiate<GameObject>(source, val3.transform); val4.transform.localPosition = Vector3.zero; val4.transform.localRotation = turn; val4.SetActive(true); if (bare) { Strip(val4); } Transform[] componentsInChildren = val4.GetComponentsInChildren<Transform>(true); foreach (Transform val5 in componentsInChildren) { ((Component)val5).gameObject.layer = layer; } if (!bare) { Renderer[] componentsInChildren2 = val4.GetComponentsInChildren<Renderer>(true); foreach (Renderer val6 in componentsInChildren2) { val6.enabled = true; } } val3.SetActive(true); pose?.Invoke(val4); Bounds arg = default(Bounds); bool flag = false; Renderer[] componentsInChildren3 = val4.GetComponentsInChildren<Renderer>(); foreach (Renderer val7 in componentsInChildren3) { if (val7.enabled && !IsParticles(val7)) { if (!flag) { arg = val7.bounds; flag = true; } else { ((Bounds)(ref arg)).Encapsulate(val7.bounds); } } } if (!flag) { return null; } val2 = frame(val3, arg); val2.cullingMask = 1 << layer; val = (val2.targetTexture = RenderTexture.GetTemporary(256, 256, 24, (RenderTextureFormat)0)); AmbientMode ambientMode = RenderSettings.ambientMode; Color ambientLight = RenderSettings.ambientLight; float reflectionIntensity = RenderSettings.reflectionIntensity; RenderSettings.ambientMode = (AmbientMode)3; RenderSettings.ambientLight = new Color(0.5f, 0.5f, 0.5f); RenderSettings.reflectionIntensity = 0.25f; try { val2.Render(); } finally { RenderSettings.ambientMode = ambientMode; RenderSettings.ambientLight = ambientLight; RenderSettings.reflectionIntensity = reflectionIntensity; } RenderTexture.active = val; Texture2D val8 = new Texture2D(((Texture)val).width, ((Texture)val).height, (TextureFormat)4, false); val8.ReadPixels(new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), 0, 0); val8.Apply(); if (LooksFine(val8, minCover)) { return Sprite.Create(val8, new Rect(0f, 0f, (float)((Texture)val8).width, (float)((Texture)val8).height), new Vector2(0.5f, 0.5f), 100f); } Object.Destroy((Object)(object)val8); return null; } finally { ZNetView.m_forceDisableInit = forceDisableInit; TerrainOp.m_forceDisableTerrainOps = forceDisableTerrainOps; RenderTexture.active = active; if ((Object)(object)val2 != (Object)null) { val2.targetTexture = null; } if ((Object)(object)val != (Object)null) { RenderTexture.ReleaseTemporary(val); } Object.DestroyImmediate((Object)(object)val3); } } private static bool IsParticles(Renderer r) { if (!(r is TrailRenderer) && !(r is LineRenderer)) { return ((object)r).GetType().Name == "ParticleSystemRenderer"; } return true; } private static Camera AddCamera(GameObject stage) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("IconCamera"); val.transform.SetParent(stage.transform, false); Camera val2 = val.AddComponent<Camera>(); ((Behaviour)val2).enabled = false; val2.clearFlags = (CameraClearFlags)2; val2.backgroundColor = new Color(0f, 0f, 0f, 0f); val2.allowHDR = false; val2.allowMSAA = false; val2.cullingMask = 1 << Layer; return val2; } private static void AddLight(GameObject stage, Quaternion rotation, float intensity) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("IconLight"); val.transform.SetParent(stage.transform, false); val.transform.rotation = rotation; Light val2 = val.AddComponent<Light>(); val2.type = (LightType)1; val2.intensity = intensity; val2.shadows = (LightShadows)0; val2.cullingMask = 1 << Layer; } private static void Strip(GameObject copy) { Transform[] componentsInChildren = copy.GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { List<MonoBehaviour> list = new List<MonoBehaviour>(((Component)val).GetComponents<MonoBehaviour>()); for (int j = 0; j < 4; j++) { if (list.Count <= 0) { break; } for (int num = list.Count - 1; num >= 0; num--) { if ((Object)(object)list[num] == (Object)null) { list.RemoveAt(num); } else if (!Needed(list[num], list)) { Object.DestroyImmediate((Object)(object)list[num]); list.RemoveAt(num); } } } } Collider[] componentsInChildren2 = copy.GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren2) { val2.enabled = false; } Rigidbody[] componentsInChildren3 = copy.GetComponentsInChildren<Rigidbody>(true); foreach (Rigidbody val3 in componentsInChildren3) { val3.isKinematic = true; val3.detectCollisions = false; } } private static bool Needed(MonoBehaviour script, List<MonoBehaviour> others) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown Type type = ((object)script).GetType(); foreach (MonoBehaviour other in others) { if ((Object)(object)other == (Object)null || (Object)(object)other == (Object)(object)script) { continue; } object[] customAttributes = ((object)other).GetType().GetCustomAttributes(typeof(RequireComponent), inherit: true); for (int i = 0; i < customAttributes.Length; i++) { RequireComponent val = (RequireComponent)customAttributes[i]; if (Is(val.m_Type0, type) || Is(val.m_Type1, type) || Is(val.m_Type2, type)) { return true; } } } return false; } private static bool Is(Type required, Type type) { if (required != null) { return required.IsAssignableFrom(type); } return false; } private static bool LooksFine(Texture2D tex, float minCover) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) Color32[] pixels = tex.GetPixels32(); int num = 0; long num2 = 0L; for (int i = 0; i < pixels.Length; i += 7) { Color32 val = pixels[i]; if (val.a > 40) { num++; num2 += val.r + val.g + val.b; } } int num3 = pixels.Length / 7 + 1; if ((float)num > (float)num3 * minCover) { return num2 / Math.Max(1, num) > 60; } return false; } private static bool LoadImage(Texture2D tex, byte[] data) { if (LoadImageMethod != null) { return (bool)LoadImageMethod.Invoke(null, new object[2] { tex, data }); } return false; } internal static Texture2D LoadEmbedded(string name) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown if (string.IsNullOrEmpty(name)) { return null; } using Stream stream = typeof(Icon).Assembly.GetManifestResourceStream(name); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); return LoadImage(val, array) ? val : null; } internal static Sprite LoadSprite(string name) { //IL_0029: 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) Texture2D val = LoadEmbedded(name); if (!((Object)(object)val == (Object)null)) { return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } return null; } } [BepInPlugin("nick.valheim.wardrobeportal", "WardrobePortal", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "nick.valheim.wardrobeportal"; public const string Name = "WardrobePortal"; public const string Version = "1.0.0"; internal static Plugin Instance; internal static ManualLogSource Log; internal static ServerSettings Synced; internal static ConfigEntry<string> Cost; internal static ConfigEntry<string> Station; internal static ConfigEntry<float> OpenDistance; internal static ConfigEntry<float> OpenAngle; internal static ConfigEntry<float> DoorSpeed; private Harmony _harmony; private void Awake() { //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Translations.Load((BaseUnityPlugin)(object)this); Synced = new ServerSettings("nick.valheim.wardrobeportal", ((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; Cost = Synced.Bind("1 - Building", "Cost", "Frostwood:10, Tar:2, BlackMetal:6, SurtlingCore:2, GreydwarfEye:10", "What a Wardrobe Portal costs to build (by default the wardrobe's cost, plus the two Surtling Cores and ten Greydwarf Eyes a portal takes). Item prefab names and amounts, separated by commas, like FineWood:12, BronzeNails:30 (Claude Tools' `prefabs <text>` shows exact names). A cost with a mistake in it keeps the last good one.", null); Station = Synced.Bind("1 - Building", "Station", "piece_workbench", "The crafting station that must be near to build it. The crafting station's prefab name (piece_workbench, forge, piece_stonecutter, piece_artisanstation, blackforge, piece_magetable), or none.", null); OpenDistance = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Doors", "Open distance", 4f, new ConfigDescription("The doors swing open when a player comes this close (metres).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>())); OpenAngle = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Doors", "Open angle", 110f, new ConfigDescription("How far the doors swing open (degrees).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 170f), Array.Empty<object>())); DoorSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Doors", "Door speed", 180f, new ConfigDescription("How fast the doors swing (degrees a second).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 720f), Array.Empty<object>())); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ((BaseUnityPlugin)this).Config.Save(); Cost.SettingChanged += delegate { WardrobePiece.ApplyCost(); }; Station.SettingChanged += delegate { WardrobePiece.ApplyCost(); }; _harmony = Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "nick.valheim.wardrobeportal"); WardrobePiece.Register(ZNetScene.instance); Log.LogInfo((object)"WardrobePortal 1.0.0 loaded"); } private void Update() { Synced?.Update(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } WardrobePiece.Unload(); Synced?.Dispose(); Translations.Unload(); Instance = null; Synced = null; } } internal class WardrobeDoors : MonoBehaviour { private class Door { public Transform T; public Quaternion Shut; public float Sign; } private const string ClosedKey = "nick_wardrobeportal_closed"; private const string ToggleRpc = "WardrobePortal_Toggle"; private const string ArrivedKey = "nick_wardrobeportal_arrived"; private const string ArriveRpc = "WardrobePortal_Arrive"; private const float ArrivalSeconds = 4f; internal static ZDOID Pending = ZDOID.None; internal static float PendingSince; private ZNetView _nview; private TeleportWorld _portal; private readonly List<Door> _doors = new List<Door>(); private float _angle; private bool _playerNear; private float _nextLook; public bool Closed { get { if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { return _nview.GetZDO().GetBool("nick_wardrobeportal_closed", false); } return false; } } public bool Arriving { get { if (Closed && (Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.GetTime().Ticks < _nview.GetZDO().GetLong("nick_wardrobeportal_arrived", 0L); } return false; } } public bool Asleep { get { if (Closed) { return !Arriving; } return false; } } private void Awake() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) _nview = ((Component)this).GetComponent<ZNetView>(); _portal = ((Component)this).GetComponent<TeleportWorld>(); if ((Object)(object)_nview == (Object)null || _nview.GetZDO() == null) { ((Behaviour)this).enabled = false; return; } _nview.Register<bool>("WardrobePortal_Toggle", (Action<long, bool>)RPC_Toggle); _nview.Register("WardrobePortal_Arrive", (Action<long>)RPC_Arrive); Transform val = ((Component)this).transform.Find("wardrobe"); if ((Object)(object)val != (Object)null) { foreach (Transform item in val) { Transform val2 = item; if (((Object)val2).name.StartsWith("door_hinge", StringComparison.Ordinal)) { _doors.Add(new Door { T = val2, Shut = val2.localRotation, Sign = ((val2.localPosition.x < 0f) ? (-1f) : 1f) }); } } } if (_doors.Count == 0) { Plugin.Log.LogWarning((object)"Wardrobe Portal: no doors found on the model (they don't swing)"); } } public void RequestToggle(Humanoid human) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { ((Character)human).Message((MessageType)2, "$piece_noaccess", 0, (Sprite)null, false); return; } _nview.InvokeRPC("WardrobePortal_Toggle", new object[1] { !Closed }); } private void RPC_Toggle(long sender, bool closed) { try { if (_nview.IsValid() && _nview.IsOwner()) { _nview.GetZDO().Set("nick_wardrobeportal_closed", closed); } } catch (Exception ex) { Plugin.Log.LogError((object)("Wardrobe Portal toggle: " + ex)); } } private void RPC_Arrive(long sender) { try { if (_nview.IsValid() && _nview.IsOwner()) { _nview.GetZDO().Set("nick_wardrobeportal_arrived", ZNet.instance.GetTime().AddSeconds(4.0).Ticks); } } catch (Exception ex) { Plugin.Log.LogError((object)("Wardrobe Portal arrival: " + ex)); } } private void CheckArrival() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0056: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (Pending == ZDOID.None) { return; } if (Time.time - PendingSince > 60f) { Pending = ZDOID.None; return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsTeleporting() && !(Pending != _nview.GetZDO().m_uid) && !(Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position) > 8f)) { Pending = ZDOID.None; if (Closed) { _nview.InvokeRPC("WardrobePortal_Arrive", Array.Empty<object>()); } } } private void Update() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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) CheckArrival(); if (Time.time >= _nextLook) { _nextLook = Time.time + 0.25f; _playerNear = (Object)(object)Player.GetClosestPlayer(((Component)this).transform.position, Plugin.OpenDistance.Value) != (Object)null; } float num = ((!Asleep && _playerNear) ? Plugin.OpenAngle.Value : 0f); if (Mathf.Approximately(_angle, num)) { return; } _angle = Mathf.MoveTowards(_angle, num, Plugin.DoorSpeed.Value * Time.deltaTime); foreach (Door door in _doors) { door.T.localRotation = door.Shut * Quaternion.Euler(0f, door.Sign * _angle, 0f); } } public string HoverText() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return ""; } string text = (((Object)(object)_portal != (Object)null) ? _portal.GetText() : ""); string text2 = (Closed ? Translations.T("wardrobeportal_closed") : "$piece_portal_connected"); if (!Closed && _nview.GetZDO().GetConnectionZDOID((ConnectionType)1) == ZDOID.None) { text2 = "$piece_portal_unconnected"; } return Localization.instance.Localize(Translations.T("wardrobeportal_piece") + " $piece_portal_tag:\"" + text + "\" [" + text2 + "]\n[<color=yellow><b>$KEY_Use</b></color>] $piece_portal_settag\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] " + Translations.T(Closed ? "wardrobeportal_open" : "wardrobeportal_close")); } } [HarmonyPatch(typeof(TeleportWorld), "Interact")] internal static class TeleportWorld_Interact { private static bool Prefix(TeleportWorld __instance, Humanoid human, bool hold, bool alt, ref bool __result) { WardrobeDoors component = ((Component)__instance).GetComponent<WardrobeDoors>(); if ((Object)(object)component == (Object)null || !alt) { return true; } __result = false; if (hold) { return false; } component.RequestToggle(human); __result = true; return false; } } [HarmonyPatch(typeof(TeleportWorld), "GetHoverText")] internal static class TeleportWorld_GetHoverText { private static void Postfix(TeleportWorld __instance, ref string __result) { WardrobeDoors component = ((Component)__instance).GetComponent<WardrobeDoors>(); if ((Object)(object)component != (Object)null) { __result = component.HoverText(); } } } [HarmonyPatch(typeof(TeleportWorld), "Teleport")] internal static class TeleportWorld_Teleport { private static bool Prefix(TeleportWorld __instance) { WardrobeDoors component = ((Component)__instance).GetComponent<WardrobeDoors>(); if (!((Object)(object)component == (Object)null)) { return !component.Closed; } return true; } private static void Postfix(TeleportWorld __instance, Player player) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && ((Character)player).IsTeleporting()) { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); ZDO val = (((Object)(object)component != (Object)null) ? component.GetZDO() : null); ZDOID val2 = ((val != null) ? val.GetConnectionZDOID((ConnectionType)1) : ZDOID.None); ZDO val3 = ((val2 != ZDOID.None) ? ZDOMan.instance.GetZDO(val2) : null); if (val3 != null && val3.GetPrefab() == WardrobePiece.Hash) { WardrobeDoors.Pending = val2; WardrobeDoors.PendingSince = Time.time; } } } catch (Exception ex) { Plugin.Log.LogError((object)("Wardrobe Portal: " + ex)); } } } [HarmonyPatch(typeof(TeleportWorld), "UpdatePortal")] internal static class TeleportWorld_UpdatePortal { private static void Postfix(TeleportWorld __instance) { WardrobeDoors component = ((Component)__instance).GetComponent<WardrobeDoors>(); if ((Object)(object)component != (Object)null && component.Asleep && (Object)(object)__instance.m_target_found != (Object)null) { __instance.m_target_found.SetActive(false); } } } internal static class WardrobePiece { public const string PrefabName = "nick_wardrobeportal"; public const string PieceName = "$wardrobeportal_piece"; private const string PortalSource = "portal_wood"; private const string WardrobeSource = "piece_chest_warderobe"; internal static GameObject Prefab; private static PieceTable _table; private static GameObject _holder; private static readonly FieldRef<ZNetScene, Dictionary<int, GameObject>> NamedPrefabs = AccessTools.FieldRefAccess<ZNetScene, Dictionary<int, GameObject>>("m_namedPrefabs"); private static readonly Vector3 SwirlScale = new Vector3(0.38f, 0.62f, 0.38f); private static readonly Vector3 SwirlAt = new Vector3(0f, 0.45f, -0.05f); private static readonly Vector3 TriggerAt = new Vector3(0f, 1.2f, 0.15f); private static readonly Vector3 TriggerScale = new Vector3(0.65f, 1.2f, 0.4f); private const float Wall = 0.05f; private const float FrontZSign = 1f; public static int Hash => StringExtensionMethods.GetStableHashCode("nick_wardrobeportal"); public static void Register(ZNetScene scene) { if ((Object)(object)scene == (Object)null) { return; } if ((Object)(object)Prefab == (Object)null) { Prefab = Build(scene); } if ((Object)(object)Prefab == (Object)null) { return; } if (!scene.m_prefabs.Contains(Prefab)) { scene.m_prefabs.Add(Prefab); } NamedPrefabs.Invoke(scene)[Hash] = Prefab; GameObject prefab = scene.GetPrefab("Hammer"); PieceTable val = ((!((Object)(object)prefab != (Object)null)) ? null : prefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces); if ((Object)(object)val != (Object)null) { val.m_pieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null); if (!val.m_pieces.Contains(Prefab)) { val.m_pieces.Add(Prefab); } _table = val; } ApplyCost(); Plugin.Synced.NeedsServer(Prefab); AddPortalHash(); } public static void ApplyCost() { Piece val = (((Object)(object)Prefab != (Object)null) ? Prefab.GetComponent<Piece>() : null); if (!((Object)(object)val == (Object)null)) { Costs.Apply(val, Plugin.Cost.Value, Plugin.Log); Costs.ApplyStation(val, Plugin.Station.Value, Plugin.Log); } } public static void AddPortalHash() { if ((Object)(object)Game.instance != (Object)null && !Game.instance.PortalPrefabHash.Contains(Hash)) { Game.instance.PortalPrefabHash.Add(Hash); } } public static void Unload() { if ((Object)(object)_table != (Object)null && (Object)(object)Prefab != (Object)null) { _table.m_pieces.Remove(Prefab); } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance != (Object)null && (Object)(object)Prefab != (Object)null) { instance.m_prefabs.Remove(Prefab); if (NamedPrefabs.Invoke(instance).TryGetValue(Hash, out var value) && (Object)(object)value == (Object)(object)Prefab) { NamedPrefabs.Invoke(instance).Remove(Hash); } } if ((Object)(object)_holder != (Object)null) { Object.Destroy((Object)(object)_holder); } Prefab = null; _table = null; _holder = null; } private static GameObject Build(ZNetScene scene) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown GameObject prefab = scene.GetPrefab("portal_wood"); GameObject prefab2 = scene.GetPrefab("piece_chest_warderobe"); if ((Object)(object)prefab == (Object)null || (Object)(object)prefab2 == (Object)null) { Plugin.Log.LogWarning((object)("The game has no " + (((Object)(object)prefab == (Object)null) ? "portal_wood" : "piece_chest_warderobe") + " to copy: no Wardrobe Portal this session")); return null; } _holder = new GameObject("WardrobePortal_prefabs"); _holder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_holder); GameObject val = Object.Instantiate<GameObject>(prefab, _holder