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 HatLib v0.0.3
HatLib.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Dawn; using Dusk; using GameNetcodeStuff; using HarmonyLib; using HatLib; using HatLib.NetcodePatcher; using HatLib.Patches; using HatLib.Tools; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Linq; using Unity.Collections; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("HatLib")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.0.3.0")] [assembly: AssemblyInformationalVersion("0.0.3")] [assembly: AssemblyProduct("HatLib")] [assembly: AssemblyTitle("HatLib")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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; } } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("MrHat.Lib", "HatLib", "0.0.3")] internal class Plugin : BaseUnityPlugin { internal const string modGUID = "MrHat.Lib"; internal const string modName = "HatLib"; internal const string modVersion = "0.0.3"; private const string DawnLibGUID = "com.github.teamxiaolan.dawnlib"; private const string DuskGUID = "com.github.teamxiaolan.dawnlib.dusk"; private readonly Harmony _harmony = new Harmony("MrHat.Lib"); internal static ManualLogSource mls; internal static Plugin instance; private void Awake() { instance = this; mls = Logger.CreateLogSource("MrHat.Lib"); ConfigManager.Bind(((BaseUnityPlugin)this).Config); _harmony.PatchAll(typeof(GameNetworkManagerPatches)); _harmony.PatchAll(typeof(StartOfRoundPatches)); mls.LogInfo((object)"HatLib loaded"); } } namespace HatLib { internal static class ConfigManager { internal static ConfigEntry<bool>? DebugLogs { get; private set; } internal static void Bind(ConfigFile config) { DebugLogs = config.Bind<bool>("Internal", "Debug Logs", false, "If true, allows debug logging"); } } internal static class Log { internal static void Debug(string message) { if (ConfigManager.DebugLogs.Value) { Write((LogLevel)32, message); } } internal static void Info(string message) { Write((LogLevel)16, message); } internal static void Warn(string message) { Write((LogLevel)4, message); } internal static void Error(string message) { Write((LogLevel)2, message); } internal static void Fatal(string message) { Write((LogLevel)1, message); } private static void Write(LogLevel logLevel, string message) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Plugin.mls.Log(logLevel, (object)message); } } public class RoundEvents { public static event Action<StartOfRound>? OnRoundStart; public static event Action<StartOfRound>? OnRoundEnd; public static event Action<StartOfRound>? OnShipLeft; public static event Action<StartOfRound>? OnShipReadyToLand; public static event Action<StartOfRound>? OnShipItemsLoaded; public static event Action<StartOfRound>? OnShipUnlockablesSynced; public static event Action<StartOfRound>? OnPlayersLoadedReset; public static event Action<StartOfRound>? OnLocalDisconnect; public static event Action<StartOfRound>? OnDestroy; public static event Action? OnGameSaved; private RoundEvents() { } internal static void RoundStart(StartOfRound startOfRound) { RoundEvents.OnRoundStart?.Invoke(startOfRound); } internal static void RoundEnd(StartOfRound startOfRound) { RoundEvents.OnRoundEnd?.Invoke(startOfRound); } internal static void ShipLeft(StartOfRound startOfRound) { RoundEvents.OnShipLeft?.Invoke(startOfRound); } internal static void ShipReadyToLand(StartOfRound startOfRound) { RoundEvents.OnShipReadyToLand?.Invoke(startOfRound); } internal static void ShipItemsLoaded(StartOfRound startOfRound) { RoundEvents.OnShipItemsLoaded?.Invoke(startOfRound); } internal static void ShipUnlockablesSynced(StartOfRound startOfRound) { RoundEvents.OnShipUnlockablesSynced?.Invoke(startOfRound); } internal static void PlayersLoadedReset(StartOfRound startOfRound) { RoundEvents.OnPlayersLoadedReset?.Invoke(startOfRound); } internal static void Disconnect(StartOfRound startOfRound) { RoundEvents.OnLocalDisconnect?.Invoke(startOfRound); } internal static void Destroy(StartOfRound startOfRound) { RoundEvents.OnDestroy?.Invoke(startOfRound); } internal static void GameSaved() { RoundEvents.OnGameSaved?.Invoke(); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "HatLib"; public const string PLUGIN_NAME = "HatLib"; public const string PLUGIN_VERSION = "0.0.3"; } } namespace HatLib.Tools { public static class AudioTools { public static bool PlayOneShot(AudioSource? source, AudioClip? clip) { if ((Object)(object)source == (Object)null || (Object)(object)clip == (Object)null) { return false; } source.PlayOneShot(clip); return true; } public static bool Load(AudioClip? clip) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 if ((Object)(object)clip == (Object)null || (int)clip.loadState > 0) { return false; } return clip.LoadAudioData(); } public static bool Unload(AudioClip? clip) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 if ((Object)(object)clip == (Object)null || (int)clip.loadState != 2) { return false; } return clip.UnloadAudioData(); } public static bool SwapClip(AudioSource? source, AudioClip? clip, bool play) { if ((Object)(object)source == (Object)null) { return false; } source.clip = clip; if (play && (Object)(object)clip != (Object)null) { source.Play(); } return true; } public static bool Stop(AudioSource? source, bool zeroVolume = false) { if ((Object)(object)source == (Object)null) { return false; } if (zeroVolume) { source.volume = 0f; } source.Stop(); return true; } public static int StopMany(bool zeroVolume = false, params AudioSource?[] sources) { if (sources == null) { return 0; } int num = 0; for (int i = 0; i < sources.Length; i++) { if (Stop(sources[i], zeroVolume)) { num++; } } return num; } } public static class CoroutineTools { public static bool Start(MonoBehaviour owner, ref Coroutine? handle, IEnumerator job) { if ((Object)(object)owner == (Object)null || job == null || handle != null) { return false; } handle = owner.StartCoroutine(job); return true; } public static bool Stop(MonoBehaviour owner, ref Coroutine? handle) { if ((Object)(object)owner == (Object)null || handle == null) { return false; } owner.StopCoroutine(handle); handle = null; return true; } public static bool Restart(MonoBehaviour owner, ref Coroutine? handle, IEnumerator job) { Stop(owner, ref handle); return Start(owner, ref handle, job); } public static Coroutine? NextFrame(MonoBehaviour owner, Action action) { if ((Object)(object)owner == (Object)null || action == null) { return null; } return owner.StartCoroutine(NextFrameWait(action)); } public static Coroutine? Delay(MonoBehaviour owner, float seconds, Action action) { if ((Object)(object)owner == (Object)null || action == null) { return null; } return owner.StartCoroutine(DelayWait(seconds, action)); } private static IEnumerator NextFrameWait(Action action) { yield return null; action(); } private static IEnumerator DelayWait(float seconds, Action action) { yield return (object)new WaitForSeconds(seconds); action(); } } public static class DawnSaveData { public static bool ReadText(NamespacedKey key, out string? raw) { raw = string.Empty; PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Debug($"Dawn save missing for {key}; no save open"); return false; } if (!((DataContainer)currentContract).TryGet<string>(key, ref raw)) { Log.Debug($"Dawn save missing for {key}"); return false; } Log.Debug($"Dawn save read for {key}"); return true; } public static bool SaveText(NamespacedKey key, string raw) { return Save(key, raw); } public static bool Read<T>(NamespacedKey key, out T? value) { value = default(T); PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Debug($"Dawn save missing for {key}; no save open"); return false; } if (!((DataContainer)currentContract).TryGet<T>(key, ref value)) { Log.Debug($"Dawn save missing for {key}"); return false; } Log.Debug($"Dawn save read for {key}"); return true; } public static bool Save<T>(NamespacedKey key, T value) { if (value == null) { Log.Warn($"Dawn save skipped for {key}; value was null"); return false; } if (!CanSave()) { Log.Debug($"Dawn save skipped for {key}; host only"); return false; } PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Warn($"Dawn save skipped for {key}; no save open"); return false; } using (((DataContainer)currentContract).CreateEditContext()) { ((DataContainer)currentContract).Set<T>(key, value); } Log.Debug($"Dawn save saved for {key}"); return true; } public static bool ReadJson(NamespacedKey parentKey, NamespacedKey childKey, out JObject? value) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown value = new JObject(); PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Debug($"Dawn save missing for {parentKey}/{childKey}; no save open"); return false; } ChildPersistentDataContainer val = default(ChildPersistentDataContainer); if (!((DataContainer)currentContract).TryGet<ChildPersistentDataContainer>(parentKey, ref val)) { Log.Debug($"Dawn save group missing for {parentKey}"); return false; } if (!((DataContainer)val).TryGet<JObject>(childKey, ref value)) { Log.Debug($"Dawn save JSON missing for {parentKey}/{childKey}"); return false; } Log.Debug($"Dawn save JSON read for {parentKey}/{childKey}"); return true; } public static bool SaveJson(NamespacedKey parentKey, NamespacedKey childKey, JObject value) { return Save<JObject>(parentKey, childKey, value); } public static bool Read<T>(NamespacedKey parentKey, NamespacedKey childKey, out T? value) { value = default(T); PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Debug($"Dawn save missing for {parentKey}/{childKey}; no save open"); return false; } ChildPersistentDataContainer val = default(ChildPersistentDataContainer); if (!((DataContainer)currentContract).TryGet<ChildPersistentDataContainer>(parentKey, ref val)) { Log.Debug($"Dawn save group missing for {parentKey}"); return false; } if (!((DataContainer)val).TryGet<T>(childKey, ref value)) { Log.Debug($"Dawn save missing for {parentKey}/{childKey}"); return false; } Log.Debug($"Dawn save read for {parentKey}/{childKey}"); return true; } public static bool Save<T>(NamespacedKey parentKey, NamespacedKey childKey, T value) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown if (value == null) { Log.Warn($"Dawn save skipped for {parentKey}/{childKey}; value was null"); return false; } if (!CanSave()) { Log.Debug($"Dawn save skipped for {parentKey}/{childKey}; host only"); return false; } PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Warn($"Dawn save skipped for {parentKey}/{childKey}; no save open"); return false; } using (((DataContainer)currentContract).CreateEditContext()) { ChildPersistentDataContainer val = default(ChildPersistentDataContainer); if (!((DataContainer)currentContract).TryGet<ChildPersistentDataContainer>(parentKey, ref val)) { val = new ChildPersistentDataContainer(currentContract); ((DataContainer)currentContract).Set<ChildPersistentDataContainer>(parentKey, val); Log.Debug($"Dawn save group created for {parentKey}"); } ((DataContainer)val).Set<T>(childKey, value); } Log.Debug($"Dawn save saved for {parentKey}/{childKey}"); return true; } public static bool Remove(NamespacedKey key) { if (!CanSave()) { Log.Debug($"Dawn save remove skipped for {key}; host only"); return false; } PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Warn($"Dawn save remove skipped for {key}; no save open"); return false; } using (((DataContainer)currentContract).CreateEditContext()) { ((DataContainer)currentContract).Remove(key); } Log.Debug($"Dawn save removed for {key}"); return true; } public static bool Remove(NamespacedKey parentKey, NamespacedKey childKey, bool removeGroupWhenEmpty = false) { if (!CanSave()) { Log.Debug($"Dawn save remove skipped for {parentKey}/{childKey}; host only"); return false; } PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Warn($"Dawn save remove skipped for {parentKey}/{childKey}; no save open"); return false; } using (((DataContainer)currentContract).CreateEditContext()) { ChildPersistentDataContainer val = default(ChildPersistentDataContainer); if (!((DataContainer)currentContract).TryGet<ChildPersistentDataContainer>(parentKey, ref val)) { Log.Debug($"Dawn save group missing for {parentKey}"); return false; } ((DataContainer)val).Remove(childKey); Log.Debug($"Dawn save removed for {parentKey}/{childKey}"); if (removeGroupWhenEmpty && ((DataContainer)val).Count == 0) { ((DataContainer)currentContract).Remove(parentKey); Log.Debug($"Dawn save group removed for {parentKey}"); } } return true; } private static bool CanSave() { NetworkManager singleton = NetworkManager.Singleton; return singleton != null && singleton.IsServer; } } public class DawnSaveSync { private const float DelaySeconds = 1.25f; private static readonly WaitForSeconds DelayWait = new WaitForSeconds(1.25f); private readonly NamespacedKey dataKey; private readonly NamespacedKey requestKey; private readonly Func<string> saveData; private readonly Action<string> acceptData; private readonly bool saveOnGameSaved; private Coroutine? hostCoroutine; private Coroutine? clientCoroutine; private MonoBehaviour? hostOwner; private MonoBehaviour? clientOwner; private string rawData = string.Empty; private bool dataReceived; private bool listening; private bool HostRestoreFinished { get; set; } = true; private bool ClientDelayFinished { get; set; } public static DawnSaveSync Bind(NamespacedKey dataKey, Func<string> saveData, Action<string> acceptData, bool saveOnGameSaved = true) { DawnSaveSync dawnSaveSync = new DawnSaveSync(dataKey, saveData, acceptData, saveOnGameSaved); dawnSaveSync.Enable(); return dawnSaveSync; } public DawnSaveSync(NamespacedKey dataKey, Func<string> saveData, Action<string> acceptData, bool saveOnGameSaved = true) { this.dataKey = dataKey ?? throw new ArgumentNullException("dataKey"); requestKey = RequestKey(dataKey); this.saveData = saveData ?? throw new ArgumentNullException("saveData"); this.acceptData = acceptData ?? throw new ArgumentNullException("acceptData"); this.saveOnGameSaved = saveOnGameSaved; } public void Enable() { if (listening) { Log.Debug($"Dawn save sync already enabled for {dataKey}"); return; } listening = true; HatNet.Init(); HatNet.AddClientHandler(dataKey, DataReceived); HatNet.AddServerHandler(requestKey, RequestReceived); RoundEvents.OnShipItemsLoaded += ShipItemsLoaded; RoundEvents.OnShipUnlockablesSynced += ShipUnlockablesSynced; RoundEvents.OnLocalDisconnect += Clear; RoundEvents.OnDestroy += Clear; if (saveOnGameSaved) { RoundEvents.OnGameSaved += SaveGame; } Log.Debug($"Dawn save sync enabled for {dataKey}"); } public void Disable() { if (!listening) { Log.Debug($"Dawn save sync already disabled for {dataKey}"); return; } listening = false; HatNet.RemoveClientHandler(dataKey, DataReceived); HatNet.RemoveServerHandler(requestKey, RequestReceived); RoundEvents.OnShipItemsLoaded -= ShipItemsLoaded; RoundEvents.OnShipUnlockablesSynced -= ShipUnlockablesSynced; RoundEvents.OnLocalDisconnect -= Clear; RoundEvents.OnDestroy -= Clear; RoundEvents.OnGameSaved -= SaveGame; Clear(); Log.Debug($"Dawn save sync disabled for {dataKey}"); } public bool Save() { return Save(saveData() ?? string.Empty); } public bool Save(string data) { if (!HostRestoreFinished) { Log.Debug($"Dawn save sync save skipped for {dataKey}; restore running"); return false; } string raw = data ?? string.Empty; if (!DawnSaveData.SaveText(dataKey, raw)) { return false; } rawData = raw; dataReceived = true; Log.Debug($"Dawn save sync saved for {dataKey}"); return true; } public bool SaveAndPublish() { if (!Save()) { return false; } if (PublishRaw(rawData)) { Log.Debug($"Dawn save sync saved and sent for {dataKey}"); return true; } Log.Warn($"Dawn save sync saved but not sent for {dataKey}"); return false; } public bool Remove() { if (!HostRestoreFinished) { Log.Debug($"Dawn save sync remove skipped for {dataKey}; restore running"); return false; } if (!DawnSaveData.Remove(dataKey)) { return false; } rawData = string.Empty; dataReceived = true; Log.Debug($"Dawn save sync removed for {dataKey}"); return true; } public bool Publish() { if (HostRestoreFinished) { NetworkManager singleton = NetworkManager.Singleton; if (singleton != null && singleton.IsServer) { rawData = saveData() ?? string.Empty; dataReceived = true; if (PublishRaw(rawData)) { Log.Debug($"Dawn save sync sent for {dataKey}"); return true; } Log.Warn($"Dawn save sync send failed for {dataKey}"); return false; } } Log.Debug($"Dawn save sync send skipped for {dataKey}"); return false; } public bool Request() { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null || !singleton.IsListening) { Log.Debug($"Dawn save sync request skipped for {dataKey}; networking unavailable"); return false; } if (HatNet.SendToServer(requestKey, string.Empty)) { Log.Debug($"Dawn save sync requested for {dataKey}"); return true; } Log.Warn($"Dawn save sync request failed for {dataKey}"); return false; } internal void Clear() { StopHostCoroutine(); StopClientCoroutine(); HostRestoreFinished = true; ClientDelayFinished = false; rawData = string.Empty; dataReceived = false; Log.Debug($"Dawn save sync cleared for {dataKey}"); } private static NamespacedKey RequestKey(NamespacedKey key) { return NamespacedKey.From(key.Namespace, key.Key + "_request"); } private void SaveGame() { Save(); } private void ShipItemsLoaded(StartOfRound startOfRound) { NetworkManager singleton = NetworkManager.Singleton; if (singleton != null && singleton.IsServer) { StopHostCoroutine(); HostRestoreFinished = false; hostOwner = (MonoBehaviour?)(object)startOfRound; hostCoroutine = ((MonoBehaviour)startOfRound).StartCoroutine(HostRestoreAfterDelay()); Log.Debug($"Dawn save sync restore scheduled for {dataKey}"); } } private void ShipUnlockablesSynced(StartOfRound startOfRound) { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null || !singleton.IsServer) { StopClientCoroutine(); ClientDelayFinished = false; clientOwner = (MonoBehaviour?)(object)startOfRound; clientCoroutine = ((MonoBehaviour)startOfRound).StartCoroutine(ClientRestoreAfterDelay()); Log.Debug($"Dawn save sync client restore scheduled for {dataKey}"); } } private void Clear(StartOfRound startOfRound) { Clear(); } private void RequestReceived(ulong senderClientId, string data) { if (!HostRestoreFinished) { return; } NetworkManager singleton = NetworkManager.Singleton; if (singleton != null && singleton.IsServer) { rawData = saveData() ?? string.Empty; dataReceived = true; if (HatNet.SendToClient(dataKey, senderClientId, rawData)) { Log.Debug($"Dawn save sync request answered for {dataKey}"); } } } private void DataReceived(ulong senderClientId, string data) { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null || !singleton.IsServer) { ReceiveData(data); } } private void ReceiveData(string data) { rawData = data ?? string.Empty; dataReceived = true; Log.Debug($"Dawn save sync received for {dataKey}"); if (ClientDelayFinished) { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null || !singleton.IsServer) { acceptData(rawData); } } } private IEnumerator HostRestoreAfterDelay() { yield return DelayWait; string savedData; bool loaded = DawnSaveData.ReadText(dataKey, out savedData) && savedData != null; string savedText = (rawData = (loaded ? savedData : string.Empty)); dataReceived = true; acceptData(savedText); if (loaded) { Log.Debug($"Dawn save sync read for {dataKey}"); } else { Log.Debug($"Dawn save sync empty for {dataKey}"); } rawData = saveData() ?? string.Empty; PublishRaw(rawData); HostRestoreFinished = true; hostCoroutine = null; hostOwner = null; Log.Debug($"Dawn save sync restore finished for {dataKey}"); } private IEnumerator ClientRestoreAfterDelay() { yield return DelayWait; ClientDelayFinished = true; clientCoroutine = null; clientOwner = null; if (dataReceived) { acceptData(rawData); Log.Debug($"Dawn save sync client data accepted for {dataKey}"); } else { Request(); } } private bool PublishRaw(string data) { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null || !singleton.IsServer) { return false; } return HatNet.SendToClients(dataKey, data ?? string.Empty); } private void StopHostCoroutine() { if (hostCoroutine != null && !((Object)(object)hostOwner == (Object)null)) { hostOwner.StopCoroutine(hostCoroutine); hostCoroutine = null; hostOwner = null; Log.Debug($"Dawn save sync restore stopped for {dataKey}"); } } private void StopClientCoroutine() { if (clientCoroutine != null && !((Object)(object)clientOwner == (Object)null)) { clientOwner.StopCoroutine(clientCoroutine); clientCoroutine = null; clientOwner = null; Log.Debug($"Dawn save sync client restore stopped for {dataKey}"); } } } public static class DawnFindResource { public static void Add<TInfo>(Registry<TInfo> registry, NamespacedKey<TInfo> key, Action<TInfo> assign) where TInfo : INamespaced<TInfo> { if (registry == null) { Log.Error($"Dawn resource registry missing for {key}"); return; } if (assign == null) { Log.Error($"Dawn resource action missing for {key}"); return; } DawnFindResource.OnFreeze<TInfo>(registry, (Action)delegate { if (DawnFindResource.Resolve<TInfo>(registry, key, out TInfo info)) { assign(info); Log.Debug($"Dawn resource assigned for {key}"); } }); Log.Debug($"Dawn resource queued for {key}"); } public static void Add<TInfo, TValue>(Registry<TInfo> registry, NamespacedKey<TInfo> key, Func<TInfo, TValue?> read, Action<TValue> assign) where TInfo : INamespaced<TInfo> where TValue : class { DawnFindResource.Add<TInfo, TValue>(registry, key, read, typeof(TValue).Name, assign); } public static void Add<TInfo, TValue>(Registry<TInfo> registry, NamespacedKey<TInfo> key, Func<TInfo, TValue?> read, string name, Action<TValue> assign) where TInfo : INamespaced<TInfo> where TValue : class { if (registry == null) { Log.Error("Dawn resource registry missing for " + name); return; } if (read == null) { Log.Error("Dawn resource reader missing for " + name); return; } if (assign == null) { Log.Error("Dawn resource action missing for " + name); return; } DawnFindResource.OnFreeze<TInfo>(registry, (Action)delegate { if (DawnFindResource.Resolve<TInfo, TValue>(registry, key, read, name, out TValue value)) { assign(value); Log.Debug("Dawn resource assigned for " + name); } }); Log.Debug("Dawn resource queued for " + name); } public static void OnFreeze<TInfo>(Registry<TInfo> registry, Action action) where TInfo : INamespaced<TInfo> { if (registry == null) { Log.Error("Dawn registry missing for " + typeof(TInfo).Name); } else if (action == null) { Log.Error("Dawn registry freeze action missing for " + typeof(TInfo).Name); } else if (registry.IsFrozen) { Log.Debug("Dawn registry already frozen for " + typeof(TInfo).Name); action(); } else { registry.OnFreeze += action; Log.Debug("Dawn registry freeze action queued for " + typeof(TInfo).Name); } } public static bool Resolve<TInfo>(Registry<TInfo> registry, NamespacedKey<TInfo> key, out TInfo info) where TInfo : INamespaced<TInfo> { info = default(TInfo); if (registry == null) { Log.Error($"Dawn resource registry missing for {key}"); return false; } if (registry.TryGetValue(key, ref info)) { Log.Debug($"Dawn resource resolved for {key}"); return true; } info = default(TInfo); Log.Warn($"Dawn resource missing for {key}"); return false; } public static bool Resolve<TInfo, TValue>(Registry<TInfo> registry, NamespacedKey<TInfo> key, Func<TInfo, TValue?> read, out TValue value) where TInfo : INamespaced<TInfo> where TValue : class { return DawnFindResource.Resolve<TInfo, TValue>(registry, key, read, typeof(TValue).Name, out value); } public static bool Resolve<TInfo, TValue>(Registry<TInfo> registry, NamespacedKey<TInfo> key, Func<TInfo, TValue?> read, string name, out TValue value) where TInfo : INamespaced<TInfo> where TValue : class { value = null; if (read == null) { Log.Error("Dawn resource reader missing for " + name); return false; } if (!DawnFindResource.Resolve<TInfo>(registry, key, out TInfo info)) { return false; } TValue val = read(info); if (Missing(val)) { Log.Warn("Dawn resource value missing for " + name); return false; } value = val; Log.Debug("Dawn resource value resolved for " + name); return true; } private static bool Missing<TValue>([NotNullWhen(false)] TValue? value) where TValue : class { if (value == null) { return true; } Object val = (Object)(object)((value is Object) ? value : null); if (val != null && val == (Object)null) { return true; } return false; } } public class DuskConfigInjector(string dawnModGUID) { public readonly string dawnModGUID = dawnModGUID; public static T Read<T>(string dawnModGUID, string settingName) { if (string.IsNullOrWhiteSpace(dawnModGUID)) { Log.Error("Dusk config mod GUID missing"); return default(T); } if (string.IsNullOrWhiteSpace(settingName)) { Log.Error("Dusk config setting name missing"); return default(T); } DuskMod val = ((IEnumerable<DuskMod>)DuskMod.AllMods).FirstOrDefault((Func<DuskMod, bool>)((DuskMod duskMod) => duskMod.Plugin.GUID == dawnModGUID)); if (val == null) { Log.Warn("Dusk mod missing for " + dawnModGUID); return default(T); } ConfigEntryBase val2 = ((IEnumerable<ConfigEntryBase>)val.ConfigEntries).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase configEntry) => configEntry.Definition.Key == settingName)); if (val2 == null) { Log.Warn("Dusk config setting missing for " + settingName); return default(T); } if (!(val2 is ConfigEntry<T> val3)) { Log.Error("Dusk config setting type mismatch for " + settingName); return default(T); } return val3.Value; } public static T Read<T>(string dawnModGUID, string section, string settingName) { if (string.IsNullOrWhiteSpace(dawnModGUID)) { Log.Error("Dusk config mod GUID missing"); return default(T); } if (string.IsNullOrWhiteSpace(section)) { Log.Error("Dusk config section missing"); return default(T); } if (string.IsNullOrWhiteSpace(settingName)) { Log.Error("Dusk config setting name missing"); return default(T); } DuskMod val = ((IEnumerable<DuskMod>)DuskMod.AllMods).FirstOrDefault((Func<DuskMod, bool>)((DuskMod duskMod) => duskMod.Plugin.GUID == dawnModGUID)); if (val == null) { Log.Warn("Dusk mod missing for " + dawnModGUID); return default(T); } ConfigEntryBase val2 = ((IEnumerable<ConfigEntryBase>)val.ConfigEntries).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase configEntry) => configEntry.Definition.Section == section && configEntry.Definition.Key == settingName)); if (val2 == null) { Log.Warn("Dusk config setting missing for " + section + "/" + settingName); return default(T); } if (!(val2 is ConfigEntry<T> val3)) { Log.Error("Dusk config setting type mismatch for " + section + "/" + settingName); return default(T); } return val3.Value; } public ConfigEntry<T>? Bind<T>(string section, string settingName, T defaultValue, string description) { if (string.IsNullOrWhiteSpace(dawnModGUID)) { Log.Error("Dusk config mod GUID missing"); return null; } if (string.IsNullOrWhiteSpace(section)) { Log.Error("Dusk config section missing"); return null; } if (string.IsNullOrWhiteSpace(settingName)) { Log.Error("Dusk config setting key missing"); return null; } DuskMod val = ((IEnumerable<DuskMod>)DuskMod.AllMods).FirstOrDefault((Func<DuskMod, bool>)((DuskMod duskMod) => duskMod.Plugin.GUID == dawnModGUID)); if (val == null) { Log.Warn("Dusk mod missing for " + dawnModGUID); return null; } ConfigContext val2 = val.ConfigManager.CreateConfigSection(section); try { return val2.Bind<T>(settingName, description, defaultValue); } finally { ((IDisposable)val2)?.Dispose(); } } } public static class FindItems { public static NamespacedKey<DawnItemInfo>? DawnKey(GrabbableObject item) { if ((Object)(object)item == (Object)null) { Log.Warn("Dawn item key missing; item was null"); return null; } if ((Object)(object)item.itemProperties == (Object)null) { Log.Warn("Dawn item key missing; item properties were null"); return null; } return ((DawnBaseInfo<DawnItemInfo>)(object)ItemExtensions.GetDawnInfo(item.itemProperties))?.TypedKey; } public static bool MatchesDawnKey(GrabbableObject item, NamespacedKey<DawnItemInfo> itemKey) { if (itemKey == null) { Log.Warn("Dawn item match skipped; item key was null"); return false; } return ((object)DawnKey(item))?.Equals((object?)itemKey) ?? false; } public static List<GrabbableObject> Active(Func<GrabbableObject, bool>? itemFilter = null) { GrabbableObject[] array = Object.FindObjectsByType<GrabbableObject>((FindObjectsInactive)0, (FindObjectsSortMode)0); List<GrabbableObject> list = new List<GrabbableObject>(); foreach (GrabbableObject val in array) { if (itemFilter == null || itemFilter(val)) { list.Add(val); } } return list; } public static List<GrabbableObject> Active(NamespacedKey<DawnItemInfo> itemKey, Func<GrabbableObject, bool>? itemFilter = null) { return Active((Func<GrabbableObject, bool>?)((GrabbableObject item) => MatchesDawnKey(item, itemKey) && (itemFilter == null || itemFilter(item)))); } public static GrabbableObject? ClosestTo(Vector3 position, float radius, Func<GrabbableObject, bool>? itemFilter = null) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) GrabbableObject[] items = Object.FindObjectsByType<GrabbableObject>((FindObjectsInactive)0, (FindObjectsSortMode)0); return ClosestTo(position, radius, items, itemFilter); } public static GrabbableObject? ClosestTo(NamespacedKey<DawnItemInfo> itemKey, Vector3 position, float radius, Func<GrabbableObject, bool>? itemFilter = null) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) GrabbableObject[] items = Object.FindObjectsByType<GrabbableObject>((FindObjectsInactive)0, (FindObjectsSortMode)0); return ClosestTo(itemKey, position, radius, items, itemFilter); } public static GrabbableObject? ClosestTo(Vector3 position, float radius, IReadOnlyList<GrabbableObject> items, Func<GrabbableObject, bool>? itemFilter = null) { //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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) float num = radius * radius; GrabbableObject result = null; for (int i = 0; i < items.Count; i++) { GrabbableObject val = items[i]; if (!((Object)(object)val == (Object)null) && (itemFilter == null || itemFilter(val))) { Vector3 val2 = ((Component)val).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude >= num)) { num = sqrMagnitude; result = val; } } } return result; } public static GrabbableObject? ClosestTo(NamespacedKey<DawnItemInfo> itemKey, Vector3 position, float radius, IReadOnlyList<GrabbableObject> items, Func<GrabbableObject, bool>? itemFilter = null) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) return ClosestTo(position, radius, items, (GrabbableObject item) => MatchesDawnKey(item, itemKey) && (itemFilter == null || itemFilter(item))); } } public static class GrabbablePlacement { public static bool PlaceAt(GrabbableObject? item, Vector3 position, Quaternion rotation) { //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_001f: 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_0026: 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) if ((Object)(object)item == (Object)null) { return false; } ((Component)item).transform.SetPositionAndRotation(position, rotation); item.startFallingPosition = position; item.targetFloorPosition = position; item.fallTime = 1f; item.hasHitGround = true; item.reachedFloorTarget = true; return true; } public static bool DropFrom(GrabbableObject? item, Vector3 startPosition, Vector3 floorPosition) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0030: 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_003d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null) { return false; } Transform parent = ((Component)item).transform.parent; if ((Object)(object)parent != (Object)null) { item.startFallingPosition = parent.InverseTransformPoint(startPosition); item.targetFloorPosition = parent.InverseTransformPoint(floorPosition); } else { item.startFallingPosition = startPosition; item.targetFloorPosition = floorPosition; } item.fallTime = 0f; item.hasHitGround = false; item.reachedFloorTarget = false; return true; } public static bool PlaceOn(GrabbableObject? item, Transform? surface, Vector3 localOffset) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0050: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null || (Object)(object)surface == (Object)null) { return false; } item.parentObject = null; ((Component)item).transform.localScale = item.originalScale; ((Component)item).transform.position = surface.TransformPoint(localOffset); item.targetFloorPosition = localOffset; item.startFallingPosition = localOffset + Vector3.up * 0.0001f; item.fallTime = 1f; item.hasHitGround = true; item.reachedFloorTarget = true; return true; } public static bool PlaceOn(GrabbableObject? item, Transform? parent, Transform? point) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null || (Object)(object)parent == (Object)null || (Object)(object)point == (Object)null) { return false; } item.parentObject = null; ((Component)item).transform.localScale = item.originalScale; ((Component)item).transform.SetParent(parent, true); ((Component)item).transform.localScale = item.originalScale; ((Component)item).transform.SetPositionAndRotation(point.position, point.rotation); item.startFallingPosition = (item.targetFloorPosition = ((Component)item).transform.localPosition) + Vector3.up * 0.0001f; item.fallTime = 1f; item.hasHitGround = true; item.reachedFloorTarget = true; return true; } public static bool PlaceLocal(GrabbableObject? item, Transform? parent, Vector3 localPosition, Quaternion localRotation) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_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_006e: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null || (Object)(object)parent == (Object)null) { return false; } item.parentObject = null; ((Component)item).transform.localScale = item.originalScale; ((Component)item).transform.SetParent(parent, false); ((Component)item).transform.SetLocalPositionAndRotation(localPosition, localRotation); ((Component)item).transform.localScale = item.originalScale; item.targetFloorPosition = localPosition; item.startFallingPosition = localPosition + Vector3.up * 0.0001f; item.fallTime = 1f; item.hasHitGround = true; item.reachedFloorTarget = true; return true; } } public delegate void HatNetMessageHandler(ulong senderClientId, string data); public static class HatNet { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__ServerMessageReceived; public static HandleNamedMessageDelegate <1>__ClientMessageReceived; } private const string ServerMessageName = "MrHat.Lib.HatNet.Server"; private const string ClientMessageName = "MrHat.Lib.HatNet.Client"; private static readonly Dictionary<string, List<HatNetMessageHandler>> ServerHandlers = new Dictionary<string, List<HatNetMessageHandler>>(StringComparer.Ordinal); private static readonly Dictionary<string, List<HatNetMessageHandler>> ClientHandlers = new Dictionary<string, List<HatNetMessageHandler>>(StringComparer.Ordinal); private static NetworkManager? messageManager; private static bool messagesReady; internal static void Init() { //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_0072: Expected O, but got Unknown //IL_0093: 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_009e: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) != null && (!messagesReady || !((Object)(object)messageManager == (Object)(object)singleton))) { Shutdown(); messageManager = singleton; messagesReady = true; CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; object obj = <>O.<0>__ServerMessageReceived; if (obj == null) { HandleNamedMessageDelegate val = ServerMessageReceived; <>O.<0>__ServerMessageReceived = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("MrHat.Lib.HatNet.Server", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = singleton.CustomMessagingManager; object obj2 = <>O.<1>__ClientMessageReceived; if (obj2 == null) { HandleNamedMessageDelegate val2 = ClientMessageReceived; <>O.<1>__ClientMessageReceived = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("MrHat.Lib.HatNet.Client", (HandleNamedMessageDelegate)obj2); Log.Info("HatNet messages ready"); } } internal static void Shutdown() { if (messagesReady) { NetworkManager? obj = messageManager; if (((obj != null) ? obj.CustomMessagingManager : null) != null) { messageManager.CustomMessagingManager.UnregisterNamedMessageHandler("MrHat.Lib.HatNet.Server"); messageManager.CustomMessagingManager.UnregisterNamedMessageHandler("MrHat.Lib.HatNet.Client"); messageManager = null; messagesReady = false; Log.Info("HatNet messages stopped"); return; } } messageManager = null; messagesReady = false; } public static void AddServerHandler(NamespacedKey key, HatNetMessageHandler handler) { if (Add(ServerHandlers, key, handler)) { Log.Debug($"HatNet server handler added for {key}"); } } public static void AddClientHandler(NamespacedKey key, HatNetMessageHandler handler) { if (Add(ClientHandlers, key, handler)) { Log.Debug($"HatNet client handler added for {key}"); } } public static void RemoveServerHandler(NamespacedKey key, HatNetMessageHandler handler) { if (Remove(ServerHandlers, key, handler)) { Log.Debug($"HatNet server handler removed for {key}"); } } public static void RemoveClientHandler(NamespacedKey key, HatNetMessageHandler handler) { if (Remove(ClientHandlers, key, handler)) { Log.Debug($"HatNet client handler removed for {key}"); } } public unsafe static bool SendToServer(NamespacedKey key, string data) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) Init(); NetworkManager val = messageManager ?? NetworkManager.Singleton; if (val == null || !val.IsListening || val.CustomMessagingManager == null) { Log.Debug("HatNet server message skipped; networking unavailable"); return false; } FastBufferWriter val2 = CreateWriter(key, data); try { val.CustomMessagingManager.SendNamedMessage("MrHat.Lib.HatNet.Server", 0uL, val2, (NetworkDelivery)4); return true; } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } public unsafe static bool SendToClients(NamespacedKey key, string data) { //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) //IL_005c: Unknown result type (might be due to invalid IL or missing references) Init(); NetworkManager val = messageManager ?? NetworkManager.Singleton; if (val == null || !val.IsListening || !val.IsServer || val.CustomMessagingManager == null) { Log.Debug("HatNet client message skipped; server unavailable"); return false; } FastBufferWriter val2 = CreateWriter(key, data); try { val.CustomMessagingManager.SendNamedMessageToAll("MrHat.Lib.HatNet.Client", val2, (NetworkDelivery)4); return true; } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } public unsafe static bool SendToClient(NamespacedKey key, ulong clientId, string data) { //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) //IL_005d: Unknown result type (might be due to invalid IL or missing references) Init(); NetworkManager val = messageManager ?? NetworkManager.Singleton; if (val == null || !val.IsListening || !val.IsServer || val.CustomMessagingManager == null) { Log.Debug("HatNet client message skipped; server unavailable"); return false; } FastBufferWriter val2 = CreateWriter(key, data); try { val.CustomMessagingManager.SendNamedMessage("MrHat.Lib.HatNet.Client", clientId, val2, (NetworkDelivery)4); return true; } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } private static bool Add(Dictionary<string, List<HatNetMessageHandler>> handlers, NamespacedKey key, HatNetMessageHandler handler) { if (key == null) { throw new ArgumentNullException("key"); } if (handler == null) { throw new ArgumentNullException("handler"); } string key2 = ((object)key).ToString(); if (!handlers.TryGetValue(key2, out List<HatNetMessageHandler> value)) { value = (handlers[key2] = new List<HatNetMessageHandler>()); } if (value.Contains(handler)) { return false; } value.Add(handler); return true; } private static bool Remove(Dictionary<string, List<HatNetMessageHandler>> handlers, NamespacedKey key, HatNetMessageHandler handler) { if (key == null) { throw new ArgumentNullException("key"); } if (handler == null) { throw new ArgumentNullException("handler"); } string key2 = ((object)key).ToString(); if (!handlers.TryGetValue(key2, out List<HatNetMessageHandler> value)) { return false; } if (!value.Remove(handler)) { return false; } if (value.Count == 0) { handlers.Remove(key2); } return true; } private static FastBufferWriter CreateWriter(NamespacedKey key, string data) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) string text = ((object)key).ToString(); string text2 = data ?? string.Empty; int num = Math.Max(64, text.Length * 4 + text2.Length * 4 + 64); FastBufferWriter result = default(FastBufferWriter); ((FastBufferWriter)(ref result))..ctor(num, (Allocator)2, -1); ((FastBufferWriter)(ref result)).WriteValueSafe(text, false); ((FastBufferWriter)(ref result)).WriteValueSafe(text2, false); return result; } private static void ServerMessageReceived(ulong senderClientId, FastBufferReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) MessageReceived(senderClientId, reader, ServerHandlers); } private static void ClientMessageReceived(ulong senderClientId, FastBufferReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) MessageReceived(senderClientId, reader, ClientHandlers); } private static void MessageReceived(ulong senderClientId, FastBufferReader reader, Dictionary<string, List<HatNetMessageHandler>> handlers) { string text = default(string); ((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false); string data = default(string); ((FastBufferReader)(ref reader)).ReadValueSafe(ref data, false); if (!handlers.TryGetValue(text, out List<HatNetMessageHandler> value)) { Log.Debug("HatNet message ignored because no handler exists for " + text); return; } HatNetMessageHandler[] array = value.ToArray(); for (int i = 0; i < array.Length; i++) { array[i](senderClientId, data); } } } public static class LocalPlayerCollider { public static Collider? Current() { GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance == (Object)null) { return null; } PlayerControllerB localPlayerController = instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { return null; } return localPlayerController.playerCollider; } public static bool Matches(Collider other) { if ((Object)(object)other == (Object)null) { return false; } return (Object)(object)other == (Object)(object)Current(); } } [DisallowMultipleComponent] public class LocalPlayerTrigger : MonoBehaviour { private Collider? playerCollider; private bool playerInside; public Collider? PlayerCollider => playerCollider ?? (playerCollider = LocalPlayerCollider.Current()); public bool PlayerInside => playerInside; public event Action<Collider>? Entered; public event Action<Collider>? Exited; public static LocalPlayerTrigger? Arm(Collider? bounds) { if ((Object)(object)bounds == (Object)null) { return null; } bounds.isTrigger = true; Rigidbody val = ((Component)bounds).gameObject.GetComponent<Rigidbody>() ?? ((Component)bounds).gameObject.AddComponent<Rigidbody>(); val.isKinematic = false; val.useGravity = false; val.constraints = (RigidbodyConstraints)126; LocalPlayerTrigger result = default(LocalPlayerTrigger); if (!((Component)bounds).TryGetComponent<LocalPlayerTrigger>(ref result)) { result = ((Component)bounds).gameObject.AddComponent<LocalPlayerTrigger>(); } return result; } private void OnDisable() { playerInside = false; } private void OnDestroy() { this.Entered = null; this.Exited = null; playerCollider = null; playerInside = false; } private void OnTriggerEnter(Collider other) { MarkEntered(other); } private void OnTriggerStay(Collider other) { MarkEntered(other); } private void OnTriggerExit(Collider other) { if (MatchesPlayer(other)) { playerInside = false; this.Exited?.Invoke(other); } } private void MarkEntered(Collider other) { if (!playerInside && MatchesPlayer(other)) { playerInside = true; this.Entered?.Invoke(other); } } private bool MatchesPlayer(Collider other) { if ((Object)(object)other == (Object)null) { return false; } Collider val = LocalPlayerCollider.Current(); if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)playerCollider) { playerCollider = val; } return (Object)(object)other == (Object)(object)playerCollider; } } public static class NetworkRefs { public static Coroutine? WhenReady(MonoBehaviour? owner, NetworkObjectReference reference, Action<NetworkObject>? action, float seconds = 8f, int frames = 0) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)owner == (Object)null || action == null) { return null; } return owner.StartCoroutine(Wait(reference, action, seconds, frames)); } public static Coroutine? WhenReady<T>(MonoBehaviour? owner, NetworkObjectReference reference, Action<T>? action, float seconds = 8f, int frames = 0) where T : Component { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)owner == (Object)null || action == null) { return null; } return owner.StartCoroutine(Wait(reference, delegate(NetworkObject networkObject) { T obj = default(T); if (((Component)networkObject).TryGetComponent<T>(ref obj)) { action(obj); } }, seconds, frames)); } private static IEnumerator Wait(NetworkObjectReference reference, Action<NetworkObject> action, float seconds, int frames) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) NetworkObject networkObject = null; float startedAt = Time.realtimeSinceStartup; while (Time.realtimeSinceStartup - startedAt < seconds && !((NetworkObjectReference)(ref reference)).TryGet(ref networkObject, (NetworkManager)null)) { yield return null; } if (!((Object)(object)networkObject == (Object)null)) { for (int i = 0; i < frames; i++) { yield return null; } action(networkObject); } } } [Serializable] public class PlayerAnimatorSwap { public RuntimeAnimatorController localAnimator = null; public RuntimeAnimatorController remoteAnimator = null; } public class PlayerAnimatorTools { private static readonly int SprintingHash = Animator.StringToHash("Sprinting"); private static readonly int JumpingHash = Animator.StringToHash("Jumping"); private static readonly int WalkingHash = Animator.StringToHash("Walking"); private static readonly int CrouchingHash = Animator.StringToHash("crouching"); private static readonly string[] RequiredPlayerLayers = new string[5] { "UpperBodyEmotes", "EmotesNoArms", "HoldingItemsRightHand", "HoldingItemsBothHands", "SpecialAnimations" }; private Animator? animator; private RuntimeAnimatorController? originalAnimator; private RuntimeAnimatorController? replacementAnimator; public bool IsActive { get; private set; } public bool SwapHeld(PlayerControllerB? player, PlayerAnimatorSwap? replacement) { if (IsActive) { return true; } if ((Object)(object)player == (Object)null || replacement == null) { return false; } RuntimeAnimatorController val = (((Object)(object)player == (Object)(object)GameNetworkManager.Instance.localPlayerController) ? replacement.localAnimator : replacement.remoteAnimator); return Swap(player.playerBodyAnimator, val); } public bool Swap(Animator? playerAnimator, RuntimeAnimatorController? replacementAnimator) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (IsActive) { return true; } if ((Object)(object)playerAnimator == (Object)null || (Object)(object)replacementAnimator == (Object)null) { return false; } animator = playerAnimator; originalAnimator = playerAnimator.runtimeAnimatorController; this.replacementAnimator = replacementAnimator; AnimatorStateInfo currentAnimatorStateInfo = playerAnimator.GetCurrentAnimatorStateInfo(0); float normalizedTime = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime; bool flag = playerAnimator.GetBool(CrouchingHash); bool flag2 = playerAnimator.GetBool(WalkingHash); bool flag3 = playerAnimator.GetBool(JumpingHash); bool flag4 = playerAnimator.GetBool(SprintingHash); playerAnimator.runtimeAnimatorController = replacementAnimator; for (int i = 0; i < RequiredPlayerLayers.Length; i++) { if (playerAnimator.GetLayerIndex(RequiredPlayerLayers[i]) < 0) { playerAnimator.runtimeAnimatorController = originalAnimator; Log.Warn("Player animator swap missing layer " + RequiredPlayerLayers[i]); animator = null; originalAnimator = null; this.replacementAnimator = null; return false; } } playerAnimator.Rebind(); playerAnimator.Play(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, 0, normalizedTime); playerAnimator.SetBool(CrouchingHash, flag); playerAnimator.SetBool(WalkingHash, flag2); playerAnimator.SetBool(JumpingHash, flag3); playerAnimator.SetBool(SprintingHash, flag4); playerAnimator.Update(0f); IsActive = true; return true; } public void Restore() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (IsActive) { if ((Object)(object)animator != (Object)null && (Object)(object)animator.runtimeAnimatorController == (Object)(object)replacementAnimator) { AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0); float normalizedTime = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime; bool flag = animator.GetBool(CrouchingHash); bool flag2 = animator.GetBool(WalkingHash); bool flag3 = animator.GetBool(JumpingHash); bool flag4 = animator.GetBool(SprintingHash); animator.runtimeAnimatorController = originalAnimator; animator.Rebind(); animator.Play(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, 0, normalizedTime); animator.SetBool(CrouchingHash, flag); animator.SetBool(WalkingHash, flag2); animator.SetBool(JumpingHash, flag3); animator.SetBool(SprintingHash, flag4); animator.Update(0f); } animator = null; originalAnimator = null; replacementAnimator = null; IsActive = false; } } } public abstract class PlayerAnimatorReplacement : GrabbableObject { [Header("Player Animator")] [SerializeField] private PlayerAnimatorSwap playerAnimator = new PlayerAnimatorSwap(); private readonly PlayerAnimatorTools playerAnimatorTools = new PlayerAnimatorTools(); protected bool SwapHeldPlayerAnimator() { return playerAnimatorTools.SwapHeld(base.playerHeldBy, playerAnimator); } protected void RestoreHeldPlayerAnimator() { playerAnimatorTools.Restore(); } protected override void __initializeVariables() { ((GrabbableObject)this).__initializeVariables(); } protected override void __initializeRpcs() { ((GrabbableObject)this).__initializeRpcs(); } protected internal override string __getTypeName() { return "PlayerAnimatorReplacement"; } } public static class PrefabSpawns { public static bool Grabbable(Item? item, Vector3 position, Quaternion rotation, out GrabbableObject grabbable, out NetworkObject networkObject, Transform? parent = null) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) grabbable = null; networkObject = null; if ((Object)(object)item?.spawnPrefab == (Object)null) { return false; } return Grabbable(item.spawnPrefab, position, rotation, out grabbable, out networkObject, parent); } public static bool Grabbable(GameObject? prefab, Vector3 position, Quaternion rotation, out GrabbableObject grabbable, out NetworkObject networkObject, Transform? parent = null) { //IL_0019: 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) grabbable = null; networkObject = null; if ((Object)(object)prefab == (Object)null) { return false; } GameObject val = Object.Instantiate<GameObject>(prefab, position, rotation, parent); GrabbableObject component = val.GetComponent<GrabbableObject>(); NetworkObject component2 = val.GetComponent<NetworkObject>(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null) { Object.Destroy((Object)(object)val); return false; } grabbable = component; networkObject = component2; return true; } public static T? Component<T>(T? prefab, Vector3 position, Quaternion rotation, Transform? parent = null) where T : Component { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return default(T); } return Object.Instantiate<T>(prefab, position, rotation, parent); } public static GameObject? GameObject(GameObject? prefab, Vector3 position, Quaternion rotation, Transform? parent = null) { //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) if ((Object)(object)prefab == (Object)null) { return null; } return Object.Instantiate<GameObject>(prefab, position, rotation, parent); } } public static class UnlockableTools { public static bool Bought(NamespacedKey<DawnUnlockableItemInfo> key) { if (key == null) { Log.Warn("Dawn unlockable check skipped; key was null"); return false; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { Log.Debug($"Dawn unlockable check skipped for {key}; no round"); return false; } List<UnlockableItem> list = instance.unlockablesList?.unlockables; if (list == null) { Log.Debug($"Dawn unlockable check skipped for {key}; no unlockable list"); return false; } for (int i = 0; i < list.Count; i++) { UnlockableItem val = list[i]; if (val == null) { continue; } DawnUnlockableItemInfo dawnInfo = UnlockableItemExtensions.GetDawnInfo(val); if (dawnInfo != null && ((object)((DawnBaseInfo<DawnUnlockableItemInfo>)(object)dawnInfo).TypedKey).Equals((object?)key)) { if (val.hasBeenUnlockedByPlayer) { Log.Debug($"Dawn unlockable bought for {key}"); return true; } Log.Debug($"Dawn unlockable locked for {key}"); return false; } } Log.Debug($"Dawn unlockable missing for {key}"); return false; } public static bool Bought(string namespacedKey) { if (string.IsNullOrWhiteSpace(namespacedKey)) { Log.Warn("Dawn unlockable check skipped; key text was empty"); return false; } NamespacedKey val = default(NamespacedKey); if (!NamespacedKey.TryParse(namespacedKey, ref val)) { Log.Warn("Dawn unlockable check skipped; key text was invalid for " + namespacedKey); return false; } return Bought(val.AsTyped<DawnUnlockableItemInfo>()); } } } namespace HatLib.Patches { [HarmonyPatch(typeof(GameNetworkManager))] internal static class GameNetworkManagerPatches { [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix() { HatNet.Init(); } [HarmonyPostfix] [HarmonyPatch("SaveGame")] private static void SaveGamePostfix() { RoundEvents.GameSaved(); } } [HarmonyPatch(typeof(StartOfRound))] internal static class StartOfRoundPatches { [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix(StartOfRound __instance) { RoundEvents.RoundStart(__instance); } [HarmonyPostfix] [HarmonyPatch("EndOfGameClientRpc")] private static void EndOfGameClientRpcPostfix(StartOfRound __instance) { RoundEvents.RoundEnd(__instance); } [HarmonyPostfix] [HarmonyPatch("ShipHasLeft")] private static void ShipHasLeftPostfix(StartOfRound __instance) { RoundEvents.ShipLeft(__instance); } [HarmonyPostfix] [HarmonyPatch("SetShipReadyToLand")] private static void SetShipReadyToLandPostfix(StartOfRound __instance) { RoundEvents.ShipReadyToLand(__instance); } [HarmonyPostfix] [HarmonyPatch("LoadShipGrabbableItems")] private static void LoadShipGrabbableItemsPostfix(StartOfRound __instance) { RoundEvents.ShipItemsLoaded(__instance); } [HarmonyPostfix] [HarmonyPatch("SyncShipUnlockablesClientRpc")] private static void SyncShipUnlockablesClientRpcPostfix(StartOfRound __instance) { RoundEvents.ShipUnlockablesSynced(__instance); } [HarmonyPostfix] [HarmonyPatch("ResetPlayersLoadedValueClientRpc")] private static void ResetPlayersLoadedValueClientRpcPostfix(StartOfRound __instance) { RoundEvents.PlayersLoadedReset(__instance); } [HarmonyPostfix] [HarmonyPatch("OnLocalDisconnect")] private static void OnLocalDisconnectPostfix(StartOfRound __instance) { RoundEvents.Disconnect(__instance); HatNet.Shutdown(); } [HarmonyPostfix] [HarmonyPatch("OnDestroy")] private static void OnDestroyPostfix(StartOfRound __instance) { RoundEvents.Destroy(__instance); HatNet.Shutdown(); } } } namespace __GEN { internal class NetworkVariableSerializationHelper { [RuntimeInitializeOnLoadMethod] internal static void InitializeSerialization() { } } } namespace HatLib.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }