Fix LuaCs initializing too late for singleplayer campaigns and rework the C# prompt to only show when enabling mods/joining server
This commit is contained in:
@@ -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<bool> onSelection, bool joiningServer)
|
||||
{
|
||||
var res = ReadyToRunNoPrompt();
|
||||
if (res.ShouldRun)
|
||||
{
|
||||
onReadyToRun?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayCsModsPromptClient(res.Item2, (selectedYes) =>
|
||||
{
|
||||
if (selectedYes)
|
||||
{
|
||||
onReadyToRun?.Invoke();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private (bool ShouldRun, ImmutableArray<ContentPackage> PromptPackages) ReadyToRunNoPrompt()
|
||||
{
|
||||
if (this.IsCsEnabled)
|
||||
{
|
||||
return (true, ImmutableArray<ContentPackage>.Empty);
|
||||
}
|
||||
|
||||
if (!ShouldPromptForCs)
|
||||
{
|
||||
return (true, ImmutableArray<ContentPackage>.Empty);
|
||||
}
|
||||
|
||||
ImmutableArray<ContentPackage> 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<ContentPackage> contentPackages, Action<bool> 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(
|
||||
|
||||
@@ -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<CoroutineStatus> WaitForSubmarineHashCalculations(GUIMessageBox messageBox)
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
</Values>
|
||||
</Setting>
|
||||
<Setting Name="UseCaching" Type="bool" Value="true" AllowChangesWhileExecuting="false"/>
|
||||
<Setting Name="CsRunPolicySession" Type="bool" AllowChangesWhileExecuting="false" ShowInMenus="false"/>
|
||||
<Setting Name="IsCsEnabledForSession" Type="bool" AllowChangesWhileExecuting="false" ShowInMenus="false"/>
|
||||
</Settings>
|
||||
</Configuration>
|
||||
|
||||
@@ -85,20 +85,31 @@ namespace Barotrauma
|
||||
public LuaGame Game => _game ??= _servicesProvider.GetService<LuaGame>();
|
||||
public Script Lua => LuaScriptManagementService.InternalScript;
|
||||
|
||||
private ISettingBase<bool> _isCsEnabledForSession;
|
||||
public bool IsCsEnabledForSession
|
||||
{
|
||||
get => _isCsEnabledForSession?.Value ?? false;
|
||||
internal set
|
||||
{
|
||||
_isCsEnabledForSession?.TrySetValue(value);
|
||||
ConfigService.SaveConfigValue(_isCsEnabledForSession);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether C# plugin code is enabled.
|
||||
/// </summary>
|
||||
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<string> _csRunPolicy;
|
||||
private bool ShouldPromptForCs => _csRunPolicy?.Value is "Prompt";
|
||||
|
||||
/// <summary>
|
||||
/// Whether usernames are anonymized or show in logs.
|
||||
@@ -139,6 +150,10 @@ namespace Barotrauma
|
||||
ConfigService.TryGetConfig<ISettingBase<bool>>(luaCsPackage, "UseCaching", out var val5)
|
||||
? val5
|
||||
: null;
|
||||
_isCsEnabledForSession =
|
||||
ConfigService.TryGetConfig<ISettingBase<bool>>(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<RunState> currentState)
|
||||
{
|
||||
EventService.Call("stop");
|
||||
#if CLIENT
|
||||
_isCsEnabledForSession = false;
|
||||
#endif
|
||||
Logger.LogResults(PackageManagementService.StopRunningPackages());
|
||||
Logger.LogMessage("LuaCs running state exited");
|
||||
}
|
||||
|
||||
@@ -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<IEventScreenSelected>(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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user