using 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? DebugLogs { get; private set; } internal static void Bind(ConfigFile config) { DebugLogs = config.Bind("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? OnRoundStart; public static event Action? OnRoundEnd; public static event Action? OnShipLeft; public static event Action? OnShipReadyToLand; public static event Action? OnShipItemsLoaded; public static event Action? OnShipUnlockablesSynced; public static event Action? OnPlayersLoadedReset; public static event Action? OnLocalDisconnect; public static event Action? 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(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(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(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(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(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(parentKey, ref val)) { Log.Debug($"Dawn save group missing for {parentKey}"); return false; } if (!((DataContainer)val).TryGet(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(parentKey, childKey, value); } public static bool Read(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(parentKey, ref val)) { Log.Debug($"Dawn save group missing for {parentKey}"); return false; } if (!((DataContainer)val).TryGet(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(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(parentKey, ref val)) { val = new ChildPersistentDataContainer(currentContract); ((DataContainer)currentContract).Set(parentKey, val); Log.Debug($"Dawn save group created for {parentKey}"); } ((DataContainer)val).Set(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(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 saveData; private readonly Action 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 saveData, Action acceptData, bool saveOnGameSaved = true) { DawnSaveSync dawnSaveSync = new DawnSaveSync(dataKey, saveData, acceptData, saveOnGameSaved); dawnSaveSync.Enable(); return dawnSaveSync; } public DawnSaveSync(NamespacedKey dataKey, Func saveData, Action 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(Registry registry, NamespacedKey key, Action assign) where TInfo : INamespaced { 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(registry, (Action)delegate { if (DawnFindResource.Resolve(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(Registry registry, NamespacedKey key, Func read, Action assign) where TInfo : INamespaced where TValue : class { DawnFindResource.Add(registry, key, read, typeof(TValue).Name, assign); } public static void Add(Registry registry, NamespacedKey key, Func read, string name, Action assign) where TInfo : INamespaced 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(registry, (Action)delegate { if (DawnFindResource.Resolve(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(Registry registry, Action action) where TInfo : INamespaced { 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(Registry registry, NamespacedKey key, out TInfo info) where TInfo : INamespaced { 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(Registry registry, NamespacedKey key, Func read, out TValue value) where TInfo : INamespaced where TValue : class { return DawnFindResource.Resolve(registry, key, read, typeof(TValue).Name, out value); } public static bool Resolve(Registry registry, NamespacedKey key, Func read, string name, out TValue value) where TInfo : INamespaced where TValue : class { value = null; if (read == null) { Log.Error("Dawn resource reader missing for " + name); return false; } if (!DawnFindResource.Resolve(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([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(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.AllMods).FirstOrDefault((Func)((DuskMod duskMod) => duskMod.Plugin.GUID == dawnModGUID)); if (val == null) { Log.Warn("Dusk mod missing for " + dawnModGUID); return default(T); } ConfigEntryBase val2 = ((IEnumerable)val.ConfigEntries).FirstOrDefault((Func)((ConfigEntryBase configEntry) => configEntry.Definition.Key == settingName)); if (val2 == null) { Log.Warn("Dusk config setting missing for " + settingName); return default(T); } if (!(val2 is ConfigEntry val3)) { Log.Error("Dusk config setting type mismatch for " + settingName); return default(T); } return val3.Value; } public static T Read(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.AllMods).FirstOrDefault((Func)((DuskMod duskMod) => duskMod.Plugin.GUID == dawnModGUID)); if (val == null) { Log.Warn("Dusk mod missing for " + dawnModGUID); return default(T); } ConfigEntryBase val2 = ((IEnumerable)val.ConfigEntries).FirstOrDefault((Func)((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 val3)) { Log.Error("Dusk config setting type mismatch for " + section + "/" + settingName); return default(T); } return val3.Value; } public ConfigEntry? Bind(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.AllMods).FirstOrDefault((Func)((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(settingName, description, defaultValue); } finally { ((IDisposable)val2)?.Dispose(); } } } public static class FindItems { public static NamespacedKey? 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)(object)ItemExtensions.GetDawnInfo(item.itemProperties))?.TypedKey; } public static bool MatchesDawnKey(GrabbableObject item, NamespacedKey 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 Active(Func? itemFilter = null) { GrabbableObject[] array = Object.FindObjectsByType((FindObjectsInactive)0, (FindObjectsSortMode)0); List list = new List(); foreach (GrabbableObject val in array) { if (itemFilter == null || itemFilter(val)) { list.Add(val); } } return list; } public static List Active(NamespacedKey itemKey, Func? itemFilter = null) { return Active((Func?)((GrabbableObject item) => MatchesDawnKey(item, itemKey) && (itemFilter == null || itemFilter(item)))); } public static GrabbableObject? ClosestTo(Vector3 position, float radius, Func? itemFilter = null) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) GrabbableObject[] items = Object.FindObjectsByType((FindObjectsInactive)0, (FindObjectsSortMode)0); return ClosestTo(position, radius, items, itemFilter); } public static GrabbableObject? ClosestTo(NamespacedKey itemKey, Vector3 position, float radius, Func? itemFilter = null) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) GrabbableObject[] items = Object.FindObjectsByType((FindObjectsInactive)0, (FindObjectsSortMode)0); return ClosestTo(itemKey, position, radius, items, itemFilter); } public static GrabbableObject? ClosestTo(Vector3 position, float radius, IReadOnlyList items, Func? 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 itemKey, Vector3 position, float radius, IReadOnlyList items, Func? 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> ServerHandlers = new Dictionary>(StringComparer.Ordinal); private static readonly Dictionary> ClientHandlers = new Dictionary>(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> 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 value)) { value = (handlers[key2] = new List()); } if (value.Contains(handler)) { return false; } value.Add(handler); return true; } private static bool Remove(Dictionary> 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 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> 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 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? Entered; public event Action? Exited; public static LocalPlayerTrigger? Arm(Collider? bounds) { if ((Object)(object)bounds == (Object)null) { return null; } bounds.isTrigger = true; Rigidbody val = ((Component)bounds).gameObject.GetComponent() ?? ((Component)bounds).gameObject.AddComponent(); val.isKinematic = false; val.useGravity = false; val.constraints = (RigidbodyConstraints)126; LocalPlayerTrigger result = default(LocalPlayerTrigger); if (!((Component)bounds).TryGetComponent(ref result)) { result = ((Component)bounds).gameObject.AddComponent(); } 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? 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(MonoBehaviour? owner, NetworkObjectReference reference, Action? 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(ref obj)) { action(obj); } }, seconds, frames)); } private static IEnumerator Wait(NetworkObjectReference reference, Action 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(prefab, position, rotation, parent); GrabbableObject component = val.GetComponent(); NetworkObject component2 = val.GetComponent(); 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? 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(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(prefab, position, rotation, parent); } } public static class UnlockableTools { public static bool Bought(NamespacedKey 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 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)(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()); } } } 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 { } }