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 Below the Keel v1.0.0
plugins/BelowTheKeel.dll
Decompiled a day 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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using HeaveHo.Shared; using Microsoft.CodeAnalysis; 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: 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 BelowTheKeel { internal static class Commands { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__3_0; internal void <Register>b__3_0(ConsoleEventArgs args) { Run(args.Context, args.Args); } } private const string Command = "keel"; private const string Usage = "keel status | keel next | keel play <eye [classic] [width] [depth] | eye [classic] at <seconds> | eye [classic] show [at <seconds>]|pacer [side] [depth] [glow x]|halfboat [near [metres]]|ransnet [side <metres>]> | keel probe [off] | keel pose | keel hands [up] [out] [marks] | keel plate <name> <x> <y> <z> <yaw> <pitch> [fov] [size] [cut [omens]] | keel depths | keel shaders [text] | keel material <prefab>"; private static readonly FieldRef<Dictionary<string, ConsoleCommand>> TerminalCommands = AccessTools.StaticFieldRefAccess<Dictionary<string, ConsoleCommand>>(AccessTools.Field(typeof(Terminal), "commands")); internal static void Register() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown object obj = <>c.<>9__3_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { Run(args.Context, args.Args); }; <>c.<>9__3_0 = val; obj = (object)val; } new ConsoleCommand("keel", "Below the Keel: keel status | keel next | keel play <eye [classic] [width] [depth] | eye [classic] at <seconds> | eye [classic] show [at <seconds>]|pacer [side] [depth] [glow x]|halfboat [near [metres]]|ransnet [side <metres>]> | keel probe [off] | keel pose | keel hands [up] [out] [marks] | keel plate <name> <x> <y> <z> <yaw> <pitch> [fov] [size] [cut [omens]] | keel depths | keel shaders [text] | keel material <prefab>", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } internal static void Unregister() { TerminalCommands.Invoke().Remove("keel"); } private static string Spread(List<float> depths) { if (depths.Count == 0) { return "none"; } depths.Sort(); return $"{depths.Count} points, deepest {depths[depths.Count - 1]:0} m; 10% {At(0.1f):0}, half {At(0.5f):0}, 90% {At(0.9f):0} m"; float At(float q) { return depths[Mathf.Clamp((int)(q * (float)(depths.Count - 1)), 0, depths.Count - 1)]; } } private static void Run(Terminal t, string[] a) { //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_0ab5: Unknown result type (might be due to invalid IL or missing references) //IL_0ba5: Unknown result type (might be due to invalid IL or missing references) //IL_0ba7: Unknown result type (might be due to invalid IL or missing references) //IL_0bb1: Invalid comparison between Unknown and I4 //IL_0bb3: Unknown result type (might be due to invalid IL or missing references) //IL_0bc5: Unknown result type (might be due to invalid IL or missing references) //IL_0eaf: Unknown result type (might be due to invalid IL or missing references) //IL_0eb4: Unknown result type (might be due to invalid IL or missing references) //IL_0eb6: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_0f23: Unknown result type (might be due to invalid IL or missing references) //IL_0f28: Unknown result type (might be due to invalid IL or missing references) //IL_0eba: Unknown result type (might be due to invalid IL or missing references) //IL_0ebd: Invalid comparison between Unknown and I4 //IL_0ebf: Unknown result type (might be due to invalid IL or missing references) //IL_0ec2: Invalid comparison between Unknown and I4 //IL_0ee1: Unknown result type (might be due to invalid IL or missing references) //IL_0ee6: Unknown result type (might be due to invalid IL or missing references) //IL_08ac: Unknown result type (might be due to invalid IL or missing references) //IL_08c4: Unknown result type (might be due to invalid IL or missing references) //IL_08dc: Unknown result type (might be due to invalid IL or missing references) string text = ((a.Length > 1) ? a[1].ToLowerInvariant() : "status"); Ship localShip = Ship.GetLocalShip(); switch (text) { case "status": { if ((Object)(object)localShip == (Object)null) { t.AddString("Not aboard a ship."); break; } Vector3 position = ((Component)localShip).transform.position; string why2; bool flag2 = Sea.IsDeep(position, out why2); t.AddString($"Depth {Sea.Depth(position):0} m, biome {WorldGenerator.instance.GetBiome(position)}: " + (flag2 ? "omens may come" : ("no omens (" + why2 + ")"))); t.AddString($"Ship id {Director.ShipId(localShip):X}, {Visuals.Count} omen object(s) showing"); foreach (string item2 in Visuals.Where()) { t.AddString(" " + item2); } t.AddString($"Open sea since its last omen: {Director.OpenSeaSeconds(localShip) / 60f:0.0} min (fail-safe at {Plugin.FailSafeMinutes.Value:0})"); t.AddString($"Weather {EnvMan.instance.GetCurrentEnvironment()?.m_name}, fog {RenderSettings.fogMode} density {RenderSettings.fogDensity:0.0000} (sight {Sea.SightDistance():0} m), night {EnvMan.IsNight()}"); break; } case "next": { if ((Object)(object)localShip == (Object)null) { t.AddString("Not aboard a ship."); break; } ulong shipId = Director.ShipId(localShip); double timeSeconds = ZNet.instance.GetTimeSeconds(); long num = (long)(timeSeconds / 30.0); int num2 = 0; for (long num3 = num + 1; num3 < num + 2000; num3++) { if (num2 >= 3) { break; } if (Director.Fires(shipId, num3, out var omen, out var _)) { float num4 = (float)(((double)num3 * 30.0 - timeSeconds) / 60.0); t.AddString($"In {num4:0.0} min: {omen.Name} (if the ship is in deep water then; night now: {EnvMan.IsNight()})"); num2++; } } if (num2 == 0) { t.AddString("None in the next 1000 minutes."); } break; } case "play": { if ((Object)(object)localShip == (Object)null) { t.AddString("Not aboard a ship."); break; } Omen omen2 = ((a.Length > 2) ? Omens.Find(a[2]) : null); if (omen2 == null) { t.AddString("keel status | keel next | keel play <eye [classic] [width] [depth] | eye [classic] at <seconds> | eye [classic] show [at <seconds>]|pacer [side] [depth] [glow x]|halfboat [near [metres]]|ransnet [side <metres>]> | keel probe [off] | keel pose | keel hands [up] [out] [marks] | keel plate <name> <x> <y> <z> <yaw> <pitch> [fov] [size] [cut [omens]] | keel depths | keel shaders [text] | keel material <prefab>"); break; } EyeOmen.Classic = omen2 is EyeOmen && Array.IndexOf(a, "classic") > 2; bool flag = omen2 is EyeOmen && Array.IndexOf(a, "show") > 2; List<string> list4 = new List<string>(a); list4.Remove("fire"); list4.Remove("classic"); list4.Remove("show"); a = list4.ToArray(); if (flag) { EyeOmen.Show = true; int num7 = Array.IndexOf(a, "at"); EyeOmen.FreezeAt = ((num7 > 0 && a.Length > num7 + 1) ? float.Parse(a[num7 + 1], CultureInfo.InvariantCulture) : 10f); EyeOmen.Play(localShip, (uint)Random.Range(int.MinValue, int.MaxValue), 12f, -9f); t.AddString("The eye, lifted above the water beside the ship for a minute"); } else if (omen2 is EyeOmen && a.Length > 4 && a[3] == "at") { float num8 = (EyeOmen.FreezeAt = float.Parse(a[4], CultureInfo.InvariantCulture)); omen2.Play(localShip, (uint)Random.Range(int.MinValue, int.MaxValue)); t.AddString($"Eye held at {num8:0.##} s for a minute"); } else if (omen2 is EyeOmen && a.Length > 3) { float result2; float num9 = (float.TryParse(a[3], NumberStyles.Float, CultureInfo.InvariantCulture, out result2) ? result2 : 36f); float result3; float num10 = ((a.Length > 4 && float.TryParse(a[4], NumberStyles.Float, CultureInfo.InvariantCulture, out result3)) ? result3 : float.NaN); EyeOmen.Play(localShip, (uint)Random.Range(int.MinValue, int.MaxValue), Mathf.Clamp(num9, 2f, 120f), num10); t.AddString(string.Format("Playing eye, {0:0} m across, top {1} down", num9, (!float.IsNaN(num10)) ? (num10.ToString("0.#") + " m") : "6-7 m")); } else if (omen2 is PacerOmen && a.Length > 3) { float num11 = float.Parse(a[3], CultureInfo.InvariantCulture); float num12 = ((a.Length > 4 && a[4] != "glow") ? float.Parse(a[4], CultureInfo.InvariantCulture) : float.NaN); int num13 = Array.IndexOf(a, "glow"); PacerOmen.Glow = ((num13 > 0 && a.Length > num13 + 1) ? float.Parse(a[num13 + 1], CultureInfo.InvariantCulture) : 1f); try { PacerOmen.Play(localShip, (uint)Random.Range(int.MinValue, int.MaxValue), num11, num12); } finally { PacerOmen.Glow = 1f; } t.AddString($"Playing pacer {num11:0} m to the side" + (float.IsNaN(num12) ? "" : $", its middle {num12:0.#} m down")); } else if (omen2 is RansNetOmen && a.Length > 4 && a[3] == "side") { RansNetOmen.Side = float.Parse(a[4], CultureInfo.InvariantCulture); omen2.Play(localShip, (uint)Random.Range(int.MinValue, int.MaxValue)); t.AddString("Playing ransnet " + a[4] + " m to the side"); } else if (omen2 is HalfBoatOmen && a.Length > 3 && a[3] == "near") { float result4; float num14 = ((a.Length > 4 && float.TryParse(a[4], NumberStyles.Float, CultureInfo.InvariantCulture, out result4)) ? result4 : 12f); HalfBoatOmen.Play(localShip, (uint)Random.Range(int.MinValue, int.MaxValue), Mathf.Sign(num14) * Mathf.Clamp(Mathf.Abs(num14), 4f, 200f)); t.AddString(string.Format("Half-boat holding {0:0} m to {1} for a minute; ship at {2:0.0} {3:0.0}, heading {4:0}", Mathf.Abs(num14), (num14 < 0f) ? "port" : "starboard", ((Component)localShip).transform.position.x, ((Component)localShip).transform.position.z, ((Component)localShip).transform.eulerAngles.y)); } else { omen2.Play(localShip, (uint)Random.Range(int.MinValue, int.MaxValue)); t.AddString("Playing " + omen2.Name); } break; } case "probe": if (a.Length > 2 && a[2] == "off") { Probe.Clear(); t.AddString("Probe removed."); } else if ((Object)(object)localShip == (Object)null) { t.AddString("Not aboard a ship."); } else { t.AddString(Probe.Show(localShip)); } break; case "hands": { if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)localShip == (Object)null) { t.AddString("Stand aboard a ship, at its side, facing over it."); break; } Hands.Markers = Array.IndexOf(a, "marks") > 1; List<float> list = new List<float>(); string[] array = a; foreach (string s in array) { if (float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { list.Add(result); } } t.AddString(Hands.Show(Player.m_localPlayer, localShip, (list.Count > 0) ? list[0] : 0f, (list.Count > 1) ? list[1] : 0f)); break; } case "plate": { if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)localShip == (Object)null || a.Length < 8) { t.AddString("keel plate <name> <x> <y> <z> <yaw> <pitch> [fov=60] [size=2048] [cut]"); break; } bool cut = Array.IndexOf(a, "cut") > 0; t.AddString(Plate.Render(Player.m_localPlayer, localShip, a[2], new Vector3(F(3, 0f), F(4, 1.6f), F(5, 0f)), F(6, 0f), F(7, 0f), F(8, 60f), (int)F(9, 2048f), cut, Array.IndexOf(a, "omens") > 0)); break; } case "pose": { if ((Object)(object)localShip == (Object)null) { t.AddString("Not aboard a ship."); break; } string text3 = RansNetOmen.Pose(localShip); t.AddString("One of Ran's drowned, above the water 7 m to starboard, for a minute (eyes open 11 s in): " + text3); break; } case "depths": { List<float> list2 = new List<float>(); List<float> list3 = new List<float>(); float value = Plugin.MinDepth.Value; Plugin.MinDepth.Value = -1000f; try { Vector3 val4 = default(Vector3); for (float num5 = -10000f; num5 <= 10000f; num5 += 200f) { for (float num6 = -10000f; num6 <= 10000f; num6 += 200f) { if (num5 * num5 + num6 * num6 > 100000000f) { continue; } ((Vector3)(ref val4))..ctor(num5, 0f, num6); if ((int)WorldGenerator.instance.GetBiome(val4) == 256) { float item = Sea.Depth(val4); list2.Add(item); if (Sea.IsDeep(val4, out var _)) { list3.Add(item); } } } } } finally { Plugin.MinDepth.Value = value; } t.AddString("Ocean depth (every 200 m over the world): " + Spread(list2)); t.AddString($"Away from land ({Plugin.LandDistance.Value:0} m): " + Spread(list3)); float[] array2 = new float[7] { 20f, 25f, 30f, 35f, 40f, 50f, 60f }; foreach (float min in array2) { t.AddString($" at least {min:0} m deep: {(float)list3.FindAll((float d) => d >= min).Count * 100f / (float)Mathf.Max(1, list3.Count):0}% of it"); } break; } case "shaders": { string value2 = ((a.Length > 2) ? a[2] : ""); SortedSet<string> sortedSet = new SortedSet<string>(); Shader[] array3 = Resources.FindObjectsOfTypeAll<Shader>(); foreach (Shader val5 in array3) { if (((Object)val5).name.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0) { sortedSet.Add(string.Format("{0} ({1}, queue {2})", ((Object)val5).name, val5.isSupported ? "ok" : "unsupported", val5.renderQueue)); } } { foreach (string item3 in sortedSet) { t.AddString(item3); } break; } } case "material": { GameObject val = ((a.Length > 2 && (Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(a[2]) : null); if ((Object)(object)val == (Object)null) { t.AddString("No such prefab."); break; } Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { Material[] sharedMaterials = val2.sharedMaterials; foreach (Material val3 in sharedMaterials) { if (!((Object)(object)val3 == (Object)null)) { t.AddString(((Object)val2).name + ": " + ((Object)val3).name + " (" + ((Object)val3.shader).name + ") keywords [" + string.Join(" ", val3.shaderKeywords) + "]"); for (int k = 0; k < val3.shader.GetPropertyCount(); k++) { string propertyName = val3.shader.GetPropertyName(k); ShaderPropertyType propertyType = val3.shader.GetPropertyType(k); string text2 = (((int)propertyType == 0) ? ((object)val3.GetColor(propertyName)/*cast due to .constrained prefix*/).ToString() : (((int)propertyType == 4) ? (((Object)(object)val3.GetTexture(propertyName) != (Object)null) ? ((Object)val3.GetTexture(propertyName)).name : "-") : (((int)propertyType == 1) ? ((object)val3.GetVector(propertyName)/*cast due to .constrained prefix*/).ToString() : val3.GetFloat(propertyName).ToString("0.###")))); t.AddString(" " + propertyName + " = " + text2); } } } } break; } default: t.AddString("keel status | keel next | keel play <eye [classic] [width] [depth] | eye [classic] at <seconds> | eye [classic] show [at <seconds>]|pacer [side] [depth] [glow x]|halfboat [near [metres]]|ransnet [side <metres>]> | keel probe [off] | keel pose | keel hands [up] [out] [marks] | keel plate <name> <x> <y> <z> <yaw> <pitch> [fov] [size] [cut [omens]] | keel depths | keel shaders [text] | keel material <prefab>"); break; } float F(int num16, float d) { if (a.Length <= num16 || !float.TryParse(a[num16], NumberStyles.Float, CultureInfo.InvariantCulture, out var result5)) { return d; } return result5; } } } internal static class Director { internal const double SlotSeconds = 30.0; internal const string OpenSeaKey = "BelowTheKeel.deepSeconds"; private static long _lastSlot = long.MinValue; private static float _lastPlayed = float.NegativeInfinity; internal static void Reset() { _lastSlot = long.MinValue; _lastPlayed = float.NegativeInfinity; } internal static void Update() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { return; } Ship localShip = Ship.GetLocalShip(); if ((Object)(object)localShip == (Object)null) { return; } long num = (long)(ZNet.instance.GetTimeSeconds() / 30.0); if (num == _lastSlot) { return; } bool flag = _lastSlot == long.MinValue; _lastSlot = num; if (flag || !Sea.IsDeep(((Component)localShip).transform.position, out var _)) { return; } ulong shipId = ShipId(localShip); Omen omen; uint seed; bool flag2 = Fires(shipId, num, out omen, out seed); bool flag3 = false; if (!flag2 && FailSafeDue(localShip)) { Pick(shipId, num, out omen, out seed); flag2 = (flag3 = true); } if (flag2) { omen = Playable(omen, localShip); } CountOpenSea(localShip, omen != null && flag2); if (flag2 && omen != null) { _lastPlayed = Time.time; if (Plugin.Enabled.Value && omen.IsEnabled) { Plugin.Log.LogInfo((object)("Omen: " + omen.Name + (flag3 ? " (fail-safe)" : ""))); omen.Play(localShip, seed); } } } internal static bool Fires(ulong shipId, long slot, out Omen omen, out uint seed) { omen = null; seed = 0u; if (!RawHit(shipId, slot)) { return false; } int num = Mathf.CeilToInt(Plugin.MinutesApart.Value * 60f / 30f); for (long num2 = slot - 1; num2 >= slot - num; num2--) { if (RawHit(shipId, num2)) { return false; } } Pick(shipId, slot, out omen, out seed); return true; } private static void Pick(ulong shipId, long slot, out Omen omen, out uint seed) { omen = Omens.All[Hash(shipId, slot, 2u) % (uint)Omens.All.Length]; seed = Hash(shipId, slot, 3u); } internal static Omen Playable(Omen picked, Ship ship) { int num = Array.IndexOf(Omens.All, picked); for (int i = 0; i < Omens.All.Length; i++) { Omen omen = Omens.All[(num + i) % Omens.All.Length]; if (omen.CanPlay(ship)) { return omen; } } return null; } internal static float OpenSeaSeconds(Ship ship) { ZDO val = ShipZdo(ship); if (val == null) { return 0f; } return val.GetFloat("BelowTheKeel.deepSeconds", 0f); } private static bool FailSafeDue(Ship ship) { float num = Plugin.FailSafeMinutes.Value * 60f; if (num <= 0f) { return false; } if (Time.time - _lastPlayed < Plugin.MinutesApart.Value * 60f) { return false; } return OpenSeaSeconds(ship) >= num; } private static void CountOpenSea(Ship ship, bool reset) { ZNetView component = ((Component)ship).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner()) { ZDO zDO = component.GetZDO(); zDO.Set("BelowTheKeel.deepSeconds", reset ? 0f : (zDO.GetFloat("BelowTheKeel.deepSeconds", 0f) + 30f)); } } private static bool RawHit(ulong shipId, long slot) { float num = Plugin.MinutesBetween.Value * 60f / 30f; float num2 = 1f / num; if (EnvMan.IsNight()) { num2 *= Plugin.NightFactor.Value; } return (float)Hash(shipId, slot, 1u) / 4.2949673E+09f < num2; } private static ZDO ShipZdo(Ship ship) { ZNetView component = ((Component)ship).GetComponent<ZNetView>(); if (!((Object)(object)component != (Object)null) || !component.IsValid()) { return null; } return component.GetZDO(); } internal static ulong ShipId(Ship ship) { ZDO val = ShipZdo(ship); if (val == null) { return 0uL; } return (ulong)((((ZDOID)(ref val.m_uid)).UserID * -7046029254386353131L) ^ ((ZDOID)(ref val.m_uid)).ID); } internal static uint Hash(ulong a, long b, uint salt) { ulong num = a ^ (ulong)(b * -4658895280553007687L) ^ (ulong)(salt * -7723592293110705685L); num ^= num >> 30; num *= 13787848793156543929uL; num ^= num >> 27; num *= 10723151780598845931uL; num ^= num >> 31; return (uint)num; } } internal sealed class Hands : MonoBehaviour { private sealed class Arm { public Transform Upper; public Transform Fore; public Transform Hand; public List<Transform[]> Fingers = new List<Transform[]>(); public Transform[] Thumb; public float Side; } private const float Seconds = 60f; private const float HandApart = 0.26f; private const float Lean = 6f; private const float BodyTilt = 0f; private const float StandBack = 0.42f; private const float RailBelowFeet = 1.05f; private const float HeadDown = 22f; private static Hands _current; internal static bool Markers; private Transform _holder; private Transform _spine; private Transform _neck; private Transform _head; private Vector3 _railLeft; private Vector3 _railRight; private Vector3 _outLocal; private Vector3 _out; private readonly Dictionary<Transform, Quaternion> _rest = new Dictionary<Transform, Quaternion>(); private readonly List<Renderer> _hidden = new List<Renderer>(); private float _age; private readonly List<Arm> _arms = new List<Arm>(); internal static string Show(Player player, Ship ship, float raise = 0f, float further = 0f) { //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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_0099: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_current != (Object)null) { Object.Destroy((Object)(object)((Component)_current).gameObject); } Vector3 forward = ((Component)player).transform.forward; forward.y = 0f; ((Vector3)(ref forward)).Normalize(); if (!FindRail(((Component)player).transform.position, forward, out var top, out var dist)) { return "No gunwale found in front of you: stand at the ship's side, facing over it."; } GameObject val = new GameObject("BelowTheKeel_Hands"); Vector3 val2 = ((Component)player).transform.position + forward * (dist - 0.42f); val2.y = top - 1.05f; val.transform.SetPositionAndRotation(val2, Quaternion.LookRotation(forward)); val.transform.SetParent(((Component)ship).transform, true); Hands hands = val.AddComponent<Hands>(); Visuals.Track(val, 61f); string text = hands.Build(player, ((Component)ship).transform, forward, top + raise, 0.42f + further); if (text != null) { Object.Destroy((Object)(object)val); return text; } _current = hands; hands.LateUpdate(); Vector3 val3 = ((Component)player).transform.InverseTransformPoint(hands.Eye()); return $"Hands on the rail for a minute. Camera at the eyes: view here {val3.x:0.00} {val3.y:0.00} {val3.z:0.00} 0 <pitch>"; } private static bool FindRail(Vector3 feet, Vector3 fwd, out float top, out float dist) { //IL_0016: 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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) top = float.NegativeInfinity; dist = -1f; for (float num = 0.2f; num <= 1.6f; num += 0.03f) { if (!(dist < 0f)) { break; } if (HighestAt(feet, fwd, num, feet.y + 0.3f, feet.y + 1.2f) > float.NegativeInfinity) { dist = num; } } if (dist < 0f) { return false; } for (float num2 = dist; num2 <= dist + 0.35f; num2 += 0.03f) { top = Mathf.Max(top, HighestAt(feet, fwd, num2, feet.y + 0.3f, feet.y + 1.2f)); } return true; } private static float HighestAt(Vector3 feet, Vector3 fwd, float d, float min, float max) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_0068: 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) float num = float.NegativeInfinity; RaycastHit[] array = Physics.RaycastAll(feet + fwd * d + Vector3.up * 2.5f, Vector3.down, 3.5f); for (int i = 0; i < array.Length; i++) { RaycastHit val = array[i]; if (!((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Player>() != (Object)null) && ((RaycastHit)(ref val)).point.y > min && ((RaycastHit)(ref val)).point.y < max) { num = Mathf.Max(num, ((RaycastHit)(ref val)).point.y); } } return num; } private string Build(Player player, Transform ship, Vector3 fwd, float railY, float railDist) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0190: 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_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: 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_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04ed: Unknown result type (might be due to invalid IL or missing references) //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Unknown result type (might be due to invalid IL or missing references) //IL_050a: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_0543: Unknown result type (might be due to invalid IL or missing references) //IL_054d: Unknown result type (might be due to invalid IL or missing references) _out = fwd; _outLocal = ship.InverseTransformDirection(fwd); Vector3 val = Vector3.Cross(Vector3.up, fwd); Vector3 val2 = ((Component)this).transform.position + fwd * (railDist + 0.04f); _railLeft = ship.InverseTransformPoint(new Vector3(val2.x, railY, val2.z) - val * 0.26f); _railRight = ship.InverseTransformPoint(new Vector3(val2.x, railY, val2.z) + val * 0.26f); GameObject look = Visuals.CloneLook("Player", ((Component)this).transform); if ((Object)(object)look == (Object)null) { return "Couldn't copy the player model."; } Animator[] componentsInChildren = look.GetComponentsInChildren<Animator>(true); foreach (Animator val3 in componentsInChildren) { ((Behaviour)val3).enabled = false; } Renderer[] componentsInChildren2 = look.GetComponentsInChildren<Renderer>(true); foreach (Renderer val4 in componentsInChildren2) { if (!(val4 is SkinnedMeshRenderer) && !(val4 is MeshRenderer)) { val4.enabled = false; } } _holder = new GameObject("Holder").transform; _holder.SetParent(((Component)this).transform, false); look.transform.SetParent(_holder, false); look.transform.localPosition = Vector3.zero; look.transform.localRotation = Quaternion.identity; Transform val5 = Find(look.transform, "LeftFoot"); Transform val6 = Find(look.transform, "LeftToeBase"); if ((Object)(object)val5 != (Object)null && (Object)(object)val6 != (Object)null) { Vector3 val7 = val6.position - val5.position; val7.y = 0f; if (((Vector3)(ref val7)).sqrMagnitude > 1E-06f) { look.transform.localRotation = Quaternion.FromToRotation(_holder.InverseTransformDirection(((Vector3)(ref val7)).normalized), Vector3.forward); } } _spine = B("Spine1"); B("Spine2"); _neck = B("Neck"); _head = B("Head"); string[] array = new string[2] { "Left", "Right" }; foreach (string text in array) { Arm arm = new Arm { Upper = B(text + "Arm"), Fore = B(text + "ForeArm"), Hand = B(text + "Hand"), Side = ((text == "Left") ? (-1f) : 1f) }; if ((Object)(object)arm.Upper == (Object)null || (Object)(object)arm.Fore == (Object)null || (Object)(object)arm.Hand == (Object)null) { return "The player model is missing arm bones."; } string[] array2 = new string[4] { "Index", "Middle", "Ring", "Pinky" }; foreach (string text2 in array2) { Transform[] array3 = (Transform[])(object)new Transform[3] { B(text + "Hand" + text2 + "1"), B(text + "Hand" + text2 + "2"), B(text + "Hand" + text2 + "3") }; if ((Object)(object)array3[0] != (Object)null && (Object)(object)array3[1] != (Object)null && (Object)(object)array3[2] != (Object)null) { arm.Fingers.Add(array3); } } arm.Thumb = (Transform[])(object)new Transform[3] { B(text + "HandThumb1"), B(text + "HandThumb2"), B(text + "HandThumb3") }; _arms.Add(arm); } if ((Object)(object)_spine == (Object)null || (Object)(object)_head == (Object)null) { return "The player model is missing spine or head bones."; } if (Markers) { Vector3[] array4 = (Vector3[])(object)new Vector3[2] { _railLeft, _railRight }; foreach (Vector3 localPosition in array4) { GameObject val8 = GameObject.CreatePrimitive((PrimitiveType)3); Object.Destroy((Object)(object)val8.GetComponent<Collider>()); val8.transform.SetParent(ship, false); val8.transform.localPosition = localPosition; val8.transform.localScale = Vector3.one * 0.06f; val8.GetComponent<Renderer>().sharedMaterial = Look.Rope(); val8.transform.SetParent(((Component)this).transform, true); } } Renderer[] componentsInChildren3 = ((Component)player).GetComponentsInChildren<Renderer>(); foreach (Renderer val9 in componentsInChildren3) { if (val9.enabled) { val9.enabled = false; _hidden.Add(val9); } } return null; Transform B(string name) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) Transform val10 = Find(look.transform, name); if ((Object)(object)val10 != (Object)null) { _rest[val10] = val10.localRotation; } return val10; } } internal Vector3 Eye() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) return _neck.position + Vector3.up * 0.17f + _out * 0.08f; } private void LateUpdate() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017f: 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_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: 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_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01df: 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_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0229: 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_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) _age += Time.deltaTime; if (_age > 60f) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } foreach (KeyValuePair<Transform, Quaternion> item in _rest) { item.Key.localRotation = item.Value; } Transform parent = ((Component)this).transform.parent; if ((Object)(object)parent == (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } _out = parent.TransformDirection(_outLocal); Vector3 val = Vector3.Cross(parent.up, _out); Vector3 normalized = ((Vector3)(ref val)).normalized; _holder.localRotation = Quaternion.Euler(0f, 0f, 0f); _spine.rotation = Quaternion.AngleAxis(6f, normalized) * _spine.rotation; _head.rotation = Quaternion.AngleAxis(22f, normalized) * _head.rotation; _neck.localScale = Vector3.one * 0.001f; foreach (Arm arm in _arms) { Vector3 val2 = parent.TransformPoint((arm.Side < 0f) ? _railLeft : _railRight); Vector3 wrist = val2 - _out * 0.02f + Vector3.up * 0.07f; SolveArm(arm, wrist, normalized); Point(arm.Hand, (arm.Fingers.Count > 1) ? arm.Fingers[1][0] : null, _out - Vector3.up * 0.35f); PalmDown(arm); foreach (Transform[] finger in arm.Fingers) { Point(finger[0], finger[1], _out - Vector3.up * 0.25f); Point(finger[1], finger[2], _out * 0.3f - Vector3.up); Point(finger[2], (finger[2].childCount > 0) ? finger[2].GetChild(0) : null, -_out * 0.4f - Vector3.up); } if ((Object)(object)arm.Thumb[0] != (Object)null && (Object)(object)arm.Thumb[1] != (Object)null && (Object)(object)arm.Thumb[2] != (Object)null) { Point(arm.Thumb[0], arm.Thumb[1], -normalized * arm.Side * 0.6f + _out * 0.3f - Vector3.up * 0.6f); Point(arm.Thumb[1], arm.Thumb[2], _out * 0.2f - Vector3.up); } } } private static void PalmDown(Arm arm) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if (arm.Fingers.Count >= 4) { Vector3 val = arm.Fingers[1][0].position - arm.Hand.position; Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 val2 = arm.Fingers[3][0].position - arm.Fingers[0][0].position; val = Vector3.Cross(normalized, val2); Vector3 val3 = ((Vector3)(ref val)).normalized * (0f - arm.Side); Vector3 val4 = Vector3.ProjectOnPlane(Vector3.down, normalized); if (!(((Vector3)(ref val3)).sqrMagnitude < 1E-06f) && !(((Vector3)(ref val4)).sqrMagnitude < 1E-06f)) { float num = Vector3.SignedAngle(val3, ((Vector3)(ref val4)).normalized, normalized); arm.Hand.rotation = Quaternion.AngleAxis(num, normalized) * arm.Hand.rotation; } } } private static void SolveArm(Arm arm, Vector3 wrist, Vector3 side) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //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_00d3: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) Vector3 position = arm.Upper.position; float num = Vector3.Distance(arm.Upper.position, arm.Fore.position); float num2 = Vector3.Distance(arm.Fore.position, arm.Hand.position); Vector3 val = wrist - position; float num3 = Mathf.Clamp(((Vector3)(ref val)).magnitude, Mathf.Abs(num - num2) + 0.001f, num + num2 - 0.001f); Vector3 normalized = ((Vector3)(ref val)).normalized; float num4 = Mathf.Acos(Mathf.Clamp((num * num + num3 * num3 - num2 * num2) / (2f * num * num3), -1f, 1f)); Vector3 val2 = side * arm.Side + Vector3.down * 0.6f; Vector3 normalized2 = ((Vector3)(ref val2)).normalized; val2 = Vector3.Cross(normalized, normalized2); Vector3 normalized3 = ((Vector3)(ref val2)).normalized; Vector3 val3 = position + Quaternion.AngleAxis((0f - num4) * 57.29578f, normalized3) * normalized * num; Point(arm.Upper, arm.Fore, val3 - position); Point(arm.Fore, arm.Hand, wrist - arm.Fore.position); } private static void Point(Transform bone, Transform child, Vector3 want) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0044: 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_0050: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)bone == (Object)null) && !((Object)(object)child == (Object)null)) { Vector3 val = child.position - bone.position; if (!(((Vector3)(ref val)).sqrMagnitude < 1E-10f) && !(((Vector3)(ref want)).sqrMagnitude < 1E-08f)) { bone.rotation = Quaternion.FromToRotation(val, want) * bone.rotation; } } } private static Transform Find(Transform root, string name) { Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == name) { return val; } } return null; } private void OnDestroy() { foreach (Renderer item in _hidden) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } _hidden.Clear(); if ((Object)(object)_current == (Object)(object)this) { _current = null; } } } internal static class Look { private static Material _darkSerpent; private static readonly Dictionary<Material, Material> _drowned = new Dictionary<Material, Material>(); private static Material _rope; private static Material _hide; private static Material _eye; private static Texture2D _eyeAlbedo; private static Texture2D _eyeGlow; private static Material _eyeFire; private static Texture2D _fireAlbedo; private static Texture2D _fireGlow; private static Material _wood; internal static Material DarkSerpent() { //IL_0074: 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_007e: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_darkSerpent != (Object)null) { return _darkSerpent; } Material val = null; GameObject val2 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("Serpent") : null); SkinnedMeshRenderer val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponentInChildren<SkinnedMeshRenderer>(true) : null); if ((Object)(object)val3 != (Object)null) { val = ((Renderer)val3).sharedMaterial; } _darkSerpent = (((Object)(object)val != (Object)null) ? new Material(val) : new Material(FindShader("Custom/Creature"))); ((Object)_darkSerpent).name = "BelowTheKeel_DarkSerpent"; _darkSerpent.color = new Color(0.05f, 0.06f, 0.07f); return _darkSerpent; } internal static Material Drowned(Material source) { //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_0042: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source == (Object)null) { return null; } if (_drowned.TryGetValue(source, out var value) && (Object)(object)value != (Object)null) { return value; } value = new Material(source) { name = "BelowTheKeel_Drowned_" + ((Object)source).name }; value.color = new Color(0.22f, 0.27f, 0.25f); _drowned[source] = value; return value; } internal static Material Rope() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_005a: Expected O, but got Unknown if ((Object)(object)_rope != (Object)null) { return _rope; } _rope = new Material(FindShader("Custom/Creature") ?? FindShader("Legacy Shaders/Diffuse")) { name = "BelowTheKeel_Rope", color = new Color(0.12f, 0.1f, 0.07f) }; return _rope; } internal static Material DarkHide() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_hide != (Object)null) { return _hide; } _hide = new Material(DarkSerpent()) { name = "BelowTheKeel_DarkHide" }; if (_hide.HasProperty("_EmissionColor")) { _hide.SetColor("_EmissionColor", Color.black); } return _hide; } internal static Material Eye() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_eye != (Object)null) { return _eye; } EyeMeshes.Draw(out _eyeAlbedo, out _eyeGlow); _eye = new Material(DarkSerpent()) { name = "BelowTheKeel_Eye", color = Color.white }; _eye.SetTexture("_MainTex", (Texture)(object)_eyeAlbedo); _eye.SetTexture("_EmissionMap", (Texture)(object)_eyeGlow); _eye.SetColor("_EmissionColor", new Color(3f, 3f, 3f)); if (_eye.HasProperty("_BumpMap")) { _eye.SetTexture("_BumpMap", (Texture)null); } return _eye; } internal static Material EyeFire() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_eyeFire != (Object)null) { return _eyeFire; } EyeMeshes.DrawFire(out _fireAlbedo, out _fireGlow); _eyeFire = new Material(DarkSerpent()) { name = "BelowTheKeel_EyeFire", color = Color.white }; _eyeFire.SetTexture("_MainTex", (Texture)(object)_fireAlbedo); _eyeFire.SetTexture("_EmissionMap", (Texture)(object)_fireGlow); _eyeFire.SetColor("_EmissionColor", new Color(2.2f, 2.2f, 2.2f)); if (_eyeFire.HasProperty("_BumpMap")) { _eyeFire.SetTexture("_BumpMap", (Texture)null); } return _eyeFire; } internal static Material Wood() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_wood != (Object)null) { return _wood; } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("shipwreck_karve_stern") : null); MeshRenderer val2 = (((Object)(object)val != (Object)null) ? val.GetComponentInChildren<MeshRenderer>(true) : null); _wood = (((Object)(object)val2 != (Object)null) ? new Material(((Renderer)val2).sharedMaterial) : new Material(FindShader("Custom/Piece") ?? FindShader("Legacy Shaders/Diffuse"))); ((Object)_wood).name = "BelowTheKeel_Wood"; return _wood; } internal static Shader FindShader(string name) { Shader[] array = Resources.FindObjectsOfTypeAll<Shader>(); foreach (Shader val in array) { if (((Object)val).name == name) { return val; } } return null; } internal static void Forget() { if ((Object)(object)_darkSerpent != (Object)null) { Object.Destroy((Object)(object)_darkSerpent); } _darkSerpent = null; foreach (Material value in _drowned.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } _drowned.Clear(); if ((Object)(object)_rope != (Object)null) { Object.Destroy((Object)(object)_rope); } _rope = null; if ((Object)(object)_wood != (Object)null) { Object.Destroy((Object)(object)_wood); } _wood = null; if ((Object)(object)_eye != (Object)null) { Object.Destroy((Object)(object)_eye); } if ((Object)(object)_eyeFire != (Object)null) { Object.Destroy((Object)(object)_eyeFire); } if ((Object)(object)_fireAlbedo != (Object)null) { Object.Destroy((Object)(object)_fireAlbedo); } if ((Object)(object)_fireGlow != (Object)null) { Object.Destroy((Object)(object)_fireGlow); } _eyeFire = null; _fireAlbedo = (_fireGlow = null); if ((Object)(object)_hide != (Object)null) { Object.Destroy((Object)(object)_hide); } _hide = null; if ((Object)(object)_eyeAlbedo != (Object)null) { Object.Destroy((Object)(object)_eyeAlbedo); } if ((Object)(object)_eyeGlow != (Object)null) { Object.Destroy((Object)(object)_eyeGlow); } _eye = null; _eyeAlbedo = (_eyeGlow = null); } } internal sealed class EyeOmen : Omen { internal const float Width = 36f; internal static float FreezeAt = -1f; internal static bool Classic; internal static bool Show; internal override string Name => "eye"; protected override ConfigEntry<bool> Setting => Plugin.Eye; internal override void Play(Ship ship, uint seed) { Play(ship, seed, 36f, float.NaN); } internal static void Play(Ship ship, uint seed, float width, float depth) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) Random random = new Random((int)seed); float num = width / 2f; if (float.IsNaN(depth)) { depth = 6.25f + (float)random.NextDouble() * 0.5f; } GameObject val = Visuals.Spawn("Eye", ((Component)ship).transform.position, Quaternion.identity, 27f); val.AddComponent<EyeBody>().Begin(ship, num, ((random.Next(2) == 0) ? (-1f) : 1f) * num * (Show ? 11.5f : (1.15f + (float)random.NextDouble() *