using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using CellMenu; using FluffyUnderware.DevTools.Extensions; using GTFO.API; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes; using Il2CppSystem.Collections.Generic; using LevelGeneration; using Microsoft.CodeAnalysis; using Player; using SNetwork; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("LoadingBars")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LoadingBars")] [assembly: AssemblyTitle("LoadingBars")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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; } } } namespace LoadingBars { internal static class DinoLogger { private static ManualLogSource logger = Logger.CreateLogSource("LoadingBars"); public static void Log(string format, params object[] args) { Log(string.Format(format, args)); } public static void Log(string str) { if (logger != null) { logger.Log((LogLevel)8, (object)str); } } public static void Warning(string format, params object[] args) { Warning(string.Format(format, args)); } public static void Warning(string str) { if (logger != null) { logger.Log((LogLevel)4, (object)str); } } public static void Error(string format, params object[] args) { Error(string.Format(format, args)); } public static void Error(string str) { if (logger != null) { logger.Log((LogLevel)2, (object)str); } } public static void Debug(string format, params object[] args) { Debug(string.Format(format, args)); } public static void Debug(string str) { if (logger != null) { logger.Log((LogLevel)32, (object)str); } } } [BepInPlugin("Dinorush.LoadingBars", "LoadingBars", "1.0.0")] internal sealed class EntryPoint : BasePlugin { public const string MODNAME = "LoadingBars"; public override void Load() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) LoadingBarNetwork.Init(); LoadingBarManager.Init(); LoadingBarUI.Init(); new Harmony("LoadingBars").PatchAll(); ((BasePlugin)this).Log.LogMessage((object)"Loaded LoadingBars"); } } public class LoadingBarManager { public static readonly LoadingBarManager Current = new LoadingBarManager(); private ulong _localLookup; private PlayerLoadingState _localState = new PlayerLoadingState(); private readonly Dictionary _syncedStates = new Dictionary(); private Queue? _currentQueue; public PlayerLoadingState LocalState => _localState; public static event Action? OnPlayerUpdate; public static event Action? OnAddPlayer; public static event Action? OnRemovePlayer; public static bool TryGetSyncedState(ulong lookup, [MaybeNullWhen(false)] out PlayerLoadingState state) { return Current._syncedStates.TryGetValue(lookup, out state); } internal static void Init() { LevelAPI.OnBuildStart += Current.OnBuildStart; LevelAPI.OnBuildDone += Current.OnBuildDone; } internal static void Clear() { Current._syncedStates.Clear(); Current._localLookup = 0uL; } internal void ResetPlayers() { LoadingBarManager.OnRemovePlayer?.Invoke(SNet.LocalPlayer); LoadingBarManager.OnAddPlayer?.Invoke(SNet.LocalPlayer); SNet_Player obj = default(SNet_Player); foreach (ulong key in _syncedStates.Keys) { if (SNet.TryGetPlayer(key, ref obj)) { LoadingBarManager.OnRemovePlayer?.Invoke(obj); LoadingBarManager.OnAddPlayer?.Invoke(obj); } } } private void OnBuildStart() { foreach (PlayerLoadingState value in _syncedStates.Values) { value.Reset(); } _localState.Reset(); _currentQueue = null; } private void OnBuildDone() { _currentQueue = null; _localState.IsDone = true; LoadingBarManager.OnPlayerUpdate?.Invoke(SNet.LocalPlayer.Lookup, _localState); LoadingBarNetwork.SendUpdate(_localState); } internal static void OnAddPlayer_Internal(SNet_Player player) { PlayerLoadingState value = new PlayerLoadingState(); if (player.IsLocal) { if (player.Lookup != Current._localLookup) { Current._localLookup = player.Lookup; LoadingBarManager.OnAddPlayer?.Invoke(player); } } else if (Current._syncedStates.TryAdd(player.Lookup, value)) { LoadingBarManager.OnAddPlayer?.Invoke(player); } } internal static void OnRemovePlayer_Internal(SNet_Player player) { if (Current._syncedStates.Remove(player.Lookup)) { LoadingBarManager.OnRemovePlayer?.Invoke(player); } } internal static void OnSyncedUpdate_Internal(ulong lookup, PlayerLoadingState state) { Current._syncedStates[lookup] = state; LoadingBarManager.OnPlayerUpdate?.Invoke(lookup, state); } internal static void OnBatchUpdate_Internal(LG_Factory factory) { Current.OnBatchUpdate_Instance(factory); } private void OnBatchUpdate_Instance(LG_Factory factory) { if (_localState.Batch != factory.m_batchStep) { _localState.Batch = factory.m_batchStep; _localState.BatchCount = 0; _currentQueue = factory.m_currentBatch.Jobs; } else { _localState.BatchCount++; } _localState.BatchCountRemaining = _currentQueue.Count; LoadingBarManager.OnPlayerUpdate?.Invoke(SNet.LocalPlayer.Lookup, _localState); LoadingBarNetwork.SendUpdate(_localState); } static LoadingBarManager() { LoadingBarManager.OnPlayerUpdate = null; LoadingBarManager.OnAddPlayer = null; LoadingBarManager.OnRemovePlayer = null; } } internal class LoadingBarNetwork { private const string UpdateEvent = "LoadingUpdate"; private const string HasModEvent = "LoadingHasMod"; private const float SyncInterval = 0.25f; private static readonly Dictionary _modPlayers = new Dictionary(); private static float _lastSyncTime = 0f; internal static void Init() { NetworkAPI.RegisterEvent("LoadingUpdate", (Action)ReceiveUpdate); NetworkAPI.RegisterEvent("LoadingHasMod", (Action)ReceiveHasMod); } internal static void Clear() { _modPlayers.Clear(); } internal static void SendUpdate(PlayerLoadingState state) { float time = Clock.Time; if (!state.IsDone && time - _lastSyncTime < 0.25f) { return; } _lastSyncTime = time; foreach (SNet_Player value in _modPlayers.Values) { NetworkAPI.InvokeEvent("LoadingUpdate", state, value, (SNet_ChannelType)0); } } private static void ReceiveUpdate(ulong lookup, PlayerLoadingState state) { LoadingBarManager.OnSyncedUpdate_Internal(lookup, state); } internal static void OnAddPlayer(SNet_Player player) { if (player.IsLocal) { LoadingBarManager.OnAddPlayer_Internal(player); } else { NetworkAPI.InvokeEvent("LoadingHasMod", true, player, (SNet_ChannelType)0); } } internal static void SendHasModResponse(SNet_Player player) { NetworkAPI.InvokeEvent("LoadingHasMod", false, player, (SNet_ChannelType)0); } private static void ReceiveHasMod(ulong lookup, bool _) { SNet_Player val = default(SNet_Player); if (SNet.TryGetPlayer(lookup, ref val) && _modPlayers.TryAdd(lookup, val)) { LoadingBarManager.OnAddPlayer_Internal(val); } } internal static void OnRemovePlayer(SNet_Player player) { if (_modPlayers.Remove(player.Lookup)) { LoadingBarManager.OnRemovePlayer_Internal(player); } } } [HarmonyPatch] internal static class LoadingBarPatches { [HarmonyPatch(typeof(LG_Factory), "GetNewJob")] [HarmonyPostfix] private static void Post_GetNewJob(LG_Factory __instance, bool __result) { if (__result) { LoadingBarManager.OnBatchUpdate_Internal(__instance); } } [HarmonyPatch(typeof(SNet_SessionHub), "AddPlayerToSession")] [HarmonyPostfix] private static void Post_AddPlayer(SNet_Player player) { LoadingBarNetwork.OnAddPlayer(player); } [HarmonyPatch(typeof(SNet_SessionHub), "OnLeftLobby")] [HarmonyPostfix] private static void Post_RemovePlayer(SNet_Player player) { LoadingBarNetwork.OnRemovePlayer(player); } [HarmonyPatch(typeof(SNet_SessionHub), "LeaveHub")] [HarmonyPostfix] private static void Post_LeaveHub() { LoadingBarNetwork.Clear(); LoadingBarManager.Clear(); LoadingBarUI.Clear(); } [HarmonyPatch(typeof(GameStateManager), "ChangeState")] [HarmonyPostfix] private static void Post_ChangeGameState(eGameStateName nextState) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)nextState == 5) { LoadingBarManager.Current.ResetPlayers(); ((GuiLayer)GuiManager.NavMarkerLayer).SetVisible(false); } } [HarmonyPatch(typeof(FocusStateManager), "ChangeState")] [HarmonyPostfix] private static void Post_ChangeFocusState(eFocusState state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)state == 7) { ((GuiLayer)GuiManager.NavMarkerLayer).SetVisible(true); LoadingBarUI.SetBarsActive(active: true); } else { LoadingBarUI.SetBarsActive(active: false); } } [HarmonyPatch(typeof(NavMarker), "UpdateTrackingDimension")] [HarmonyPrefix] private static bool Pre_UpdateTrackingDimension(NavMarker __instance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 eGameStateName currentStateName = GameStateManager.CurrentStateName; if (currentStateName - 6 <= 3) { return false; } return true; } } public class LoadingBarUI { public class LoadingBarState { public GameObject Holder; private readonly SNet_Player _player; private NavMarker _marker; private readonly CM_TimedButton _jobBar; private readonly CM_TimedButton _batchBar; private bool _isSetup; internal bool IsDone; public LoadingBarState(SNet_Player player, GameObject holder, CM_TimedButton jobBar, CM_TimedButton batchBar) { _player = player; Holder = holder; _jobBar = jobBar; _batchBar = batchBar; } public void Update(PlayerLoadingState state) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) if (!_isSetup) { Setup(); } if (!IsDone) { float num = (float)(state.Batch + 1) / (float)PlayerLoadingState.NumBatches; ((Component)_batchBar.m_holdBtnProgressSprite).transform.localScale = new Vector3(num, 1f, 1f); ((TMP_Text)_batchBar.m_btnText).SetText($"Batch {state.BatchName}\n{state.Batch + 1} / {PlayerLoadingState.NumBatches}\n ", true); ((Component)_jobBar.m_holdBtnProgressSprite).transform.localScale = new Vector3(state.BatchProgress, 1f, 1f); ((TMP_Text)_jobBar.m_btnText).SetText($"Jobs\n{state.BatchCount} / {state.BatchCountMax}\n ", true); if (state.IsDone) { CoroutineManager.BlinkOut(Holder, 0f); IsDone = true; } } } private void Setup() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) if (_player.IsLocal) { ((Component)_batchBar).transform.localPosition = new Vector3(0f, -200f, 0f); ((Component)_jobBar).transform.localPosition = new Vector3(0f, -300f, 0f); } else { if (!_player.HasPlayerAgent) { DinoLogger.Warning("Still don't have nav marker >:("); return; } GameObject gameObject = ((Component)((Il2CppObjectBase)_player.PlayerAgent).Cast().PlayerSyncModel.m_tentacleTarget).gameObject; NavMarker val = GuiManager.NavMarkerLayer.PlaceCustomMarker((NavMarkerOption)0, gameObject, "", 0f, false); val.SetPinEnabled(false); Holder.transform.SetParent(((Component)val).transform, false); ((Component)_batchBar).transform.localPosition = new Vector3(0f, 100f, 0f); ((Component)_jobBar).transform.localPosition = new Vector3(0f, 0f, 0f); val.m_isInPlayerDimension = true; _marker = val; } ((Component)_batchBar).gameObject.SetActive(true); ((Component)_jobBar).gameObject.SetActive(true); ColorMarkers(_player.PlayerColor); _isSetup = true; Holder.SetActive(true); ((GuiLayer)GuiManager.NavMarkerLayer).SetVisible(true); } private void ColorMarkers(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) color = Color.Lerp(color, Color.white, 0.33f); _jobBar.m_holdBtnProgressSprite.color = color; _batchBar.m_holdBtnProgressSprite.color = color; } public void Destroy() { ObjectExt.Destroy((Object)(object)Holder); GuiManager.NavMarkerLayer.RemoveMarker(_marker); } } public static Dictionary _playerBars = new Dictionary(); private static readonly string m_prefabPath = "CM_TimedButton"; public static void Init() { LoadingBarManager.OnAddPlayer += RegisterPlayer; LoadingBarManager.OnRemovePlayer += OnPlayerLeave; LoadingBarManager.OnPlayerUpdate += OnPlayerUpdate; } public static void RegisterPlayer(SNet_Player player) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown if (!player.IsBot) { if (_playerBars.ContainsKey(player.Lookup)) { DinoLogger.Warning("Player " + player.NickName + " already has a registered loading bar??"); return; } CM_TimedButton val = CreateAndStyleBar(); ((Object)val).name = "JobProgress"; ((Component)val).gameObject.SetActive(false); CM_TimedButton val2 = CreateAndStyleBar(); ((Object)val2).name = "BatchProgress"; ((Component)val2).gameObject.SetActive(false); GameObject val3 = new GameObject("Loading Bar Holder"); val3.transform.SetParent(((Component)val).transform.parent, false); ((Component)val).transform.SetParent(val3.transform, false); ((Component)val2).transform.SetParent(val3.transform, false); _playerBars.Add(player.Lookup, new LoadingBarState(player, val3, val, val2)); val3.gameObject.SetActive(false); } } private static CM_TimedButton CreateAndStyleBar() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) CM_TimedButton obj = ((Il2CppObjectBase)((GuiLayer)GuiManager.NavMarkerLayer).AddRectComp(m_prefabPath, (GuiAnchor)3, default(Vector2), (Transform)null)).TryCast(); int num = 300; ((RectTransformComp)obj).SetSize(new Vector2((float)num, 30f)); ((CM_Item)obj).SetButtonEnabled(false); obj.m_backgroundSprite = ((Component)((Component)obj).transform.Find("Background")).GetComponent(); obj.m_backgroundSprite.color = Color.grey; obj.m_holdBtnProgressSprite.sprite = SpriteAsset.TopLeftPivotSprite; obj.m_holdBtnProgressSprite.size = new Vector2((float)(num - 6), 24f); obj.m_holdBtnProgressSprite.color = new Color(0.65f, 0.7f, 0.8f); ((Renderer)obj.m_holdBtnProgressSprite).sortingOrder = 1; ((Renderer)obj.m_holdBtnProgressSprite).enabled = true; RectTransform obj2 = ((Il2CppObjectBase)((Component)obj.m_holdBtnProgressSprite).transform).TryCast(); obj2.anchoredPosition = new Vector2(2f, -3f); obj2.anchorMax = new Vector2(1f, 1f); obj2.anchorMin = new Vector2(0f, 0f); obj2.pivot = new Vector2(0f, 1f); ((TMP_Text)obj.m_btnText).autoSizeTextContainer = true; ((Graphic)obj.m_btnText).color = Color.white; obj.m_btnText.sortingOrder = 2; ((TMP_Text)obj.m_btnText).verticalAlignment = (VerticalAlignmentOptions)512; ((TMP_Text)obj.m_btnText).fontStyle = (FontStyles)1; ((TMP_Text)obj.m_btnText).SetText("", true); ((TMP_Text)obj.m_btnText).fontSize = 18f; ((TMP_Text)obj.m_btnText).lineSpacing = 30f; RectTransform obj3 = ((Il2CppObjectBase)obj.m_btnText.transform).TryCast(); obj3.anchorMin = new Vector2(-1f, 1f); obj3.anchorMax = new Vector2(2f, 1f); ((Transform)obj3).localPosition = Vector3.zero; return obj; } public static void Clear() { foreach (ulong key in _playerBars.Keys) { OnPlayerLeave(key); } } public static void OnPlayerLeave(SNet_Player player) { OnPlayerLeave(player.Lookup); } public static void OnPlayerLeave(ulong lookup) { if (_playerBars.TryGetValue(lookup, out LoadingBarState value)) { value.Destroy(); _playerBars.Remove(lookup); } } public static void OnPlayerUpdate(ulong playerLookup, PlayerLoadingState state) { if (!_playerBars.TryGetValue(playerLookup, out LoadingBarState value)) { DinoLogger.Warning($"Didn't get player bars for {playerLookup}"); } else { value.Update(state); } } public static void SetBarsActive(bool active) { foreach (LoadingBarState value in _playerBars.Values) { if ((Object)(object)value.Holder != (Object)null) { value.Holder.SetActive(active && !value.IsDone); } } } } internal static class SpriteAsset { internal static Sprite TopLeftPivotSprite; static SpriteAsset() { TopLeftPivotSprite = GuiManager.MainMenuLayer.PageLoadout.m_readyButton.m_holdBtnProgressSprite.sprite; } } public struct PlayerLoadingState { public static readonly int NumBatches = EnumUtil.GetValueLength(); public int Batch; public int BatchCount; public int BatchCountRemaining; public bool IsDone; public readonly BatchName BatchName { get { if (Batch >= 0) { return (BatchName)Batch; } return (BatchName)0; } } public readonly float BatchProgress { get { if (BatchCountMax <= 0) { return 0f; } return (float)BatchCount / (float)BatchCountMax; } } public readonly int BatchCountMax => BatchCount + BatchCountRemaining; public PlayerLoadingState() { Batch = -1; BatchCount = 0; BatchCountRemaining = 0; IsDone = false; Batch = -1; BatchCount = 0; BatchCountRemaining = 0; IsDone = false; } public void Reset() { Batch = -1; BatchCount = 0; BatchCountRemaining = 0; IsDone = false; } } }