From 410ad52b599bf5cae611575a195d9026503d075d Mon Sep 17 00:00:00 2001 From: Garrett <52760019+Casimir255@users.noreply.github.com> Date: Tue, 19 Dec 2023 22:37:03 -0600 Subject: [PATCH] - Fixed duplicate component calls - Removed loading screen items in SP - Re-Added custom loading screens for servers --- Components/LoadingScreenComponent.cs | 216 ++++----- Components/PlayersWindowComponent.cs | 3 +- GUI/Screens/GUILoadingScreen.cs | 652 +++++++++++++++++++++++++++ Seamless.cs | 9 +- SeamlessClient.csproj | 1 + Utilities/PatchUtils.cs | 13 + 6 files changed, 763 insertions(+), 131 deletions(-) create mode 100644 GUI/Screens/GUILoadingScreen.cs diff --git a/Components/LoadingScreenComponent.cs b/Components/LoadingScreenComponent.cs index 79271ce..98652ad 100644 --- a/Components/LoadingScreenComponent.cs +++ b/Components/LoadingScreenComponent.cs @@ -18,171 +18,137 @@ using Sandbox.Engine.Networking; using VRage; using VRage.GameServices; using VRageRender; +using Sandbox.Game.Multiplayer; +using Sandbox.Game; +using SeamlessClient.GUI.Screens; +using Sandbox.Engine.Analytics; +using System.IO; +using VRage.FileSystem; namespace SeamlessClient.Components { public class LoadingScreenComponent : ComponentBase { private static MethodInfo LoadMultiplayer; - private static string _loadingScreenTexture = null; - private static string _serverName; + private bool ScannedMods = false; + public static string JoiningServerName { get; private set; } + public static List CustomLoadingTextures { get; private set; } = new List(); + + static Random random = new Random(Guid.NewGuid().GetHashCode()); + delegate void MyDelegate(string text); + + private static List mods; public override void Patch(Harmony patcher) { + var startLoading = PatchUtils.GetMethod(typeof(MySessionLoader), "StartLoading"); var loadingAction = PatchUtils.GetMethod(typeof(MySessionLoader), "LoadMultiplayerSession"); - var loadingScreenDraw = PatchUtils.GetMethod(typeof(MyGuiScreenLoading), "DrawInternal"); - LoadMultiplayer = PatchUtils.GetMethod(typeof(MySession), "LoadMultiplayer"); + patcher.Patch(startLoading, prefix: new HarmonyMethod(Get(typeof(LoadingScreenComponent), nameof(StartLoading)))); + patcher.Patch(loadingAction, postfix: new HarmonyMethod(Get(typeof(LoadingScreenComponent), nameof(LoadMultiplayerSession)))); + } - patcher.Patch(loadingAction, prefix: new HarmonyMethod(Get(typeof(LoadingScreenComponent), nameof(LoadMultiplayerSession)))); - patcher.Patch(loadingScreenDraw, prefix: new HarmonyMethod(Get(typeof(LoadingScreenComponent), nameof(DrawInternal_PRE)))); - patcher.Patch(loadingScreenDraw, postfix: new HarmonyMethod(Get(typeof(LoadingScreenComponent), nameof(DrawInternal_POST)))); - - - base.Patch(patcher); + public static string getRandomLoadingScreen() + { + int randomIndex = random.Next(CustomLoadingTextures.Count); + return CustomLoadingTextures[randomIndex]; } - private static bool LoadMultiplayerSession(MyObjectBuilder_World world, MyMultiplayerBase multiplayerSession) + private static void LoadMultiplayerSession(MyObjectBuilder_World world, MyMultiplayerBase multiplayerSession) { - MyLog.Default.WriteLine("LoadSession() - Start"); - if (!MyWorkshop.CheckLocalModsAllowed(world.Checkpoint.Mods, false)) - { - MyGuiSandbox.AddScreen(MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Error, MyMessageBoxButtonsType.OK, messageCaption: MyTexts.Get(MyCommonTexts.MessageBoxCaptionError), messageText: MyTexts.Get(MyCommonTexts.DialogTextLocalModsDisabledInMultiplayer))); - MyLog.Default.WriteLine("LoadSession() - End"); - return false; - } + //This is the main enty point for the start loading system... + if (Sync.IsServer) + return; - MyWorkshop.DownloadModsAsync(world.Checkpoint.Mods, delegate (MyGameServiceCallResult result) - { - switch (result) - { - case MyGameServiceCallResult.NotEnoughSpace: - MyGuiSandbox.AddScreen(MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Error, MyMessageBoxButtonsType.OK, messageCaption: MyTexts.Get(MyCommonTexts.MessageBoxCaptionError), messageText: MyTexts.Get(MyCommonTexts.DialogTextDownloadModsFailed_NotEnoughSpace), okButtonText: null, cancelButtonText: null, yesButtonText: null, noButtonText: null, callback: delegate - { - MySessionLoader.UnloadAndExitToMenu(); - })); - break; - case MyGameServiceCallResult.OK: - MyScreenManager.CloseAllScreensNowExcept(null); - MyGuiSandbox.Update(16); + JoiningServerName = multiplayerSession.HostName; + mods = world.Checkpoint.Mods; + //GetCustomLoadingScreenPath(world.Checkpoint.Mods); + //Search for any custom loading screens - if (MySession.Static != null) - { - MySession.Static.Unload(); - MySession.Static = null; - } - - MySessionLoader.StartLoading(delegate - { - LoadMultiplayer.Invoke(null, new object[] { world, multiplayerSession }); - }); - - break; - - default: - multiplayerSession.Dispose(); - MySessionLoader.UnloadAndExitToMenu(); - if (MyGameService.IsOnline) - { - MyGuiSandbox.AddScreen(MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Error, MyMessageBoxButtonsType.OK, messageCaption: MyTexts.Get(MyCommonTexts.MessageBoxCaptionError), messageText: MyTexts.Get(MyCommonTexts.DialogTextDownloadModsFailed))); - } - else - { - MyGuiSandbox.AddScreen(MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Error, MyMessageBoxButtonsType.OK, messageCaption: MyTexts.Get(MyCommonTexts.MessageBoxCaptionError), messageText: new StringBuilder(string.Format(MyTexts.GetString(MyCommonTexts.DialogTextDownloadModsFailedSteamOffline), MySession.GameServiceDisplayName)))); - } - break; - } - MyLog.Default.WriteLine("LoadSession() - End"); - }, delegate - { - multiplayerSession.Dispose(); - MySessionLoader.UnloadAndExitToMenu(); - }); - - return false; + return; } - private void OnFinished(MyGameServiceCallResult result) + private static bool StartLoading(Action loadingAction, Action loadingActionXMLAllowed = null, string customLoadingBackground = null, string customLoadingtext = null) { - - } + /* Control what screen is being loaded */ - private static bool DrawInternal_PRE(MyGuiScreenLoading __instance) - { - //If we dont have a custom loading screen texture, do not do the special crap below - - - - - - if (string.IsNullOrEmpty(_loadingScreenTexture)) + //If we are loading into a single player enviroment, skip override + if (Sync.IsServer) return true; - const string mFont = "LoadingScreen"; - var mTransitionAlpha = (float)typeof(MyGuiScreenBase).GetField("m_transitionAlpha", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance); - var color = new Color(255, 255, 255, 250); - color.A = (byte)(color.A * mTransitionAlpha); - var fullscreenRectangle = MyGuiManager.GetFullscreenRectangle(); - MyGuiManager.DrawSpriteBatch("Textures\\GUI\\Blank.dds", fullscreenRectangle, Color.Black, false, true); - Rectangle outRect; - MyGuiManager.GetSafeHeightFullScreenPictureSize(MyGuiConstants.LOADING_BACKGROUND_TEXTURE_REAL_SIZE, - out outRect); - MyGuiManager.DrawSpriteBatch(_loadingScreenTexture, outRect, - new Color(new Vector4(1f, 1f, 1f, mTransitionAlpha)), true, true); - MyGuiManager.DrawSpriteBatch("Textures\\Gui\\Screens\\screen_background_fade.dds", outRect, - new Color(new Vector4(1f, 1f, 1f, mTransitionAlpha)), true, true); - - //MyGuiSandbox.DrawGameLogoHandler(m_transitionAlpha, MyGuiManager.ComputeFullscreenGuiCoordinate(MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_TOP, 44, 68)); - - var loadScreen = $"Loading into {_serverName}! Please wait!"; - - - MyGuiManager.DrawString(mFont, loadScreen, new Vector2(0.5f, 0.95f), - MyGuiSandbox.GetDefaultTextScaleWithLanguage() * 1.1f, - new Color(MyGuiConstants.LOADING_PLEASE_WAIT_COLOR * mTransitionAlpha), - MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_BOTTOM); - - - - - - - - - - /* - if (string.IsNullOrEmpty(m_customTextFromConstructor)) + GetCustomLoadingScreenPath(); + if (MySpaceAnalytics.Instance != null) { - string font = m_font; - Vector2 positionAbsoluteBottomLeft = m_multiTextControl.GetPositionAbsoluteBottomLeft(); - Vector2 textSize = m_multiTextControl.TextSize; - Vector2 normalizedCoord = positionAbsoluteBottomLeft + new Vector2((m_multiTextControl.Size.X - textSize.X) * 0.5f + 0.025f, 0.025f); - MyGuiManager.DrawString(font, m_authorWithDash.ToString(), normalizedCoord, MyGuiSandbox.GetDefaultTextScaleWithLanguage()); + MySpaceAnalytics.Instance.StoreWorldLoadingStartTime(); } - */ - //m_multiTextControl.Draw(1f, 1f); + MyGuiScreenGamePlay newGameplayScreen = new MyGuiScreenGamePlay(); + MyGuiScreenGamePlay myGuiScreenGamePlay = newGameplayScreen; + myGuiScreenGamePlay.OnLoadingAction = (Action)Delegate.Combine(myGuiScreenGamePlay.OnLoadingAction, loadingAction); + + //Use custom loading screen + GUILoadingScreen myGuiScreenLoading = new GUILoadingScreen(newGameplayScreen, MyGuiScreenGamePlay.Static, customLoadingBackground, customLoadingtext); + + myGuiScreenLoading.OnScreenLoadingFinished += delegate + { + if (MySession.Static != null) + { + MyGuiSandbox.AddScreen(MyGuiSandbox.CreateScreen(MyPerGameSettings.GUI.HUDScreen)); + newGameplayScreen.LoadingDone = true; + } + }; + + myGuiScreenLoading.OnLoadingXMLAllowed = loadingActionXMLAllowed; + MyGuiSandbox.AddScreen(myGuiScreenLoading); return false; } - private static void DrawInternal_POST(MyGuiScreenLoading __instance) + + + + public static void GetCustomLoadingScreenPath() { - const string mFont = "LoadingScreen"; - var mTransitionAlpha = (float)typeof(MyGuiScreenBase).GetField("m_transitionAlpha", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance); - MyGuiManager.DrawString(mFont, "Nexus & SeamlessClient Made by: Casimir", new Vector2(0.95f, 0.95f), - MyGuiSandbox.GetDefaultTextScaleWithLanguage() * 1.1f, - new Color(MyGuiConstants.LOADING_PLEASE_WAIT_COLOR * mTransitionAlpha), - MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_BOTTOM); + try + { + //var Mods = world.Checkpoint.Mods; + var Mods = mods; + + Seamless.TryShow("Server Mods: " + Mods); + foreach (var mod in Mods) + { + var searchDir = mod.GetPath(); + + if (!Directory.Exists(searchDir)) + continue; + + var files = Directory.GetFiles(searchDir, "CustomLoadingBackground*.dds", SearchOption.TopDirectoryOnly); + + foreach (var file in files) + { + // Adds all files containing CustomLoadingBackground to a list for later randomisation + Seamless.TryShow(mod.FriendlyName + " contains a custom loading background!"); + CustomLoadingTextures.Add(file); + } + } + } + catch (Exception ex) + { + Seamless.TryShow(ex.ToString()); + } + + Seamless.TryShow(""); + return; } + } } diff --git a/Components/PlayersWindowComponent.cs b/Components/PlayersWindowComponent.cs index eba39c5..aae1cfb 100644 --- a/Components/PlayersWindowComponent.cs +++ b/Components/PlayersWindowComponent.cs @@ -1,6 +1,7 @@ using HarmonyLib; using Sandbox.Game; using Sandbox.Game.Gui; +using Sandbox.Game.Multiplayer; using Sandbox.Game.World; using SeamlessClient.Messages; using SeamlessClient.Utilities; @@ -27,7 +28,7 @@ namespace SeamlessClient.OnlinePlayersWindow public override void Update() { - if (!Seamless.isSeamlessServer) + if (Sync.IsServer) { MyPerGameSettings.GUI.PlayersScreen = typeof(MyGuiScreenPlayers); } diff --git a/GUI/Screens/GUILoadingScreen.cs b/GUI/Screens/GUILoadingScreen.cs new file mode 100644 index 0000000..c076632 --- /dev/null +++ b/GUI/Screens/GUILoadingScreen.cs @@ -0,0 +1,652 @@ +using Sandbox.AppCode; +using Sandbox.Engine.Multiplayer; +using Sandbox.Engine.Networking; +using Sandbox.Engine.Utils; +using Sandbox.Game.Gui; +using Sandbox.Game.Screens; +using Sandbox.Game.World; +using Sandbox.Game; +using Sandbox.Graphics.GUI; +using Sandbox.Graphics; +using Sandbox; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VRage.Audio; +using VRage.Input; +using VRage.Library.Utils; +using VRage.Utils; +using VRage; +using VRageMath; +using VRageRender; +using VRage.Collections; +using Sandbox.Game.Multiplayer; +using Sandbox.Engine.Platform; +using SeamlessClient.Components; +using System.Security.AccessControl; +using System.Reflection; +using System.Timers; + +namespace SeamlessClient.GUI.Screens +{ + public class GUILoadingScreen : MyGuiScreenBase + { + public static readonly int STREAMING_TIMEOUT = 900; + + public static GUILoadingScreen Static; + + private MyGuiScreenBase m_screenToLoad; + + private readonly MyGuiScreenGamePlay m_screenToUnload; + + private string m_backgroundScreenTexture; + + private string m_backgroundTextureFromConstructor; + + private string m_customTextFromConstructor; + + private string m_rotatingWheelTexture; + + private object m_currentText; + + private MyGuiControlMultilineText m_multiTextControl; + + private StringBuilder m_authorWithDash; + + private MyGuiControlRotatingWheel m_wheel; + + private bool m_exceptionDuringLoad; + + public static string LastBackgroundTexture; + + public Action OnLoadingXMLAllowed; + + public static int m_currentTextIdx = 0; + + private volatile bool m_loadInDrawFinished; + + private bool m_loadFinished; + + private bool m_runLoadEnded; + + private bool m_isStreamed; + + private int m_streamingTimeout; + + private float m_progress; + + private int m_displayProgress; + + private float m_localProgress; + + private float m_localTotal; + + private float m_localProgressDelta; + + private float m_localProgressMin; + + private string m_font = "LoadingScreen"; + + private bool m_closed; + + private MyTimeSpan m_loadingTimeStart; + + private static Dictionary _progressMap; + + private Timer backgroundTimer = new Timer(8000); + + + + + /// + /// Event created once the screen has been loaded and added to GUI manager. + /// + public event Action OnScreenLoadingFinished; + + public GUILoadingScreen(MyGuiScreenBase screenToLoad, MyGuiScreenGamePlay screenToUnload, string textureFromConstructor, string customText = null) + : base(Vector2.Zero) + { + base.CanBeHidden = false; + m_isTopMostScreen = true; + + object instance = PatchUtils.GetProperty(PatchUtils.MyLoadingPerformance, "Instance").GetValue(null); + if(instance != null) + PatchUtils.GetMethod(PatchUtils.MyLoadingPerformance, "StartTiming").Invoke(instance, null); + + //MyLoadingPerformance.Instance.StartTiming(); + Static = this; + m_screenToLoad = screenToLoad; + m_screenToUnload = screenToUnload; + m_closeOnEsc = false; + base.DrawMouseCursor = false; + m_loadInDrawFinished = false; + m_drawEvenWithoutFocus = true; + + MethodInfo text = PatchUtils.GetMethod(PatchUtils.MyLoadingScreenText, "GetRandomText"); + m_currentText = text.Invoke(null, null); + //m_currentText = MyLoadingScreenText.GetRandomText(); + + + m_isFirstForUnload = true; + MyGuiSandbox.SetMouseCursorVisibility(false); + m_rotatingWheelTexture = "Textures\\GUI\\screens\\screen_loading_wheel_loading_screen.dds"; + m_backgroundTextureFromConstructor = textureFromConstructor; + m_customTextFromConstructor = customText; + m_loadFinished = false; + if (m_screenToLoad != null) + { + MySandboxGame.IsUpdateReady = false; + MySandboxGame.AreClipmapsReady = !Sync.IsServer || Game.IsDedicated || MyExternalAppBase.Static != null; + MySandboxGame.RenderTasksFinished = Game.IsDedicated || MyExternalAppBase.Static != null; + } + m_authorWithDash = new StringBuilder(); + RecreateControls(true); + MyInput.Static.EnableInput(false); + if (Sync.IsServer || Game.IsDedicated || MyMultiplayer.Static == null) + { + m_isStreamed = true; + } + else + { + MyMultiplayer.Static.LocalRespawnRequested += OnLocalRespawnRequested; + } + MySession.LoadingStep = (Action)Delegate.Combine(MySession.LoadingStep, new Action(SetProgress)); + MySession.LoadingLocalAdd = (Action)Delegate.Combine(MySession.LoadingLocalAdd, new Action(AddLocalProgress)); + MySession.LoadingLocalClear = (Action)Delegate.Combine(MySession.LoadingLocalClear, new Action(ClearLocalProgress)); + MySession.LoadingLocalBoundSet = (Action)Delegate.Combine(MySession.LoadingLocalBoundSet, new Action(SetLocalBounds)); + MySession.LoadingLocalTotalSet = (Action)Delegate.Combine(MySession.LoadingLocalTotalSet, new Action(SetLocalTotal)); + + + + + + + + } + + private void OnLocalRespawnRequested() + { + (MyMultiplayer.Static as MyMultiplayerClientBase).RequestBatchConfirmation(); + MyMultiplayer.Static.PendingReplicablesDone += MyMultiplayer_PendingReplicablesDone; + MyMultiplayer.Static.LocalRespawnRequested -= OnLocalRespawnRequested; + m_streamingTimeout = 0; + } + + private void MyMultiplayer_PendingReplicablesDone() + { + m_isStreamed = true; + if (MySession.Static.VoxelMaps.Instances.Count > 0) + { + MySandboxGame.AreClipmapsReady = false; + } + MyMultiplayer.Static.PendingReplicablesDone -= MyMultiplayer_PendingReplicablesDone; + } + + public GUILoadingScreen(MyGuiScreenBase screenToLoad, MyGuiScreenGamePlay screenToUnload) + : this(screenToLoad, screenToUnload, null) + { + } + + public override void RecreateControls(bool constructor) + { + base.RecreateControls(constructor); + Vector2 vector = MyGuiManager.MeasureString(m_font, MyTexts.Get(MyCommonTexts.LoadingPleaseWaitUppercase), 1.1f); + m_wheel = new MyGuiControlRotatingWheel(MyGuiConstants.LOADING_PLEASE_WAIT_POSITION - new Vector2(0f, 0.09f + vector.Y), MyGuiConstants.ROTATING_WHEEL_COLOR, 0.36f, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, m_rotatingWheelTexture, false, MyPerGameSettings.GUI.MultipleSpinningWheels); + m_multiTextControl = new MyGuiControlMultilineText(contents: string.IsNullOrEmpty(m_customTextFromConstructor) ? new StringBuilder(m_currentText.ToString()) : new StringBuilder(m_customTextFromConstructor), position: new Vector2(0.5f, 0.66f), size: new Vector2(0.9f, 0.2f), backgroundColor: Vector4.One, font: m_font, textScale: 1f, textAlign: MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_BOTTOM, drawScrollbarV: false, drawScrollbarH: false); + m_multiTextControl.BorderEnabled = false; + m_multiTextControl.OriginAlign = MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_BOTTOM; + m_multiTextControl.TextBoxAlign = MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_BOTTOM; + Controls.Add(m_wheel); + + + RefreshText(); + } + + public override string GetFriendlyName() + { + return "GUILoadingScreen"; + } + + public override void LoadContent() + { + m_loadingTimeStart = new MyTimeSpan(Stopwatch.GetTimestamp()); + MySandboxGame.Log.WriteLine("MyGuiScreenLoading.LoadContent - START"); + MySandboxGame.Log.IncreaseIndent(); + m_backgroundScreenTexture = m_backgroundTextureFromConstructor ?? GetRandomBackgroundTexture(); + if (m_screenToUnload != null) + { + m_screenToUnload.IsLoaded = false; + m_screenToUnload.CloseScreenNow(); + } + base.LoadContent(); + MyRenderProxy.LimitMaxQueueSize = true; + if (m_screenToLoad != null && !m_loadInDrawFinished && m_loadFinished) + { + m_screenToLoad.State = MyGuiScreenState.OPENING; + m_screenToLoad.LoadContent(); + } + else + { + m_loadFinished = false; + } + MySandboxGame.Log.DecreaseIndent(); + MySandboxGame.Log.WriteLine("MyGuiScreenLoading.LoadContent - END"); + + + } + + public static string GetRandomBackgroundTexture() + { + + + string text = MyUtils.GetRandomInt(MyPerGameSettings.GUI.LoadingScreenIndexRange.X, MyPerGameSettings.GUI.LoadingScreenIndexRange.Y + 1).ToString().PadLeft(3, '0'); + return "Textures\\GUI\\Screens\\loading_background_" + text + ".dds"; + } + + public override void UnloadContent() + { + if (m_backgroundScreenTexture != null) + { + MyRenderProxy.UnloadTexture(m_backgroundScreenTexture); + } + if (m_backgroundTextureFromConstructor != null) + { + MyRenderProxy.UnloadTexture(m_backgroundTextureFromConstructor); + } + if (m_backgroundScreenTexture != null) + { + MyRenderProxy.UnloadTexture(m_rotatingWheelTexture); + } + if (m_screenToLoad != null && !m_loadFinished && m_loadInDrawFinished) + { + m_screenToLoad.UnloadContent(); + m_screenToLoad.UnloadData(); + m_screenToLoad = null; + } + if (m_screenToLoad != null && !m_loadInDrawFinished) + { + m_screenToLoad.UnloadContent(); + } + MyRenderProxy.LimitMaxQueueSize = false; + base.UnloadContent(); + Static = null; + } + + public override bool Update(bool hasFocus) + { + if (!base.Update(hasFocus)) + { + return false; + } + if (base.State == MyGuiScreenState.OPENED && !m_loadFinished) + { + m_loadFinished = true; + MyHud.ScreenEffects.FadeScreen(0f); + MyAudio.Static.Mute = true; + MyAudio.Static.StopMusic(); + MyAudio.Static.ChangeGlobalVolume(0f, 0f); + MyRenderProxy.DeferStateChanges(true); + DrawLoading(); + if (m_screenToLoad != null) + { + MySandboxGame.Log.WriteLine("RunLoadingAction - START"); + RunLoad(); + Action loadingStep = MySession.LoadingStep; + if (loadingStep != null) + { + loadingStep(LoadingProgress.PROGRESS_STEP10); + } + MySandboxGame.Log.WriteLine("RunLoadingAction - END"); + } + if (m_screenToLoad != null) + { + MyScreenManager.AddScreenNow(m_screenToLoad); + m_screenToLoad.Update(false); + } + m_screenToLoad = null; + m_wheel.ManualRotationUpdate = true; + } + m_streamingTimeout++; + bool flag = Sync.IsServer || Game.IsDedicated || MyMultiplayer.Static == null || !MyFakes.ENABLE_WAIT_UNTIL_MULTIPLAYER_READY || m_isStreamed || (MyFakes.LOADING_STREAMING_TIMEOUT_ENABLED && m_streamingTimeout >= STREAMING_TIMEOUT); + if (m_runLoadEnded && m_loadFinished && ((MySandboxGame.IsGameReady && flag && MySandboxGame.AreClipmapsReady) || m_exceptionDuringLoad) && !m_closed) + { + MyRenderProxy.DeferStateChanges(false); + MyHud.ScreenEffects.FadeScreen(1f, (!MyFakes.TESTING_TOOL_PLUGIN) ? 5f : 0f); + if (MyHud.ScreenEffects.IsBlackscreenFadeInProgress()) + { + MyHudScreenEffects screenEffects = MyHud.ScreenEffects; + screenEffects.OnBlackscreenFadeFinishedCallback = (Action)Delegate.Combine(screenEffects.OnBlackscreenFadeFinishedCallback, new Action(MyGameService.OnLoadingScreenCompleted)); + } + else + { + MyGameService.OnLoadingScreenCompleted(); + } + if (!m_exceptionDuringLoad && this.OnScreenLoadingFinished != null) + { + this.OnScreenLoadingFinished(); + this.OnScreenLoadingFinished = null; + } + CloseScreenNow(); + DrawLoading(); + MyTimeSpan myTimeSpan = new MyTimeSpan(Stopwatch.GetTimestamp()) - m_loadingTimeStart; + MySandboxGame.Log.WriteLine("Loading duration: " + myTimeSpan.Seconds); + m_closed = true; + } + else if (m_loadFinished && !MySandboxGame.AreClipmapsReady && MySession.Static != null && MySession.Static.VoxelMaps.Instances.Count == 0) + { + MySandboxGame.AreClipmapsReady = true; + } + return true; + } + + private void RunLoad() + { + m_exceptionDuringLoad = false; + try + { + m_screenToLoad.RunLoadingAction(); + } + catch (MyLoadingNeedXMLException ex) + { + m_exceptionDuringLoad = true; + if (OnLoadingXMLAllowed != null) + { + UnloadOnException(false); + if (MySandboxGame.Static.SuppressLoadingDialogs) + { + OnLoadingXMLAllowed(); + return; + } + MyGuiSandbox.AddScreen(MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Error, MyMessageBoxButtonsType.OK, MyTexts.Get(MyCommonTexts.LoadingNeedsXML), MyTexts.Get(MyCommonTexts.MessageBoxCaptionInfo), null, null, null, null, delegate + { + OnLoadingXMLAllowed(); + })); + } + else + { + OnLoadException(ex, new StringBuilder(ex.Message), 1.5f); + } + } + catch (MyLoadingException ex2) + { + OnLoadException(ex2, new StringBuilder(ex2.Message), 1.5f); + m_exceptionDuringLoad = true; + } + catch (OutOfMemoryException) + { + throw; + } + catch (Exception e) + { + OnLoadException(e, MyTexts.Get(MyCommonTexts.WorldFileIsCorruptedAndCouldNotBeLoaded)); + m_exceptionDuringLoad = true; + } + finally + { + m_runLoadEnded = true; + } + } + + protected override void OnClosed() + { + MyRenderProxy.DeferStateChanges(false); + base.OnClosed(); + MyInput.Static.EnableInput(true); + MyAudio.Static.Mute = false; + MySession.LoadingStep = (Action)Delegate.Remove(MySession.LoadingStep, new Action(SetProgress)); + MySession.LoadingLocalAdd = (Action)Delegate.Remove(MySession.LoadingLocalAdd, new Action(AddLocalProgress)); + MySession.LoadingLocalClear = (Action)Delegate.Remove(MySession.LoadingLocalClear, new Action(ClearLocalProgress)); + MySession.LoadingLocalBoundSet = (Action)Delegate.Remove(MySession.LoadingLocalBoundSet, new Action(SetLocalBounds)); + MySession.LoadingLocalTotalSet = (Action)Delegate.Remove(MySession.LoadingLocalTotalSet, new Action(SetLocalTotal)); + } + + private void UnloadOnException(bool exitToMainMenu) + { + MyRenderProxy.DeferStateChanges(false); + DrawLoading(); + m_screenToLoad = null; + if (MyGuiScreenGamePlay.Static != null) + { + MyGuiScreenGamePlay.Static.UnloadData(); + MyGuiScreenGamePlay.Static.UnloadContent(); + } + MySandboxGame.IsUpdateReady = true; + MySandboxGame.AreClipmapsReady = true; + MySandboxGame.RenderTasksFinished = true; + if (exitToMainMenu) + { + MySessionLoader.UnloadAndExitToMenu(); + } + else + { + MySessionLoader.Unload(); + } + } + + private void OnLoadException(Exception e, StringBuilder errorText, float heightMultiplier = 1f) + { + MySandboxGame.Log.WriteLine("ERROR: Loading screen failed"); + MySandboxGame.Log.WriteLine(e); + UnloadOnException(true); + MyLoadingNeedDLCException exception; + MyGuiScreenMessageBox myGuiScreenMessageBox; + if ((exception = e as MyLoadingNeedDLCException) != null) + { + myGuiScreenMessageBox = MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Info, MyMessageBoxButtonsType.YES_NO, messageCaption: MyTexts.Get(MyCommonTexts.RequiresAnyDlc), messageText: new StringBuilder().AppendFormat(MyTexts.GetString(MyPlatformGameSettings.LocalizationKeys.ScenarioRequiresDlc), MyTexts.GetString(exception.RequiredDLC.DisplayName)), okButtonText: null, cancelButtonText: null, yesButtonText: null, noButtonText: null, callback: delegate (MyGuiScreenMessageBox.ResultEnum result) + { + if (result == MyGuiScreenMessageBox.ResultEnum.YES) + { + MyGameService.OpenDlcInShop(exception.RequiredDLC.AppId); + } + }); + } + else + { + myGuiScreenMessageBox = MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Error, MyMessageBoxButtonsType.OK, errorText, MyTexts.Get(MyCommonTexts.MessageBoxCaptionError)); + Vector2 value = myGuiScreenMessageBox.Size.Value; + value.Y *= heightMultiplier; + myGuiScreenMessageBox.Size = value; + myGuiScreenMessageBox.RecreateControls(false); + } + MyGuiSandbox.AddScreen(myGuiScreenMessageBox); + } + + public override void HandleInput(bool receivedFocusInThisUpdate) + { + base.HandleInput(receivedFocusInThisUpdate); + } + + public void SetLocalBounds(LoadingProgress start, LoadingProgress end) + { + m_localProgressDelta = _progressMap[end] - _progressMap[start]; + m_localProgressMin = m_progress; + } + + public void ClearLocalProgress() + { + m_localTotal = 1f; + m_localProgress = 0f; + m_localProgressDelta = 0f; + } + + public void SetLocalTotal(float total) + { + m_localTotal = total; + m_localProgress = 0f; + } + + public void AddLocalProgress(float amount = 1f) + { + SetLocalProgress(m_localProgress + amount); + } + + public void SetLocalProgress(float progress) + { + m_localProgress = progress; + if (m_localTotal > 0f) + { + float num = MathHelper.Clamp(m_localProgress / m_localTotal, 0f, 1f); + SetProgress(m_localProgressMin + num * m_localProgressDelta); + } + } + + public void SetProgress(LoadingProgress progress) + { + SetProgress(_progressMap[progress]); + } + + private void SetProgress(float progress) + { + m_progress = progress; + int num = (int)(m_progress * 100f); + if (num != m_displayProgress) + { + m_displayProgress = num; + if (MyUtils.MainThread == System.Threading.Thread.CurrentThread) + { + DrawLoading(); + } + } + } + + public bool DrawLoading() + { + DrawInternal(); + bool result = base.Draw(); + MyRenderProxy.AfterUpdate(null, false); + MyRenderProxy.BeforeUpdate(); + return result; + } + + private void DrawInternal() + { + Color color = new Color(255, 255, 255, 250); + color.A = (byte)((float)(int)color.A * m_transitionAlpha); + Rectangle fullscreenRectangle = MyGuiManager.GetFullscreenRectangle(); + MyGuiManager.DrawSpriteBatch("Textures\\GUI\\Blank.dds", fullscreenRectangle, Color.Black, false, true); + Rectangle outRect; + MyGuiManager.GetSafeHeightFullScreenPictureSize(MyGuiConstants.LOADING_BACKGROUND_TEXTURE_REAL_SIZE, out outRect); + + bool isCustom = false; + if(LoadingScreenComponent.CustomLoadingTextures.Count != 0) + { + if(LoadingScreenComponent.CustomLoadingTextures.Count > 1) + { + if (!backgroundTimer.Enabled) + { + backgroundTimer.Elapsed += BackgroundTimer_Elapsed; + backgroundTimer.Start(); + m_backgroundScreenTexture = LoadingScreenComponent.getRandomLoadingScreen(); + } + + } + else + { + m_backgroundScreenTexture = LoadingScreenComponent.CustomLoadingTextures.First(); + } + + isCustom = true; + } + + + MyGuiManager.DrawSpriteBatch(m_backgroundScreenTexture, outRect, new Color(new Vector4(1f, 1f, 1f, m_transitionAlpha)), true, true); + MyGuiManager.DrawSpriteBatch("Textures\\Gui\\Screens\\screen_background_fade.dds", outRect, new Color(new Vector4(1f, 1f, 1f, m_transitionAlpha)), true, true); + //MyGuiSandbox.DrawGameLogoHandler(m_transitionAlpha, MyGuiManager.ComputeFullscreenGuiCoordinate(MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_TOP, 44, 68), new Vector2(0.005f, 0.19f)); + LastBackgroundTexture = m_backgroundScreenTexture; + + string loading = MyTexts.GetString(MyCommonTexts.LoadingPleaseWaitUppercase); + //If our server name is not empty: + if (!string.IsNullOrEmpty(LoadingScreenComponent.JoiningServerName)) + { + loading = $"Loading into {LoadingScreenComponent.JoiningServerName}..."; + } + + + MyGuiManager.DrawString(m_font, loading, MyGuiConstants.LOADING_PLEASE_WAIT_POSITION, MyGuiSandbox.GetDefaultTextScaleWithLanguage() * 1.1f, new Color(MyGuiConstants.LOADING_PLEASE_WAIT_COLOR * m_transitionAlpha), MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_BOTTOM); + MyGuiManager.DrawString(m_font, string.Format("{0}%", m_displayProgress), MyGuiConstants.LOADING_PERCENTAGE_POSITION, MyGuiSandbox.GetDefaultTextScaleWithLanguage() * 1.1f, new Color(MyGuiConstants.LOADING_PLEASE_WAIT_COLOR * m_transitionAlpha), MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_BOTTOM); + + + + if (!isCustom && string.IsNullOrEmpty(m_customTextFromConstructor)) + { + string font = m_font; + Vector2 positionAbsoluteBottomLeft = m_multiTextControl.GetPositionAbsoluteBottomLeft(); + Vector2 textSize = m_multiTextControl.TextSize; + MyGuiManager.DrawString(normalizedCoord: positionAbsoluteBottomLeft + new Vector2((m_multiTextControl.Size.X - textSize.X) * 0.5f + 0.025f, 0.025f), font: font, text: m_authorWithDash.ToString(), scale: MyGuiSandbox.GetDefaultTextScaleWithLanguage()); + m_multiTextControl.Draw(1f, 1f); + } + + /* Custom draws */ + + MyGuiManager.DrawString(m_font, "Nexus & SeamlessClient Made by: Casimir", new Vector2(0.95f, 0.95f), + MyGuiSandbox.GetDefaultTextScaleWithLanguage() * 1.1f, + new Color(MyGuiConstants.LOADING_PLEASE_WAIT_COLOR * m_transitionAlpha), + MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_BOTTOM); + + + + } + + + + private void BackgroundTimer_Elapsed(object sender, ElapsedEventArgs e) + { + m_backgroundScreenTexture = LoadingScreenComponent.getRandomLoadingScreen(); + } + + + + + public override bool Draw() + { + DrawInternal(); + return base.Draw(); + } + + private void RefreshText() + { + if (string.IsNullOrEmpty(m_customTextFromConstructor)) + { + m_multiTextControl.TextEnum = MyStringId.GetOrCompute(m_currentText.ToString()); + if (m_currentText.GetType() == PatchUtils.MyLoadingScreenQuote) + { + MyStringId author = (MyStringId)PatchUtils.GetField(PatchUtils.MyLoadingScreenQuote, "Author").GetValue(m_currentText); + m_authorWithDash.Clear().Append("- ").AppendStringBuilder(MyTexts.Get(author)) + .Append(" -"); + } + } + } + + public override void OnRemoved() + { + base.OnRemoved(); + } + + static GUILoadingScreen() + { + Dictionary dictionary = new Dictionary(); + dictionary[LoadingProgress.PROGRESS_STEP1] = 0.01f; + dictionary[LoadingProgress.PROGRESS_STEP2] = 0.05f; + dictionary[LoadingProgress.PROGRESS_STEP2_1_BEFORE_COMPILE_SCRIPTS] = 0.05f; + dictionary[LoadingProgress.PROGRESS_STEP2_2_AFTER_COMPILE_SCRIPTS] = 0.2f; + dictionary[LoadingProgress.PROGRESS_STEP2_3_LOAD_DEFINITIONS] = 0.26f; + dictionary[LoadingProgress.PROGRESS_STEP2_4_POST_LOAD_DEFINITIONS] = 0.26f; + dictionary[LoadingProgress.PROGRESS_STEP2_5_BEFORE_LOAD_VOXELS] = 0.3f; + dictionary[LoadingProgress.PROGRESS_STEP2_6_AFTER_LOAD_VOXELS] = 0.4f; + dictionary[LoadingProgress.PROGRESS_STEP2_6_AFTER_LOAD_GAME_DEFINITION] = 0.44f; + dictionary[LoadingProgress.PROGRESS_STEP3] = 0.45f; + dictionary[LoadingProgress.PROGRESS_STEP4] = 0.5f; + dictionary[LoadingProgress.PROGRESS_STEP5] = 0.9f; + dictionary[LoadingProgress.PROGRESS_STEP6] = 0.91f; + dictionary[LoadingProgress.PROGRESS_STEP7] = 0.92f; + dictionary[LoadingProgress.PROGRESS_STEP8] = 0.93f; + dictionary[LoadingProgress.PROGRESS_STEP9] = 0.99f; + dictionary[LoadingProgress.PROGRESS_STEP10] = 1f; + _progressMap = dictionary; + } + + } +} diff --git a/Seamless.cs b/Seamless.cs index c47180b..8b77b46 100644 --- a/Seamless.cs +++ b/Seamless.cs @@ -33,7 +33,7 @@ namespace SeamlessClient private Assembly thisAssembly => typeof(Seamless).Assembly; private bool Initilized = false; public static bool isSeamlessServer { get; private set; } = false; - public static bool isDebug = true; + public static bool isDebug = false; @@ -155,11 +155,10 @@ namespace SeamlessClient { } - - - public void Update() { + allComps.ForEach(x => x.Update()); + if (MyAPIGateway.Multiplayer == null) { isSeamlessServer = false; @@ -174,7 +173,7 @@ namespace SeamlessClient Initilized = true; } - allComps.ForEach(x => x.Update()); + } diff --git a/SeamlessClient.csproj b/SeamlessClient.csproj index 62260cc..36f619a 100644 --- a/SeamlessClient.csproj +++ b/SeamlessClient.csproj @@ -99,6 +99,7 @@ + diff --git a/Utilities/PatchUtils.cs b/Utilities/PatchUtils.cs index e4fe10d..925668f 100644 --- a/Utilities/PatchUtils.cs +++ b/Utilities/PatchUtils.cs @@ -45,6 +45,19 @@ namespace SeamlessClient.Components public static readonly Type MySlimBlockType = Type.GetType("Sandbox.Game.Entities.Cube.MySlimBlock, Sandbox.Game"); + public static readonly Type MyLoadingScreenQuote = + Type.GetType("Sandbox.Game.Screens.Helpers.MyLoadingScreenQuote, Sandbox.Game"); + + public static readonly Type MyLoadingScreenHint = + Type.GetType("Sandbox.Game.Screens.Helpers.MyLoadingScreenHint, Sandbox.Game"); + + public static readonly Type MyLoadingPerformance = +Type.GetType("Sandbox.Engine.Utils.MyLoadingPerformance, Sandbox.Game"); + + public static readonly Type MyLoadingScreenText = +Type.GetType("Sandbox.Game.Screens.Helpers.MyLoadingScreenText, Sandbox.Game"); + + /* Harmony Patcher */ private static readonly Harmony Patcher = new Harmony("SeamlessClientPatcher");