Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs
MapleWheels d2b9ca4c1b [Refactor-Minor]
- Refactored interface definition.
- Plugin Loading System Refactor (incomplete).
2026-02-07 20:10:39 -05:00

460 lines
18 KiB
C#

using System;
using System.IO;
using Barotrauma.LuaCs.Configuration;
using Barotrauma.LuaCs.Services;
using Barotrauma.LuaCs.Services.Compatibility;
using Barotrauma.LuaCs.Services.Processing;
using Barotrauma.Networking;
namespace Barotrauma
{
class LuaCsSetupConfig
{
public bool EnableCsScripting = false;
public bool TreatForcedModsAsNormal = true;
public bool PreferToUseWorkshopLuaSetup = false;
public bool DisableErrorGUIOverlay = false;
public bool HideUserNames
{
get { return LuaCsLogger.HideUserNames; }
set { LuaCsLogger.HideUserNames = value; }
}
public LuaCsSetupConfig() { }
public LuaCsSetupConfig(LuaCsSetupConfig config)
{
EnableCsScripting = config.EnableCsScripting;
TreatForcedModsAsNormal = config.TreatForcedModsAsNormal;
PreferToUseWorkshopLuaSetup = config.PreferToUseWorkshopLuaSetup;
DisableErrorGUIOverlay = config.DisableErrorGUIOverlay;
}
}
internal delegate void LuaCsMessageLogger(string message);
internal delegate void LuaCsErrorHandler(Exception ex, LuaCsMessageOrigin origin);
internal delegate void LuaCsExceptionHandler(Exception ex, LuaCsMessageOrigin origin);
partial class LuaCsSetup : IDisposable
{
public LuaCsSetup()
{
// load services
_servicesProvider = new ServicesProvider();
RegisterServices();
// load manifest
if (!_servicesProvider.TryGetService(out IModConfigCreatorService modConfigSvc))
throw new NullReferenceException("LuaCsSetup: Failed to get mod config parser service!"); // we should crash here
var luaConfig = modConfigSvc.BuildConfigFromManifest(Directory.GetCurrentDirectory() + LuaCsConfigFile);
if (!luaConfig.IsSuccess)
{
Logger.LogResults(luaConfig.ToResult());
throw new FileLoadException("LuaCsSetup: Failed to load config file!");
}
// load resources
RegisterLocalizations();
RegisterConfigs();
LuaForBarotraumaId = new SteamWorkshopId(LuaForBarotraumaSteamId.Value);
return;
//---
void RegisterServices()
{
_servicesProvider.RegisterServiceType<ILoggerService, LoggerService>(ServiceLifetime.Singleton);
_servicesProvider.RegisterServiceType<PerformanceCounterService, PerformanceCounterService>(ServiceLifetime.Singleton);
_servicesProvider.RegisterServiceType<IPackageService, PackageService>(ServiceLifetime.Singleton);
_servicesProvider.RegisterServiceType<IPackageManagementService, PackageManagementService>(ServiceLifetime.Singleton);
_servicesProvider.RegisterServiceType<ILuaScriptService, LuaScriptService>(ServiceLifetime.Singleton);
_servicesProvider.RegisterServiceType<ILuaScriptManagementService, LuaScriptService>(ServiceLifetime.Singleton);
// TODO: IConfigService
// TODO: INetworkingService
// TODO: [Resource Converter/Parser Services]
// TODO: ILocalizationService
// TODO: IEventService
_servicesProvider.Compile();
}
void RegisterLocalizations()
{
LocalizationService.LoadLocalizations(luaConfig.Value.Localizations);
}
void RegisterConfigs()
{
if (ConfigService.AddConfigs(luaConfig.Value.Configs) is { IsSuccess: false } res1)
{
Logger.LogResults(res1);
throw new Exception("LuaCsSetup: Failed to load config!");
}
if (ConfigService.AddConfigsProfiles(luaConfig.Value.ConfigProfiles) is { IsSuccess: false } res2)
{
Logger.LogResults(res2);
throw new Exception("LuaCsSetup: Failed to load config profiles!");
}
IsCsEnabled = GetOrThrowForConfig<bool>(luaConfig.Value.PackageName, "IsCsEnabled");
TreatForcedModsAsNormal = GetOrThrowForConfig<bool>(luaConfig.Value.PackageName, "TreatForcedModsAsNormal");
PreferToUseWorkshopLuaSetup = GetOrThrowForConfig<bool>(luaConfig.Value.PackageName, "PreferToUseWorkshopLuaSetup");
DisableErrorGUIOverlay = GetOrThrowForConfig<bool>(luaConfig.Value.PackageName, "DisableErrorGUIOverlay");
EnableThreadedLoading = GetOrThrowForConfig<bool>(luaConfig.Value.PackageName, "EnableThreadedLoading");
HideUserNamesInLogs = GetOrThrowForConfig<bool>(luaConfig.Value.PackageName, "HideUserNamesInLogs");
LuaForBarotraumaSteamId = GetOrThrowForConfig<ulong>(luaConfig.Value.PackageName, "LuaForBarotraumaSteamId");
return;
//---
IConfigEntry<T> GetOrThrowForConfig<T>(string packName, string internalName) where T : IConvertible, IEquatable<T>
{
var cfgRes = ConfigService.GetConfig<IConfigEntry<T>>(packName, internalName);
if (cfgRes.IsSuccess)
{
return cfgRes.Value;
}
Logger.LogResults(cfgRes.ToResult());
throw new Exception($"LuaCsSetup: Failed to load config for {internalName}!");
}
}
}
#region CONST_DEF
public const string LuaCsConfigFile = "LuaCsConfig.xml";
#if SERVER
public const bool IsServer = true;
public const bool IsClient = false;
#else
public const bool IsServer = false;
public const bool IsClient = true;
#endif
#endregion
#region Services_ConfigVars
/*
* === Singleton Services
*/
private readonly IServicesProvider _servicesProvider;
public PerformanceCounterService PerformanceCounter => _servicesProvider.TryGetService<PerformanceCounterService>(out var svc)
? svc : throw new NullReferenceException("Performance counter service not found!");
public ILoggerService Logger => _servicesProvider.TryGetService<ILoggerService>(out var svc)
? svc : throw new NullReferenceException("Logger service not found!");
public IConfigService ConfigService => _servicesProvider.TryGetService<IConfigService>(out var svc)
? svc : throw new NullReferenceException("Config Manager service not found!");
public IPackageManagementService PackageManagementService => _servicesProvider.TryGetService<IPackageManagementService>(out var svc)
? svc : throw new NullReferenceException("Package Manager service not found!");
public IPluginManagementService PluginManagementService => _servicesProvider.TryGetService<IPluginManagementService>(out var svc)
? svc : throw new NullReferenceException("Plugin Manager service not found!");
public ILuaScriptManagementService LuaScriptService => _servicesProvider.TryGetService<ILuaScriptManagementService>(out var svc)
? svc : throw new NullReferenceException("Lua Script Manager service not found!");
public ILocalizationService LocalizationService => _servicesProvider.TryGetService<ILocalizationService>(out var svc)
? svc : throw new NullReferenceException("Localization Manager service not found!");
public INetworkingService NetworkingService => _servicesProvider.TryGetService<INetworkingService>(out var svc)
? svc : throw new NullReferenceException("Networking Manager service not found!");
public IEventService EventService => _servicesProvider.TryGetService<IEventService>(out var svc)
? svc : throw new NullReferenceException("Networking Manager service not found!");
/*
* === Config Vars
*/
/// <summary>
/// Whether C# plugin code is enabled.
/// </summary>
public IConfigEntry<bool> IsCsEnabled { get; private set; }
/// <summary>
/// Whether mods marked as 'forced' or 'always load' should only be loaded if they're in the enabled mods list.
/// </summary>
public IConfigEntry<bool> TreatForcedModsAsNormal { get; private set; }
/// <summary>
/// Whether the lua script runner from Workshop package should be used over the in-built version.
/// </summary>
public IConfigEntry<bool> PreferToUseWorkshopLuaSetup { get; private set; }
/// <summary>
/// Whether the popup error GUI should be hidden/suppressed.
/// </summary>
public IConfigEntry<bool> DisableErrorGUIOverlay { get; private set; }
/// <summary>
/// [Experimental] Whether multithreading should be used for loading.
/// </summary>
public IConfigEntry<bool> EnableThreadedLoading { get; private set; }
/// <summary>
/// Whether usernames are anonymized or show in logs.
/// </summary>
public IConfigEntry<bool> HideUserNamesInLogs { get; private set; }
private IConfigEntry<ulong> LuaForBarotraumaSteamId { get; set; }
#endregion
#region LegacyRedirects
public ILuaCsHook Hook => this.EventService;
#endregion
/// <summary>
/// Whether mod content is loaded and being executed.
/// </summary>
public bool IsModContentRunning { get; private set; }
public readonly ContentPackageId LuaForBarotraumaId;
public static bool IsRunningInsideWorkshop
{
get
{
#if SERVER
return Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) != Directory.GetCurrentDirectory();
#else
return false; // unnecessary but just keeps things clear that this is NOT for client stuff
#endif
}
}
/*public Script Lua { get; private set; }
public LuaScriptLoader LuaScriptLoader { get; private set; }
public LuaGame Game { get; private set; }
public LuaCsHook Hook { get; private set; }
public LuaCsTimer Timer { get; private set; }
public LuaCsNetworking Networking { get; private set; }
public LuaCsSteam Steam { get; private set; }
// must be available at anytime
private static AssemblyManager _assemblyManager;
public static AssemblyManager AssemblyManager => _assemblyManager ??= new AssemblyManager();
private CsPackageManager _pluginPackageManager;
public CsPackageManager PluginPackageManager => _pluginPackageManager ??= new CsPackageManager(AssemblyManager, this);
private LuaRequire Require { get; set; }
public LuaCsSetupConfig Config { get; private set; }
public MoonSharpVsCodeDebugServer DebugServer { get; private set; }
public bool IsInitialized { get; private set; }*/
private bool ShouldRunCs
{
get
{
#if SERVER
if (GetPackage(CsForBarotraumaId, false, false) != null && GameMain.Server.ServerPeer is LidgrenServerPeer) { return true; }
#endif
return IsCsEnabled.Value;
}
}
[Obsolete("Use AssemblyManager::GetTypesByName()")]
public static Type GetType(string typeName, bool throwOnError = false, bool ignoreCase = false)
{
throw new NotImplementedException();
//return AssemblyManager.GetTypesByName(typeName).FirstOrDefault((Type)null);
}
// Old config ref
/*public void ReadSettings()
{
Config = new LuaCsSetupConfig();
if (File.Exists(configFileName))
{
try
{
using (var file = File.Open(configFileName, FileMode.Open, FileAccess.Read))
{
XDocument document = XDocument.Load(file);
Config.EnableCsScripting = document.Root.GetAttributeBool("EnableCsScripting", Config.EnableCsScripting);
Config.TreatForcedModsAsNormal = document.Root.GetAttributeBool("TreatForcedModsAsNormal", Config.TreatForcedModsAsNormal);
Config.PreferToUseWorkshopLuaSetup = document.Root.GetAttributeBool("PreferToUseWorkshopLuaSetup", Config.PreferToUseWorkshopLuaSetup);
Config.DisableErrorGUIOverlay = document.Root.GetAttributeBool("DisableErrorGUIOverlay", Config.DisableErrorGUIOverlay);
Config.HideUserNames = document.Root.GetAttributeBool("HideUserNames", Config.HideUserNames);
}
}
catch (Exception e)
{
LuaCsLogger.HandleException(e, LuaCsMessageOrigin.LuaCs);
}
}
}
public void WriteSettings()
{
XDocument document = new XDocument();
document.Add(new XElement("LuaCsSetupConfig"));
document.Root.SetAttributeValue("EnableCsScripting", Config.EnableCsScripting);
document.Root.SetAttributeValue("EnableCsScripting", Config.EnableCsScripting);
document.Root.SetAttributeValue("TreatForcedModsAsNormal", Config.TreatForcedModsAsNormal);
document.Root.SetAttributeValue("PreferToUseWorkshopLuaSetup", Config.PreferToUseWorkshopLuaSetup);
document.Root.SetAttributeValue("DisableErrorGUIOverlay", Config.DisableErrorGUIOverlay);
document.Root.SetAttributeValue("HideUserNames", Config.HideUserNames);
document.Save(configFileName);
}*/
public static ContentPackage GetPackage(ContentPackageId id, bool fallbackToAll = true, bool useBackup = false)
{
foreach (ContentPackage package in ContentPackageManager.EnabledPackages.All)
{
if (package.UgcId.ValueEquals(id))
{
return package;
}
}
if (fallbackToAll)
{
foreach (ContentPackage package in ContentPackageManager.LocalPackages)
{
if (package.UgcId.ValueEquals(id))
{
return package;
}
}
foreach (ContentPackage package in ContentPackageManager.AllPackages)
{
if (package.UgcId.ValueEquals(id))
{
return package;
}
}
}
if (useBackup && ContentPackageManager.EnabledPackages.BackupPackages.Regular != null)
{
foreach (ContentPackage package in ContentPackageManager.EnabledPackages.BackupPackages.Regular.Value)
{
if (package.UgcId.ValueEquals(id))
{
return package;
}
}
}
return null;
}
// Old code ref
/*private DynValue DoFile(string file, Table globalContext = null, string codeStringFriendly = null)
{
if (!LuaCsFile.CanReadFromPath(file))
{
throw new ScriptRuntimeException($"dofile: File access to {file} not allowed.");
}
if (!LuaCsFile.Exists(file))
{
throw new ScriptRuntimeException($"dofile: File {file} not found.");
}
return Lua.DoFile(file, globalContext, codeStringFriendly);
}
private DynValue LoadFile(string file, Table globalContext = null, string codeStringFriendly = null)
{
if (!LuaCsFile.CanReadFromPath(file))
{
throw new ScriptRuntimeException($"loadfile: File access to {file} not allowed.");
}
if (!LuaCsFile.Exists(file))
{
throw new ScriptRuntimeException($"loadfile: File {file} not found.");
}
return Lua.LoadFile(file, globalContext, codeStringFriendly);
}
public DynValue CallLuaFunction(object function, params object[] args)
{
// XXX: `lua` might be null if `LuaCsSetup.Stop()` is called while
// a patched function is still running.
if (Lua == null) { return null; }
lock (Lua)
{
try
{
return Lua.Call(function, args);
}
catch (Exception e)
{
LuaCsLogger.HandleException(e, LuaCsMessageOrigin.LuaMod);
}
return null;
}
}
private void SetModulePaths(string[] str)
{
LuaScriptLoader.ModulePaths = str;
}
public void Update()
{
Timer?.Update();
Steam?.Update();
#if CLIENT
Stopwatch luaSw = new Stopwatch();
luaSw.Start();
#endif
Hook?.Call("think");
#if CLIENT
luaSw.Stop();
GameMain.PerformanceCounter.AddElapsedTicks("Think Hook", luaSw.ElapsedTicks);
#endif
}
*/
public void Stop()
{
IsInitialized = false;
}
public void Initialize(bool forceEnableCs = false)
{
if (IsInitialized)
{
Stop();
}
IsInitialized = true;
Logger.Log($"Initializing LuaCs, git revision = {AssemblyInfo.GitRevision}");
}
public void Update()
{
throw new NotImplementedException();
}
public void Reset()
{
throw new NotImplementedException();
}
public void Dispose()
{
// TODO release managed resources here
}
}
}