diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs index 7e41efaf5..023f8fc45 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs @@ -1,106 +1,47 @@ -using System; +using Barotrauma.CharacterEditor; +using Barotrauma.Extensions; +using Barotrauma.LuaCs; +using Barotrauma.LuaCs.Data; +using Barotrauma.Networking; +using Microsoft.Xna.Framework; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.IO; using System.Linq; using System.Text; -using Barotrauma.CharacterEditor; -using Barotrauma.LuaCs; -using Barotrauma.LuaCs.Data; -using Barotrauma.Networking; -using Microsoft.Xna.Framework; +using static System.Collections.Specialized.BitVector32; // ReSharper disable ObjectCreationAsStatement namespace Barotrauma { partial class LuaCsSetup - { - private bool _isClientPromptActive; - private bool _isCsEnabledForSession = false; - - public void CheckRunConditionalHostingCsEnabled(Action onReadyToRun) + { + public void PromptCSharpMods(Action onSelection, bool joiningServer) { - var res = ReadyToRunNoPrompt(); - if (res.ShouldRun) - { - onReadyToRun?.Invoke(); - return; - } - - DisplayCsModsPromptClient(res.Item2, (selectedYes) => - { - if (selectedYes) - { - onReadyToRun?.Invoke(); - } - }); - } - - private (bool ShouldRun, ImmutableArray PromptPackages) ReadyToRunNoPrompt() - { - if (this.IsCsEnabled) - { - return (true, ImmutableArray.Empty); - } - - if (!ShouldPromptForCs) - { - return (true, ImmutableArray.Empty); - } - ImmutableArray contentPackages = PackageManagementService.GetLoadedAssemblyPackages() .Where(p => p.Name != PackageName) .ToImmutableArray(); - return (contentPackages.IsEmpty, contentPackages); - } - - partial void CheckReadyToRun(Action onReadyToRun) - { - var res = ReadyToRunNoPrompt(); - if (res.ShouldRun) + if (_csRunPolicy?.Value is "Enabled") { - onReadyToRun?.Invoke(); + IsCsEnabledForSession = true; + onSelection(true); return; } - - if (GameMain.Client?.ClientPeer is P2POwnerPeer) + else if (_csRunPolicy?.Value is "Disabled") { - SetCsPolicyAndContinue(true); + IsCsEnabledForSession = false; + onSelection(false); return; } - DisplayCsModsPromptClient(res.PromptPackages, (selectedYes) => + if (contentPackages.None()) { - SetCsPolicyAndContinue(selectedYes); + onSelection(true); return; - }); - - void SetCsPolicyAndContinue(bool csSessionExecutionPolicy) - { - var prevRunState = this.CurrentRunState; - if (CurrentRunState >= RunState.Running) - { - SetRunState(RunState.LoadedNoExec); - } - this._isCsEnabledForSession = csSessionExecutionPolicy; - CoroutineManager.Invoke(() => - { - if (CurrentRunState != prevRunState) - { - SetRunState(prevRunState); - } - onReadyToRun?.Invoke(); - }, 0f); } - } - - void DisplayCsModsPromptClient(ImmutableArray contentPackages, Action onSelection) - { - if (_isClientPromptActive) { return; } - - _isClientPromptActive = true; GUIMessageBox messageBox = new GUIMessageBox( TextManager.Get("warning"), @@ -126,22 +67,39 @@ namespace Barotrauma foreach (ContentPackage package in contentPackages) { GUIFrame packageFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.15f), packageListBox.Content.RectTransform), style: "ListBoxElement"); - new GUITextBlock(new RectTransform(new Vector2(1f, 1f), packageFrame.RectTransform), package.Name); + GUILayoutGroup packageLayout = new GUILayoutGroup(new RectTransform(Vector2.One, packageFrame.RectTransform), true, Anchor.CenterLeft); + new GUITextBlock(new RectTransform(new Vector2(0.7f, 1f), packageLayout.RectTransform), package.Name); + new GUIButton(new RectTransform(new Vector2(0.3f, 1f), packageLayout.RectTransform, Anchor.CenterRight), "Open Folder", style: "GUIButtonSmall") + { + OnClicked = (GUIButton button, object obj) => + { + string directory = package.Dir; + if (string.IsNullOrEmpty(directory)) { return false; } + + ToolBox.OpenFileWithShell(directory); + return true; + } + }; } - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0f), msgBoxLayout.RectTransform), "C# mods are not sandboxed, meaning that they have unrestrictive access to your computer, please make sure you trust these mods before you continue. If you are not hosting a server, selecting cancel will only run Lua mods.", wrap: true) + string bodyText = + joiningServer ? + "You are joining a server that includes mods with C# code. These mods are not sandboxed and may access your computer without restrictions. If you trust these mods, select 'Enable C# for this session'. Otherwise, select 'Cancel' to run only Lua mods." + : "You have enabled mods that include C# code. These mods are not sandboxed and may access your computer without restrictions. If you trust these mods, select 'Enable C# for this session'. Otherwise, select 'Cancel' to run only Lua mods."; + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0f), msgBoxLayout.RectTransform), bodyText, wrap: true) { Wrap = true }; GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), messageBox.Content.RectTransform, Anchor.BottomCenter), isHorizontal: false, childAnchor: Anchor.TopCenter); - new GUIButton(new RectTransform(new Vector2(0.8f, 0.0f), buttonLayout.RectTransform), "Continue") + new GUIButton(new RectTransform(new Vector2(0.8f, 0.0f), buttonLayout.RectTransform), "Enable C# for this session") { TextBlock = { AutoScaleHorizontal = true }, OnClicked = (btn, userdata) => { - _isClientPromptActive = false; + IsCsEnabledForSession = true; onSelection(true); messageBox.Close(); return true; @@ -152,7 +110,7 @@ namespace Barotrauma { OnClicked = (btn, userdata) => { - _isClientPromptActive = false; + IsCsEnabledForSession = false; onSelection(false); messageBox.Close(); return true; @@ -201,10 +159,18 @@ namespace Barotrauma case SpriteEditorScreen: case SubEditorScreen: case TestScreen: // notes: TestScreen is a Linux edge case editor screen and is deprecated. - CheckReadyToRun(() => + + if (screen is NetLobbyScreen) + { + PromptCSharpMods(selection => + { + SetRunState(RunState.Running); + }, joiningServer: true); + } + else { SetRunState(RunState.Running); - }); + } break; default: Logger.LogError( diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen/MainMenuScreen.cs index 063d4fcb7..2d1f03114 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen/MainMenuScreen.cs @@ -1015,25 +1015,20 @@ namespace Barotrauma private void TryStartServer() { - LuaCsSetup.Instance.CheckRunConditionalHostingCsEnabled(() => + if (SubmarineInfo.SavedSubmarines.Any(s => s.CalculatingHash)) { - if (SubmarineInfo.SavedSubmarines.Any(s => s.CalculatingHash)) + var waitBox = new GUIMessageBox(TextManager.Get("pleasewait"), TextManager.Get("waitforsubmarinehashcalculations"), new LocalizedString[] { TextManager.Get("cancel") }); + var waitCoroutine = CoroutineManager.StartCoroutine(WaitForSubmarineHashCalculations(waitBox), "WaitForSubmarineHashCalculations"); + waitBox.Buttons[0].OnClicked += (btn, userdata) => { - var waitBox = new GUIMessageBox(TextManager.Get("pleasewait"), TextManager.Get("waitforsubmarinehashcalculations"), new LocalizedString[] { TextManager.Get("cancel") }); - var waitCoroutine = CoroutineManager.StartCoroutine(WaitForSubmarineHashCalculations(waitBox), "WaitForSubmarineHashCalculations"); - waitBox.Buttons[0].OnClicked += (btn, userdata) => - { - CoroutineManager.StopCoroutines(waitCoroutine); - return true; - }; - } - else - { - StartServer(); - } - }); - - + CoroutineManager.StopCoroutines(waitCoroutine); + return true; + }; + } + else + { + StartServer(); + } } private IEnumerable WaitForSubmarineHashCalculations(GUIMessageBox messageBox) diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Config/SettingsShared.xml b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Config/SettingsShared.xml index 103091314..66d855ef6 100644 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Config/SettingsShared.xml +++ b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Config/SettingsShared.xml @@ -10,6 +10,6 @@ - + diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs index 5cffb7a64..bab861816 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs @@ -85,20 +85,31 @@ namespace Barotrauma public LuaGame Game => _game ??= _servicesProvider.GetService(); public Script Lua => LuaScriptManagementService.InternalScript; + private ISettingBase _isCsEnabledForSession; + public bool IsCsEnabledForSession + { + get => _isCsEnabledForSession?.Value ?? false; + internal set + { + _isCsEnabledForSession?.TrySetValue(value); + ConfigService.SaveConfigValue(_isCsEnabledForSession); + } + } + /// /// Whether C# plugin code is enabled. /// public bool IsCsEnabled { #if CLIENT - get => _csRunPolicy?.Value == "Enabled" || _isCsEnabledForSession; + get => _csRunPolicy?.Value == "Enabled" || IsCsEnabledForSession; #elif SERVER // cs settings cannot be changed on the server after launch get => _csRunPolicy?.Value is "Enabled" or "Prompt"; #endif } + private ISettingList _csRunPolicy; - private bool ShouldPromptForCs => _csRunPolicy?.Value is "Prompt"; /// /// Whether usernames are anonymized or show in logs. @@ -139,6 +150,10 @@ namespace Barotrauma ConfigService.TryGetConfig>(luaCsPackage, "UseCaching", out var val5) ? val5 : null; + _isCsEnabledForSession = + ConfigService.TryGetConfig>(luaCsPackage, "IsCsEnabledForSession", out var val6) + ? val6 + : null; if (!ContentPackageManager.EnabledPackages.All.Contains(luaCsPackage)) { @@ -237,14 +252,8 @@ namespace Barotrauma CoroutineManager.Invoke(() => { -#if CLIENT - bool prevCsEnabled = _isCsEnabledForSession; -#endif var state = CurrentRunState; SetRunState(RunState.Unloaded); -#if CLIENT - _isCsEnabledForSession = prevCsEnabled; -#endif SetRunState(state); }); } @@ -266,7 +275,7 @@ namespace Barotrauma SetRunState(state); // restore } - private void SetRunState(RunState targetRunState) + public void SetRunState(RunState targetRunState) { if (CurrentRunState == targetRunState) { @@ -393,9 +402,6 @@ namespace Barotrauma void RunStateRunning_OnExit(State currentState) { EventService.Call("stop"); -#if CLIENT - _isCsEnabledForSession = false; -#endif Logger.LogResults(PackageManagementService.StopRunningPackages()); Logger.LogMessage("LuaCs running state exited"); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/HarmonyEventPatchesService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/HarmonyEventPatchesService.cs index 114b6aa9e..2e5f3994d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/HarmonyEventPatchesService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/HarmonyEventPatchesService.cs @@ -2,6 +2,7 @@ using Barotrauma.LuaCs; using Barotrauma.LuaCs.Events; using Barotrauma.Networking; +using Barotrauma.Steam; using HarmonyLib; using Microsoft.Xna.Framework; using System; @@ -95,6 +96,27 @@ internal class HarmonyEventPatchesService : ISystem _eventService.PublishEvent(x => x.OnScreenSelected(__instance)); } +#if CLIENT + [HarmonyPatch(typeof(MainMenuScreen), "StartGame"), HarmonyPostfix] + public static void MainMenuScreen_StartGame_Pre(Screen __instance) + { + LuaCsSetup.Instance.SetRunState(RunState.Running); + } + + [HarmonyPatch(typeof(MainMenuScreen), "LoadGame"), HarmonyPostfix] + public static void MainMenuScreen_LoadGame_Pre(Screen __instance) + { + LuaCsSetup.Instance.SetRunState(RunState.Running); + } + + [HarmonyPatch(typeof(MutableWorkshopMenu), nameof(MutableWorkshopMenu.Apply)), HarmonyPostfix] + public static void MutableWorkshopMenu_Apply_Post(Screen __instance) + { + LuaCsSetup.Instance.PromptCSharpMods(selection => { }, joiningServer: false); + } + +#endif + [HarmonyPatch(typeof(ContentPackageManager.PackageSource), nameof(ContentPackageManager.PackageSource.Refresh)), HarmonyPostfix] public static void PackageSource_Refresh_Post() {