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.1
HatLib.dll
Decompiled 6 hours 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.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.1.0")] [assembly: AssemblyInformationalVersion("0.0.1")] [assembly: AssemblyProduct("HatLib")] [assembly: AssemblyTitle("HatLib")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.1.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; } } } 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); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("MrHat.Lib", "HatLib", "0.0.1")] internal class Plugin : BaseUnityPlugin { internal const string modGUID = "MrHat.Lib"; internal const string modName = "HatLib"; internal const string modVersion = "0.0.1"; private const string DawnLibGUID = "com.github.teamxiaolan.dawnlib"; private const string DuskGUID = "com.github.teamxiaolan.dawnlib.dusk"; internal static Harmony _harmony; internal static ManualLogSource mls; internal static Plugin instance; private void Awake() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown instance = this; mls = Logger.CreateLogSource("MrHat.Lib"); _harmony = new Harmony("MrHat.Lib"); ConfigManager.Bind(((BaseUnityPlugin)this).Config); _harmony.PatchAll(typeof(GameNetworkManagerPatches)); _harmony.PatchAll(typeof(StartOfRoundPatches)); mls.LogInfo((object)"HatLib loaded"); } } 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.1"; } } 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 DawnContractData { public static bool LoadString(NamespacedKey key, out string? raw) { raw = string.Empty; PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Debug($"Dawn contract string load skipped because no current contract exists for {key}"); return false; } if (!((DataContainer)currentContract).TryGet<string>(key, ref raw)) { Log.Debug($"Dawn contract string was not found for {key}"); return false; } Log.Debug($"Dawn contract string loaded for {key}"); return true; } public static bool WriteString(NamespacedKey key, string raw) { return Write(key, raw); } public static bool Load<T>(NamespacedKey key, out T? value) { value = default(T); PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Debug($"Dawn contract value load skipped because no current contract exists for {key}"); return false; } if (!((DataContainer)currentContract).TryGet<T>(key, ref value)) { Log.Debug($"Dawn contract value was not found for {key}"); return false; } Log.Debug($"Dawn contract value loaded for {key}"); return true; } public static bool Write<T>(NamespacedKey key, T value) { if (value == null) { Log.Warn($"Dawn contract value write skipped because value was null for {key}"); return false; } if (!CanWrite()) { Log.Warn($"Dawn contract value write skipped because this client is not the server for {key}"); return false; } PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Warn($"Dawn contract value write skipped because no current contract exists for {key}"); return false; } using (((DataContainer)currentContract).CreateEditContext()) { ((DataContainer)currentContract).Set<T>(key, value); } Log.Debug($"Dawn contract value written for {key}"); return true; } public static bool LoadJObject(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 contract child object load skipped because no current contract exists for {childKey}"); return false; } ChildPersistentDataContainer val = default(ChildPersistentDataContainer); if (!((DataContainer)currentContract).TryGet<ChildPersistentDataContainer>(parentKey, ref val)) { Log.Debug($"Dawn contract child container was not found for {parentKey}"); return false; } if (!((DataContainer)val).TryGet<JObject>(childKey, ref value)) { Log.Debug($"Dawn contract child object was not found for {childKey}"); return false; } Log.Debug($"Dawn contract child object loaded for {childKey}"); return true; } public static bool WriteJObject(NamespacedKey parentKey, NamespacedKey childKey, JObject value) { return Write<JObject>(parentKey, childKey, value); } public static bool Load<T>(NamespacedKey parentKey, NamespacedKey childKey, out T? value) { value = default(T); PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Debug($"Dawn contract child value load skipped because no current contract exists for {childKey}"); return false; } ChildPersistentDataContainer val = default(ChildPersistentDataContainer); if (!((DataContainer)currentContract).TryGet<ChildPersistentDataContainer>(parentKey, ref val)) { Log.Debug($"Dawn contract child container was not found for {parentKey}"); return false; } if (!((DataContainer)val).TryGet<T>(childKey, ref value)) { Log.Debug($"Dawn contract child value was not found for {childKey}"); return false; } Log.Debug($"Dawn contract child value loaded for {childKey}"); return true; } public static bool Write<T>(NamespacedKey parentKey, NamespacedKey childKey, T value) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if (value == null) { Log.Warn($"Dawn contract child value write skipped because value was null for {childKey}"); return false; } if (!CanWrite()) { Log.Warn($"Dawn contract child value write skipped because this client is not the server for {childKey}"); return false; } PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Warn($"Dawn contract child value write skipped because no current contract exists for {childKey}"); 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 contract child container created for {parentKey}"); } ((DataContainer)val).Set<T>(childKey, value); } Log.Debug($"Dawn contract child value written for {childKey}"); return true; } public static bool Delete(NamespacedKey key) { if (!CanWrite()) { Log.Warn($"Dawn contract value delete skipped because this client is not the server for {key}"); return false; } PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Warn($"Dawn contract value delete skipped because no current contract exists for {key}"); return false; } using (((DataContainer)currentContract).CreateEditContext()) { ((DataContainer)currentContract).Remove(key); } Log.Debug($"Dawn contract value deleted for {key}"); return true; } public static bool Delete(NamespacedKey parentKey, NamespacedKey childKey, bool deleteParentWhenEmpty = false) { if (!CanWrite()) { Log.Warn($"Dawn contract child value delete skipped because this client is not the server for {childKey}"); return false; } PersistentDataContainer currentContract = DawnLib.GetCurrentContract(); if (currentContract == null) { Log.Warn($"Dawn contract child value delete skipped because no current contract exists for {childKey}"); return false; } using (((DataContainer)currentContract).CreateEditContext()) { ChildPersistentDataContainer val = default(ChildPersistentDataContainer); if (!((DataContainer)currentContract).TryGet<ChildPersistentDataContainer>(parentKey, ref val)) { Log.Debug($"Dawn contract child delete skipped because container was not found for {parentKey}"); return false; } ((DataContainer)val).Remove(childKey); Log.Debug($"Dawn contract child value deleted for {childKey}"); if (deleteParentWhenEmpty && ((DataContainer)val).Count == 0) { ((DataContainer)currentContract).Remove(parentKey); Log.Debug($"Dawn contract child container deleted for {parentKey}"); } } return true; } private static bool CanWrite() { NetworkManager singleton = NetworkManager.Singleton; return singleton != null && singleton.IsServer; } } public class DawnContractSync { 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> writeData; private readonly Action<string> readData; 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 DawnContractSync Register(NamespacedKey dataKey, Func<string> writeData, Action<string> readData, bool saveOnGameSaved = true) { DawnContractSync dawnContractSync = new DawnContractSync(dataKey, writeData, readData, saveOnGameSaved); dawnContractSync.Enable(); return dawnContractSync; } public DawnContractSync(NamespacedKey dataKey, Func<string> writeData, Action<string> readData, bool saveOnGameSaved = true) { this.dataKey = dataKey ?? throw new ArgumentNullException("dataKey"); requestKey = RequestKey(dataKey); this.writeData = writeData ?? throw new ArgumentNullException("writeData"); this.readData = readData ?? throw new ArgumentNullException("readData"); this.saveOnGameSaved = saveOnGameSaved; } public void Enable() { if (listening) { Log.Debug($"Dawn contract sync enable skipped because it is already enabled for {dataKey}"); return; } listening = true; HatNet.Init(); HatNet.RegisterClient(dataKey, DataReceived); HatNet.RegisterServer(requestKey, RequestReceived); RoundEvents.OnShipItemsLoaded += ShipItemsLoaded; RoundEvents.OnShipUnlockablesSynced += ShipUnlockablesSynced; RoundEvents.OnLocalDisconnect += Clear; RoundEvents.OnDestroy += Clear; if (saveOnGameSaved) { RoundEvents.OnGameSaved += SaveGame; } Log.Debug($"Dawn contract sync enabled for {dataKey}"); } public void Disable() { if (!listening) { Log.Debug($"Dawn contract sync disable skipped because it is already disabled for {dataKey}"); return; } listening = false; HatNet.UnregisterClient(dataKey, DataReceived); HatNet.UnregisterServer(requestKey, RequestReceived); RoundEvents.OnShipItemsLoaded -= ShipItemsLoaded; RoundEvents.OnShipUnlockablesSynced -= ShipUnlockablesSynced; RoundEvents.OnLocalDisconnect -= Clear; RoundEvents.OnDestroy -= Clear; RoundEvents.OnGameSaved -= SaveGame; Clear(); Log.Debug($"Dawn contract sync disabled for {dataKey}"); } public bool Save() { return Save(writeData() ?? string.Empty); } public bool Save(string data) { if (!HostRestoreFinished) { Log.Debug($"Dawn contract sync save skipped because restore is still running for {dataKey}"); return false; } string raw = data ?? string.Empty; if (!DawnContractData.WriteString(dataKey, raw)) { Log.Warn($"Dawn contract sync data could not be saved for {dataKey}"); return false; } rawData = raw; dataReceived = true; Log.Debug($"Dawn contract sync data saved for {dataKey}"); return true; } public bool SaveAndPublish() { if (!Save()) { return false; } if (PublishRaw(rawData)) { Log.Debug($"Dawn contract sync data saved and published for {dataKey}"); return true; } Log.Warn($"Dawn contract sync data was saved but not published for {dataKey}"); return false; } public bool Delete() { if (!HostRestoreFinished) { Log.Debug($"Dawn contract sync delete skipped because restore is still running for {dataKey}"); return false; } if (!DawnContractData.Delete(dataKey)) { Log.Warn($"Dawn contract sync data could not be deleted for {dataKey}"); return false; } rawData = string.Empty; dataReceived = true; Log.Debug($"Dawn contract sync data deleted for {dataKey}"); return true; } public bool Publish() { if (HostRestoreFinished) { NetworkManager singleton = NetworkManager.Singleton; if (singleton != null && singleton.IsServer) { rawData = writeData() ?? string.Empty; dataReceived = true; if (PublishRaw(rawData)) { Log.Debug($"Dawn contract sync data published for {dataKey}"); return true; } Log.Warn($"Dawn contract sync data could not be published for {dataKey}"); return false; } } Log.Debug($"Dawn contract sync publish skipped for {dataKey}"); return false; } public bool Request() { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null || !singleton.IsListening) { Log.Debug($"Dawn contract sync request skipped because networking is unavailable for {dataKey}"); return false; } if (HatNet.SendToServer(requestKey, string.Empty)) { Log.Debug($"Dawn contract sync data requested for {dataKey}"); return true; } Log.Warn($"Dawn contract sync data could not be requested for {dataKey}"); return false; } internal void Clear() { StopHostCoroutine(); StopClientCoroutine(); HostRestoreFinished = true; ClientDelayFinished = false; rawData = string.Empty; dataReceived = false; Log.Debug($"Dawn contract sync transient data 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 contract 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 contract 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 = writeData() ?? string.Empty; dataReceived = true; if (HatNet.SendToClient(dataKey, senderClientId, rawData)) { Log.Debug($"Dawn contract 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 contract sync data received for {dataKey}"); if (ClientDelayFinished) { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null || !singleton.IsServer) { readData(rawData); } } } private IEnumerator HostRestoreAfterDelay() { yield return DelayWait; string savedData; bool loaded = DawnContractData.LoadString(dataKey, out savedData) && savedData != null; string contractData = (rawData = (loaded ? savedData : string.Empty)); dataReceived = true; readData(contractData); if (loaded) { Log.Debug($"Dawn contract sync data loaded for {dataKey}"); } else { Log.Debug($"Dawn contract sync data was missing for {dataKey}"); } rawData = writeData() ?? string.Empty; PublishRaw(rawData); HostRestoreFinished = true; hostCoroutine = null; hostOwner = null; Log.Debug($"Dawn contract sync restore finished for {dataKey}"); } private IEnumerator ClientRestoreAfterDelay() { yield return DelayWait; ClientDelayFinished = true; clientCoroutine = null; clientOwner = null; if (dataReceived) { readData(rawData); Log.Debug($"Dawn contract sync client data applied 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 contract 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 contract sync client restore stopped for {dataKey}"); } } } public static class DawnFindResource { public static void Add<TInfo>(Registry<TInfo> registry, NamespacedKey<TInfo> key, Action<TInfo> apply) where TInfo : INamespaced<TInfo> { if (registry == null) { Log.Error($"Dawn resource registry was missing for {key}"); return; } if (apply == null) { Log.Error($"Dawn resource request was missing for {key}"); return; } DawnFindResource.OnFreeze<TInfo>(registry, (Action)delegate { if (DawnFindResource.Get<TInfo>(registry, key, out TInfo info)) { apply(info); Log.Debug($"Dawn resource request applied for {key}"); } }); Log.Debug($"Dawn resource request added for {key}"); } public static void Add<TInfo, TValue>(Registry<TInfo> registry, NamespacedKey<TInfo> key, Func<TInfo, TValue?> read, Action<TValue> apply) where TInfo : INamespaced<TInfo> where TValue : class { DawnFindResource.Add<TInfo, TValue>(registry, key, read, typeof(TValue).Name, apply); } public static void Add<TInfo, TValue>(Registry<TInfo> registry, NamespacedKey<TInfo> key, Func<TInfo, TValue?> read, string name, Action<TValue> apply) where TInfo : INamespaced<TInfo> where TValue : class { if (registry == null) { Log.Error("Dawn resource registry was missing for " + name); return; } if (read == null) { Log.Error("Dawn resource lookup was missing for " + name); return; } if (apply == null) { Log.Error("Dawn resource request was missing for " + name); return; } DawnFindResource.OnFreeze<TInfo>(registry, (Action)delegate { if (DawnFindResource.Get<TInfo, TValue>(registry, key, read, name, out TValue value)) { apply(value); Log.Debug("Dawn resource request applied for " + name); } }); Log.Debug("Dawn resource request added for " + name); } public static void OnFreeze<TInfo>(Registry<TInfo> registry, Action action) where TInfo : INamespaced<TInfo> { if (registry == null) { Log.Error("Dawn registry was missing for " + typeof(TInfo).Name); } else if (action == null) { Log.Error("Dawn registry freeze action was missing for " + typeof(TInfo).Name); } else if (registry.IsFrozen) { Log.Debug("Dawn registry was already frozen for " + typeof(TInfo).Name); action(); } else { registry.OnFreeze += action; Log.Debug("Dawn registry freeze action added for " + typeof(TInfo).Name); } } public static bool Get<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 was missing for {key}"); return false; } if (registry.TryGetValue(key, ref info)) { Log.Debug($"Dawn resource found for {key}"); return true; } info = default(TInfo); Log.Warn($"Dawn resource was not found for {key}"); return false; } public static bool Get<TInfo, TValue>(Registry<TInfo> registry, NamespacedKey<TInfo> key, Func<TInfo, TValue?> read, out TValue value) where TInfo : INamespaced<TInfo> where TValue : class { return DawnFindResource.Get<TInfo, TValue>(registry, key, read, typeof(TValue).Name, out value); } public static bool Get<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 lookup was missing for " + name); return false; } if (!DawnFindResource.Get<TInfo>(registry, key, out TInfo info)) { return false; } TValue val = read(info); if (Missing(val)) { Log.Warn("Dawn resource value was not found for " + name); return false; } value = val; Log.Debug("Dawn resource value found 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 Get<T>(string dawnModGUID, string settingName) { if (string.IsNullOrWhiteSpace(dawnModGUID)) { Log.Error("Dusk config read failed because the Dawn mod GUID was empty"); return default(T); } if (string.IsNullOrWhiteSpace(settingName)) { Log.Error("Dusk config read failed because the setting name was empty"); 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 config read failed because Dawn mod GUID '" + dawnModGUID + "' was not found"); 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 '" + settingName + "' was not found"); return default(T); } if (!(val2 is ConfigEntry<T> val3)) { Log.Error("Dusk config setting '" + settingName + "' was not a " + typeof(T).Name); 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("DuskConfigInjector was created with an empty dawnModGUID"); return null; } if (string.IsNullOrWhiteSpace(section)) { Log.Error("Dusk config section was empty"); return null; } if (string.IsNullOrWhiteSpace(settingName)) { Log.Error("Dusk config key was empty"); return null; } DuskMod val = ((IEnumerable<DuskMod>)DuskMod.AllMods).FirstOrDefault((Func<DuskMod, bool>)((DuskMod duskMod) => duskMod.Plugin.GUID == dawnModGUID)); if (val == null) { Log.Warn("Dusk GUID was not found 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 read skipped because item was missing"); return null; } if ((Object)(object)item.itemProperties == (Object)null) { Log.Warn("Dawn item key read skipped because item properties were missing"); 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 because item key was missing"); 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); } } Log.Debug($"{list.Count} items found"); return list; } public static List<GrabbableObject> Active(NamespacedKey<DawnItemInfo> itemKey, Func<GrabbableObject, bool>? itemFilter = null) { List<GrabbableObject> list = Active((Func<GrabbableObject, bool>?)((GrabbableObject item) => MatchesDawnKey(item, itemKey) && (itemFilter == null || itemFilter(item)))); Log.Debug($"{list.Count} Dawn items found"); return list; } 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); GrabbableObject val = ClosestTo(position, radius, items, itemFilter); Log.Debug(((Object)(object)val == (Object)null) ? "Closest item was not found" : "Closest item found"); return val; } 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); GrabbableObject val = ClosestTo(itemKey, position, radius, items, itemFilter); Log.Debug(((Object)(object)val == (Object)null) ? "Closest Dawn item was not found" : "Closest Dawn item found"); return val; } 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 val = null; for (int i = 0; i < items.Count; i++) { GrabbableObject val2 = items[i]; if (!((Object)(object)val2 == (Object)null) && (itemFilter == null || itemFilter(val2))) { Vector3 val3 = ((Component)val2).transform.position - position; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (!(sqrMagnitude >= num)) { num = sqrMagnitude; val = val2; } } } Log.Debug(((Object)(object)val == (Object)null) ? "Closest item was not found" : "Closest item found"); return val; } 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) GrabbableObject val = ClosestTo(position, radius, items, (GrabbableObject item) => MatchesDawnKey(item, itemKey) && (itemFilter == null || itemFilter(item))); Log.Debug(((Object)(object)val == (Object)null) ? "Closest Dawn item was not found" : "Closest Dawn item found"); return val; } } 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? registeredManager; private static bool registeredMessages; 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 && (!registeredMessages || !((Object)(object)registeredManager == (Object)(object)singleton))) { Shutdown(); registeredManager = singleton; registeredMessages = 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 registered"); } } internal static void Shutdown() { if (registeredMessages) { NetworkManager? obj = registeredManager; if (((obj != null) ? obj.CustomMessagingManager : null) != null) { registeredManager.CustomMessagingManager.UnregisterNamedMessageHandler("MrHat.Lib.HatNet.Server"); registeredManager.CustomMessagingManager.UnregisterNamedMessageHandler("MrHat.Lib.HatNet.Client"); registeredManager = null; registeredMessages = false; Log.Info("HatNet messages unregistered"); return; } } registeredManager = null; registeredMessages = false; } public static void RegisterServer(NamespacedKey key, HatNetMessageHandler handler) { if (Register(ServerHandlers, key, handler)) { Log.Debug($"HatNet server registered for {key}"); } } public static void RegisterClient(NamespacedKey key, HatNetMessageHandler handler) { if (Register(ClientHandlers, key, handler)) { Log.Debug($"HatNet client registered for {key}"); } } public static void UnregisterServer(NamespacedKey key, HatNetMessageHandler handler) { if (Unregister(ServerHandlers, key, handler)) { Log.Debug($"HatNet server unregistered for {key}"); } } public static void UnregisterClient(NamespacedKey key, HatNetMessageHandler handler) { if (Unregister(ClientHandlers, key, handler)) { Log.Debug($"HatNet client unregistered 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 = registeredManager ?? NetworkManager.Singleton; if (val == null || !val.IsListening || val.CustomMessagingManager == null) { Log.Debug("HatNet server message was not sent because networking is 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 = registeredManager ?? NetworkManager.Singleton; if (val == null || !val.IsListening || !val.IsServer || val.CustomMessagingManager == null) { Log.Debug("HatNet client message was not sent because the server is 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 = registeredManager ?? NetworkManager.Singleton; if (val == null || !val.IsListening || !val.IsServer || val.CustomMessagingManager == null) { Log.Debug("HatNet client message was not sent because the server is 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 Register(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 Unregister(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 is registered 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; } } [Serializable] public class PlayerAnimatorControllerReplacement { public RuntimeAnimatorController animatorController = null; public RuntimeAnimatorController remoteAnimatorController = 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? originalController; private RuntimeAnimatorController? replacementController; public bool IsActive { get; private set; } public bool ApplyHeld(PlayerControllerB? player, PlayerAnimatorControllerReplacement? replacement) { if (IsActive) { return true; } if ((Object)(object)player == (Object)null || replacement == null) { return false; } RuntimeAnimatorController targetController = (((Object)(object)player == (Object)(object)GameNetworkManager.Instance.localPlayerController) ? replacement.animatorController : replacement.remoteAnimatorController); return Apply(player.playerBodyAnimator, targetController); } public bool Apply(Animator? targetAnimator, RuntimeAnimatorController? targetController) { //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)targetAnimator == (Object)null || (Object)(object)targetController == (Object)null) { return false; } animator = targetAnimator; originalController = targetAnimator.runtimeAnimatorController; replacementController = targetController; AnimatorStateInfo currentAnimatorStateInfo = targetAnimator.GetCurrentAnimatorStateInfo(0); float normalizedTime = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime; bool flag = targetAnimator.GetBool(CrouchingHash); bool flag2 = targetAnimator.GetBool(WalkingHash); bool flag3 = targetAnimator.GetBool(JumpingHash); bool flag4 = targetAnimator.GetBool(SprintingHash); targetAnimator.runtimeAnimatorController = targetController; for (int i = 0; i < RequiredPlayerLayers.Length; i++) { if (targetAnimator.GetLayerIndex(RequiredPlayerLayers[i]) < 0) { targetAnimator.runtimeAnimatorController = originalController; Log.Warn("Player animator replacement missing layer " + RequiredPlayerLayers[i]); animator = null; originalController = null; replacementController = null; return false; } } targetAnimator.Rebind(); targetAnimator.Play(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, 0, normalizedTime); targetAnimator.SetBool(CrouchingHash, flag); targetAnimator.SetBool(WalkingHash, flag2); targetAnimator.SetBool(JumpingHash, flag3); targetAnimator.SetBool(SprintingHash, flag4); targetAnimator.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)replacementController) { 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 = originalController; 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; originalController = null; replacementController = null; IsActive = false; } } } public abstract class PlayerAnimatorReplacement : GrabbableObject { [Header("Player Animator")] [SerializeField] private PlayerAnimatorControllerReplacement playerAnimator = new PlayerAnimatorControllerReplacement(); private readonly PlayerAnimatorTools playerAnimatorTools = new PlayerAnimatorTools(); protected bool ApplyHeldPlayerAnimator() { return playerAnimatorTools.ApplyHeld(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 UnlockableTools { public static bool Bought(NamespacedKey<DawnUnlockableItemInfo> key) { if (key == null) { Log.Warn("Dawn unlockable bought check skipped because key was missing"); return false; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { Log.Debug($"Dawn unlockable bought check skipped because no round exists for {key}"); return false; } List<UnlockableItem> list = instance.unlockablesList?.unlockables; if (list == null) { Log.Debug($"Dawn unlockable bought check skipped because no unlockable list exists for {key}"); 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 check passed for {key}"); return true; } Log.Debug($"Dawn unlockable bought check failed because unlockable is locked for {key}"); return false; } } Log.Debug($"Dawn unlockable bought check failed because unlockable was not found for {key}"); return false; } public static bool Bought(string namespacedKey) { if (string.IsNullOrWhiteSpace(namespacedKey)) { Log.Warn("Dawn unlockable bought check skipped because key string was empty"); return false; } NamespacedKey val = default(NamespacedKey); if (!NamespacedKey.TryParse(namespacedKey, ref val)) { Log.Warn("Dawn unlockable bought check skipped because key string could not be parsed 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 { } }