diff --git a/.gitignore b/.gitignore
index a0299529ec..72de34f1ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,9 +3,6 @@
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
-# Nitrox-specific files
-DevVars.targets
-
# User-specific files
*.rsuser
*.suo
diff --git a/DevVars.targets.example b/DevVars.targets.example
deleted file mode 100644
index 2d9aeb8e49..0000000000
--- a/DevVars.targets.example
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
- C:\Program Files\Epic Games\Subnautica
-
-
\ No newline at end of file
diff --git a/Directory.Build.props b/Directory.Build.props
index 09827326dc..a212013c34 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,5 +1,5 @@
-
+
v4.7.2
@@ -7,6 +7,13 @@
false
false
false
+ $(SolutionDir)Nitrox.BuildTool\bin\
+ $(BuildToolDir)generated_files\
+ $(BuildGenDir)publicized_assemblies\
+ AnyCPU
+ prompt
+ 4
+ true
TRACE;DEBUG
@@ -27,26 +34,41 @@
true
-
+
true
true
-
+
-
+
Properties\AssemblyInfoCommon.cs
+
+
+
+
+ {15C4C9C4-683C-4EF0-9E0F-0664A3BDA0CE}
+ Nitrox.BuildTool
+
+ {B16F4DE7-21AD-4FEF-955B-0A5A365FA4E3}
NitroxModel
+
+
+
+
+
+
+
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 9d37423945..8cae6b8ccb 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -1,272 +1,287 @@
-
-
-
+
.netstandard2.0
-
+
-
- $(SubnauticaManaged)\Unity.Timeline.dll
+ $(GameManagedDir)\Unity.Timeline.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.dll
+ $(GameManagedDir)\UnityEngine.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.AccessibilityModule.dll
+ $(GameManagedDir)\UnityEngine.AccessibilityModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.AIModule.dll
+ $(GameManagedDir)\UnityEngine.AIModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.AndroidJNIModule.dll
+ $(GameManagedDir)\UnityEngine.AndroidJNIModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.AnimationModule.dll
+ $(GameManagedDir)\UnityEngine.AnimationModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.ARModule.dll
+ $(GameManagedDir)\UnityEngine.ARModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.AssetBundleModule.dll
+ $(GameManagedDir)\UnityEngine.AssetBundleModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.AudioModule.dll
+ $(GameManagedDir)\UnityEngine.AudioModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.ClothModule.dll
+ $(GameManagedDir)\UnityEngine.ClothModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.ClusterInputModule.dll
+ $(GameManagedDir)\UnityEngine.ClusterInputModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.ClusterRendererModule.dll
+ $(GameManagedDir)\UnityEngine.ClusterRendererModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.CoreModule.dll
+ $(GameManagedDir)\UnityEngine.CoreModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.CrashReportingModule.dll
+ $(GameManagedDir)\UnityEngine.CrashReportingModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.DirectorModule.dll
+ $(GameManagedDir)\UnityEngine.DirectorModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.DSPGraphModule.dll
+ $(GameManagedDir)\UnityEngine.DSPGraphModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.FileSystemHttpModule.dll
+ $(GameManagedDir)\UnityEngine.FileSystemHttpModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.GameCenterModule.dll
+ $(GameManagedDir)\UnityEngine.GameCenterModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.GridModule.dll
+ $(GameManagedDir)\UnityEngine.GridModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.HotReloadModule.dll
+ $(GameManagedDir)\UnityEngine.HotReloadModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.ImageConversionModule.dll
+ $(GameManagedDir)\UnityEngine.ImageConversionModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.IMGUIModule.dll
+ $(GameManagedDir)\UnityEngine.IMGUIModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.InputLegacyModule.dll
+ $(GameManagedDir)\UnityEngine.InputLegacyModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.InputModule.dll
+ $(GameManagedDir)\UnityEngine.InputModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.JSONSerializeModule.dll
+ $(GameManagedDir)\UnityEngine.JSONSerializeModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.LocalizationModule.dll
+ $(GameManagedDir)\UnityEngine.LocalizationModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.ParticleSystemModule.dll
+ $(GameManagedDir)\UnityEngine.ParticleSystemModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.PerformanceReportingModule.dll
+ $(GameManagedDir)\UnityEngine.PerformanceReportingModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.Physics2DModule.dll
+ $(GameManagedDir)\UnityEngine.Physics2DModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.PhysicsModule.dll
+ $(GameManagedDir)\UnityEngine.PhysicsModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.ProfilerModule.dll
+ $(GameManagedDir)\UnityEngine.ProfilerModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.ScreenCaptureModule.dll
+ $(GameManagedDir)\UnityEngine.ScreenCaptureModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.SharedInternalsModule.dll
+ $(GameManagedDir)\UnityEngine.SharedInternalsModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.SpriteMaskModule.dll
+ $(GameManagedDir)\UnityEngine.SpriteMaskModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.SpriteShapeModule.dll
+ $(GameManagedDir)\UnityEngine.SpriteShapeModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.StreamingModule.dll
+ $(GameManagedDir)\UnityEngine.StreamingModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.SubstanceModule.dll
+ $(GameManagedDir)\UnityEngine.SubstanceModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.TerrainModule.dll
+ $(GameManagedDir)\UnityEngine.TerrainModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.TerrainPhysicsModule.dll
+ $(GameManagedDir)\UnityEngine.TerrainPhysicsModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.TextCoreModule.dll
+ $(GameManagedDir)\UnityEngine.TextCoreModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.TextRenderingModule.dll
+ $(GameManagedDir)\UnityEngine.TextRenderingModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.TilemapModule.dll
+ $(GameManagedDir)\UnityEngine.TilemapModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.TLSModule.dll
+ $(GameManagedDir)\UnityEngine.TLSModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UI.dll
+ $(GameManagedDir)\UnityEngine.UI.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UIElementsModule.dll
+ $(GameManagedDir)\UnityEngine.UIElementsModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UIModule.dll
+ $(GameManagedDir)\UnityEngine.UIModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UmbraModule.dll
+ $(GameManagedDir)\UnityEngine.UmbraModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UNETModule.dll
+ $(GameManagedDir)\UnityEngine.UNETModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UnityAnalyticsModule.dll
+ $(GameManagedDir)\UnityEngine.UnityAnalyticsModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UnityConnectModule.dll
+ $(GameManagedDir)\UnityEngine.UnityConnectModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UnityTestProtocolModule.dll
+ $(GameManagedDir)\UnityEngine.UnityTestProtocolModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UnityWebRequestAssetBundleModule.dll
+ $(GameManagedDir)\UnityEngine.UnityWebRequestAssetBundleModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UnityWebRequestAudioModule.dll
+ $(GameManagedDir)\UnityEngine.UnityWebRequestAudioModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UnityWebRequestModule.dll
+ $(GameManagedDir)\UnityEngine.UnityWebRequestModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UnityWebRequestTextureModule.dll
+ $(GameManagedDir)\UnityEngine.UnityWebRequestTextureModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.UnityWebRequestWWWModule.dll
+ $(GameManagedDir)\UnityEngine.UnityWebRequestWWWModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.VehiclesModule.dll
+ $(GameManagedDir)\UnityEngine.VehiclesModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.VFXModule.dll
+ $(GameManagedDir)\UnityEngine.VFXModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.VideoModule.dll
+ $(GameManagedDir)\UnityEngine.VideoModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.VRModule.dll
+ $(GameManagedDir)\UnityEngine.VRModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.WindModule.dll
+ $(GameManagedDir)\UnityEngine.WindModule.dll
$(TestLibrary)
- $(SubnauticaManaged)\UnityEngine.XRModule.dll
+ $(GameManagedDir)\UnityEngine.XRModule.dll
$(TestLibrary)
+
+
+
+
+
+
+
- $(SubnauticaManaged)\Assembly-CSharp.dll
+ $(BuildGenDllDir)\Assembly-CSharp.dll
+ $(TestLibrary)
+
+
+ $(BuildGenDllDir)\Assembly-CSharp-firstpass.dll
+ $(TestLibrary)
+
+
+
+
+
+
+ $(GameManagedDir)\Assembly-CSharp.dll
$(TestLibrary)
-
- $(SubnauticaManaged)\Assembly-CSharp-firstpass.dll
+ $(GameManagedDir)\Assembly-CSharp-firstpass.dll
$(TestLibrary)
diff --git a/Nitrox.BuildTool/Nitrox.BuildTool.csproj b/Nitrox.BuildTool/Nitrox.BuildTool.csproj
new file mode 100644
index 0000000000..55f878f4ba
--- /dev/null
+++ b/Nitrox.BuildTool/Nitrox.BuildTool.csproj
@@ -0,0 +1,38 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {15C4C9C4-683C-4EF0-9E0F-0664A3BDA0CE}
+ Exe
+ Properties
+ BuildTool
+ Nitrox.BuildTool
+ 512
+
+ bin\
+ true
+ full
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.11.3
+
+
+
+
+
+
+
diff --git a/Nitrox.BuildTool/Program.cs b/Nitrox.BuildTool/Program.cs
new file mode 100644
index 0000000000..0e8513217a
--- /dev/null
+++ b/Nitrox.BuildTool/Program.cs
@@ -0,0 +1,96 @@
+using System;
+using System.IO;
+using System.Reflection;
+using System.Threading.Tasks;
+using NitroxModel.Discovery;
+
+namespace BuildTool
+{
+ ///
+ /// Entry point of the build automation project.
+ /// 1. Search for Subnautica install.
+ /// 2. Publicize the .NET dlls and persist for subsequent Nitrox builds.
+ ///
+ public static class Program
+ {
+ private static readonly Lazy processDir =
+ new(() => Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location ?? Directory.GetCurrentDirectory()));
+
+ public static string ProcessDir => processDir.Value;
+
+ public static string GeneratedOutputDir => Path.Combine(ProcessDir, "generated_files");
+
+ public static async Task Main(string[] args)
+ {
+ AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) =>
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine(eventArgs.ExceptionObject);
+ Console.ResetColor();
+
+ Exit((eventArgs.ExceptionObject as Exception)?.HResult ?? 1);
+ };
+
+ GameInstallData game = await Task.Factory.StartNew(EnsureGame).ConfigureAwait(false);
+ Console.WriteLine($"Found game at {game.InstallDir}");
+ await Task.Factory.StartNew(() => EnsurePublicizedAssemblies(game)).ConfigureAwait(false);
+
+ Exit();
+ }
+
+ private static void Exit(int exitCode = 0)
+ {
+ Console.WriteLine();
+ Console.WriteLine("Press any key to continue . . .");
+ Console.ReadKey(true);
+ Environment.Exit(exitCode);
+ }
+
+ private static GameInstallData EnsureGame()
+ {
+ static bool ValidateUnityGame(GameInstallData game, out string error)
+ {
+ if (!File.Exists(Path.Combine(game.InstallDir, "UnityPlayer.dll")))
+ {
+ error = $"Game at: '{game.InstallDir}' is not a Unity game";
+ return false;
+ }
+ if (!Directory.Exists(game.ManagedDllsDir))
+ {
+ error = $"Invalid Unity managed DLLs directory: {game.ManagedDllsDir}";
+ return false;
+ }
+
+ error = null;
+ return true;
+ }
+
+ string cacheFile = Path.Combine(GeneratedOutputDir, "game.props");
+ if (GameInstallData.TryFrom(cacheFile, out GameInstallData game) && !ValidateUnityGame(game, out string error))
+ {
+ throw new Exception(error);
+ }
+
+ game ??= new GameInstallData(GameInstallationFinder.Instance.FindGame());
+ game.TrySave(cacheFile);
+ return game;
+ }
+
+ private static void EnsurePublicizedAssemblies(GameInstallData game)
+ {
+ if (Directory.Exists(Path.Combine(GeneratedOutputDir, "publicized_assemblies")))
+ {
+ Console.WriteLine("Assemblies are already publicized.");
+ return;
+ }
+
+ string[] dllsToPublicize = Directory.GetFiles(game.ManagedDllsDir, "Assembly-*.dll");
+ foreach (string publicizedDll in Publicizer.Execute(dllsToPublicize,
+ "",
+ Path.Combine(GeneratedOutputDir, "publicized_assemblies")))
+ {
+ Console.WriteLine($"Publicized dll: {publicizedDll}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Nitrox.BuildTool/Publicizer.cs b/Nitrox.BuildTool/Publicizer.cs
new file mode 100644
index 0000000000..c59e79a0ec
--- /dev/null
+++ b/Nitrox.BuildTool/Publicizer.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using Mono.Cecil;
+
+namespace BuildTool
+{
+ public static class Publicizer
+ {
+ public static IEnumerable Execute(IEnumerable files, string outputSuffix = "", string outputPath = null)
+ {
+ // Ensure target directory exists.
+ if (string.IsNullOrWhiteSpace(outputPath))
+ {
+ outputPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ }
+ if (!string.IsNullOrWhiteSpace(outputPath))
+ {
+ Directory.CreateDirectory(outputPath);
+ }
+
+ // Create dependency resolve for cecil (needed to write dlls that have other dependencies).
+ DefaultAssemblyResolver resolver = new();
+
+ foreach (string file in files)
+ {
+ if (!File.Exists(file))
+ {
+ throw new FileNotFoundException("Dll to publicize not found", file);
+ }
+ resolver.AddSearchDirectory(Path.GetDirectoryName(file));
+
+ string outputName = $"{Path.GetFileNameWithoutExtension(file)}{outputSuffix}{Path.GetExtension(file)}";
+ string outputFile = Path.Combine(outputPath, outputName);
+ Publicize(file, resolver).Write(outputFile);
+ yield return outputFile;
+ }
+ }
+
+ public static IEnumerable FilterBackingEventFields(List allTypes)
+ {
+ List eventNames = allTypes.SelectMany(t => t.Events)
+ .Select(eventDefinition => eventDefinition.Name)
+ .ToList();
+
+ return allTypes.SelectMany(x => x.Fields)
+ .Where(fieldDefinition => !eventNames.Contains(fieldDefinition.Name));
+ }
+
+ ///
+ /// Method which returns all Types of the given module, including nested ones (recursively).
+ ///
+ /// .NET module to search through for types.
+ /// Types found in module.
+ public static IEnumerable GetAllTypes(ModuleDefinition moduleDefinition) => GetAllNestedTypes(moduleDefinition.Types);
+
+ private static AssemblyDefinition Publicize(string file, BaseAssemblyResolver dllResolver)
+ {
+ AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(file,
+ new ReaderParameters
+ {
+ AssemblyResolver = dllResolver
+ });
+ List allTypes = GetAllTypes(assembly.MainModule).ToList();
+ foreach (TypeDefinition type in allTypes)
+ {
+ if (type == null)
+ {
+ continue;
+ }
+
+ // Publicize type and nested types.
+ if (!type.IsPublic || !type.IsNestedPublic)
+ {
+ if (type.IsNested)
+ {
+ type.IsNestedPublic = true;
+ }
+ else
+ {
+ type.IsPublic = true;
+ }
+ }
+ // Publicize methods on type.
+ foreach (MethodDefinition method in type.Methods)
+ {
+ if (!method?.IsPublic ?? false)
+ {
+ method.IsPublic = true;
+ }
+ }
+ }
+
+ // Publicize all fields (excludes fields if they would cause name conflicts on a type).
+ foreach (FieldDefinition field in FilterBackingEventFields(allTypes))
+ {
+ if (!field?.IsPublic ?? false)
+ {
+ field.IsPublic = true;
+ }
+ }
+
+ return assembly;
+ }
+
+ ///
+ /// Recursive method to get all nested types. Use
+ ///
+ ///
+ ///
+ private static IEnumerable GetAllNestedTypes(IEnumerable typeDefinitions)
+ {
+ IEnumerable defs = typeDefinitions as TypeDefinition[] ?? typeDefinitions.ToArray();
+ if (!defs.Any())
+ {
+ return Array.Empty();
+ }
+
+ return defs.Concat(GetAllNestedTypes(defs.SelectMany(t => t.NestedTypes)));
+ }
+ }
+}
diff --git a/Nitrox.Subnautica.Assets/Nitrox.Subnautica.Assets.shproj b/Nitrox.Subnautica.Assets/Nitrox.Subnautica.Assets.shproj
index 04a5cbd8b4..73ea54b512 100644
--- a/Nitrox.Subnautica.Assets/Nitrox.Subnautica.Assets.shproj
+++ b/Nitrox.Subnautica.Assets/Nitrox.Subnautica.Assets.shproj
@@ -1,5 +1,5 @@
-
+
{0763D551-B1A8-4960-B88A-98833F957936}
@@ -12,4 +12,4 @@
-
\ No newline at end of file
+
diff --git a/Nitrox.sln b/Nitrox.sln
index a01826d583..63aa45aae7 100644
--- a/Nitrox.sln
+++ b/Nitrox.sln
@@ -18,7 +18,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.editorconfig = .editorconfig
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
- SharedConfig.targets = SharedConfig.targets
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NitroxModel-Subnautica", "NitroxModel-Subnautica\NitroxModel-Subnautica.csproj", "{0A377218-6B36-4522-89A3-A39CFC999209}"
@@ -33,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nitrox.Bootloader", "Nitrox
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Nitrox.Subnautica.Assets", "Nitrox.Subnautica.Assets\Nitrox.Subnautica.Assets.shproj", "{0763D551-B1A8-4960-B88A-98833F957936}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nitrox.BuildTool", "Nitrox.BuildTool\Nitrox.BuildTool.csproj", "{15C4C9C4-683C-4EF0-9E0F-0664A3BDA0CE}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Nitrox.Subnautica.Assets\Nitrox.Subnautica.Assets.projitems*{0763d551-b1a8-4960-b88a-98833f957936}*SharedItemsImports = 13
@@ -82,6 +83,10 @@ Global
{E4226522-9189-410B-93B2-792942FBD588}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E4226522-9189-410B-93B2-792942FBD588}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E4226522-9189-410B-93B2-792942FBD588}.Release|Any CPU.Build.0 = Release|Any CPU
+ {15C4C9C4-683C-4EF0-9E0F-0664A3BDA0CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {15C4C9C4-683C-4EF0-9E0F-0664A3BDA0CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {15C4C9C4-683C-4EF0-9E0F-0664A3BDA0CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {15C4C9C4-683C-4EF0-9E0F-0664A3BDA0CE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/NitroxClient/NitroxClient.csproj b/NitroxClient/NitroxClient.csproj
index b2f1e4c015..cb9787fc30 100644
--- a/NitroxClient/NitroxClient.csproj
+++ b/NitroxClient/NitroxClient.csproj
@@ -374,11 +374,11 @@
- $(SubnauticaManaged)\iTween.dll
+ $(GameManagedDir)\iTween.dll
false
- $(SubnauticaManaged)\LitJson.dll
+ $(GameManagedDir)\LitJson.dll
false
@@ -389,4 +389,4 @@
-
\ No newline at end of file
+
diff --git a/NitroxLauncher/NitroxLauncher.csproj b/NitroxLauncher/NitroxLauncher.csproj
index 1b6d744d22..69b7a7acf7 100644
--- a/NitroxLauncher/NitroxLauncher.csproj
+++ b/NitroxLauncher/NitroxLauncher.csproj
@@ -1,5 +1,5 @@
-
+
Debug
@@ -269,4 +269,4 @@
-
\ No newline at end of file
+
diff --git a/NitroxModel-Subnautica/NitroxModel-Subnautica.csproj b/NitroxModel-Subnautica/NitroxModel-Subnautica.csproj
index 8886deff6b..e0bcbf09c2 100644
--- a/NitroxModel-Subnautica/NitroxModel-Subnautica.csproj
+++ b/NitroxModel-Subnautica/NitroxModel-Subnautica.csproj
@@ -94,4 +94,4 @@
-
\ No newline at end of file
+
diff --git a/NitroxModel/Discovery/GameInstallData.cs b/NitroxModel/Discovery/GameInstallData.cs
new file mode 100644
index 0000000000..0a43832adb
--- /dev/null
+++ b/NitroxModel/Discovery/GameInstallData.cs
@@ -0,0 +1,93 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Xml;
+using NitroxModel.Helper;
+
+namespace NitroxModel.Discovery
+{
+ ///
+ /// Game definition data gathered from Steam's files.
+ ///
+ public class GameInstallData
+ {
+ private string managedDllsDir;
+ public string InstallDir { get; private set; }
+
+ public string ManagedDllsDir => managedDllsDir ??= Directory.EnumerateDirectories(InstallDir, "Managed", SearchOption.AllDirectories).FirstOrDefault();
+
+ private GameInstallData()
+ {
+ // Required for serialization
+ }
+
+ public GameInstallData(string installDir)
+ {
+ Validate.NotNull(installDir, $"Argument '{nameof(installDir)}' must not be null.");
+ InstallDir = installDir;
+ }
+
+ public static bool TryFrom(string path, out GameInstallData result)
+ {
+ try
+ {
+ GameInstallData game = new();
+ XmlDocument xDoc = new();
+ xDoc.Load(path);
+ XmlNamespaceManager nsManager = new(xDoc.NameTable);
+ nsManager.AddNamespace("d", xDoc.DocumentElement.NamespaceURI);
+ foreach (XmlElement elem in xDoc.DocumentElement.SelectNodes("//d:PropertyGroup/*", nsManager))
+ {
+ switch (elem.Name)
+ {
+ case "GameDir":
+ game.InstallDir = elem.LastChild.Value;
+ break;
+ case "GameManagedDir":
+ if (!Directory.Exists(elem.LastChild.Value))
+ {
+ throw new DirectoryNotFoundException();
+ }
+ game.managedDllsDir = elem.LastChild.Value;
+ break;
+ }
+ }
+
+ result = game;
+ return true;
+ }
+ catch (Exception)
+ {
+ result = null;
+ return false;
+ }
+ }
+
+ public void TrySave(string path)
+ {
+ static string PostfixBackslash(string text)
+ {
+ return text switch
+ {
+ null => null,
+ "" => "\\",
+ _ => text.TrimEnd('\\') + '\\'
+ };
+ }
+
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+ using XmlTextWriter writer = new(path, Encoding.UTF8)
+ {
+ Formatting = Formatting.Indented
+ };
+ writer.WriteStartElement("Project");
+ writer.WriteAttributeString("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
+ writer.WriteStartElement("PropertyGroup");
+ writer.WriteElementString("GameDir", PostfixBackslash(InstallDir));
+ writer.WriteElementString("GameManagedDir", PostfixBackslash(ManagedDllsDir));
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+ }
+}
diff --git a/NitroxModel/Discovery/GameInstallationFinder.cs b/NitroxModel/Discovery/GameInstallationFinder.cs
index c444bc1205..f8e0889422 100644
--- a/NitroxModel/Discovery/GameInstallationFinder.cs
+++ b/NitroxModel/Discovery/GameInstallationFinder.cs
@@ -28,11 +28,7 @@ public class GameInstallationFinder : IFindGameInstallation
public string FindGame(IList errors = null)
{
- if (errors == null)
- {
- errors = new List();
- }
-
+ errors ??= new List();
foreach (IFindGameInstallation finder in finders)
{
string path = finder.FindGame(errors);
@@ -55,7 +51,7 @@ public static bool IsSubnauticaDirectory(string directory)
return false;
}
- return Directory.EnumerateFileSystemEntries(directory, "*.exe")
+ return Directory.EnumerateFiles(directory, "*.exe")
.Any(file => Path.GetFileName(file)?.Equals("subnautica.exe", StringComparison.OrdinalIgnoreCase) ?? false);
}
}
diff --git a/NitroxModel/Logger/Log.cs b/NitroxModel/Logger/Log.cs
index 7c93dc4797..38794e2753 100644
--- a/NitroxModel/Logger/Log.cs
+++ b/NitroxModel/Logger/Log.cs
@@ -14,7 +14,8 @@ namespace NitroxModel.Logger
{
public static class Log
{
- private static ILogger logger;
+ private static ILogger logger = Serilog.Core.Logger.None;
+ private static bool isSetup;
public static string PlayerName
{
@@ -27,10 +28,12 @@ public static string PlayerName
public static void Setup(bool asyncConsoleWriter = false, InGameLogger inGameLogger = null, bool isConsoleApp = false, bool useConsoleLogging = true)
{
- if (logger != null)
+ if (isSetup)
{
throw new Exception($"{nameof(Log)} setup should only be executed once.");
}
+ isSetup = true;
+
PlayerName = "";
logger = new LoggerConfiguration()
.MinimumLevel.Debug()
diff --git a/NitroxModel/NitroxModel.csproj b/NitroxModel/NitroxModel.csproj
index 62ea5a5c58..5867fc485c 100644
--- a/NitroxModel/NitroxModel.csproj
+++ b/NitroxModel/NitroxModel.csproj
@@ -77,6 +77,7 @@
+
diff --git a/NitroxServer-Subnautica/NitroxServer-Subnautica.csproj b/NitroxServer-Subnautica/NitroxServer-Subnautica.csproj
index 1fcf742764..1d95f43d33 100644
--- a/NitroxServer-Subnautica/NitroxServer-Subnautica.csproj
+++ b/NitroxServer-Subnautica/NitroxServer-Subnautica.csproj
@@ -1,5 +1,5 @@
-
+
Debug
diff --git a/NitroxServer/NitroxServer.csproj b/NitroxServer/NitroxServer.csproj
index f36e1ab695..cb7ba90dc3 100644
--- a/NitroxServer/NitroxServer.csproj
+++ b/NitroxServer/NitroxServer.csproj
@@ -248,4 +248,4 @@
-
\ No newline at end of file
+
diff --git a/NitroxTest/NitroxTest.csproj b/NitroxTest/NitroxTest.csproj
index 941ced3e95..4997a1ed51 100644
--- a/NitroxTest/NitroxTest.csproj
+++ b/NitroxTest/NitroxTest.csproj
@@ -1,5 +1,5 @@
-
+
Debug
AnyCPU
@@ -109,10 +109,6 @@
{ed5034bd-66b5-4596-94b7-66a28d3eff49}
NitroxClient
-
- {b16f4de7-21ad-4fef-955b-0a5a365fa4e3}
- NitroxModel
-
{0a377218-6b36-4522-89a3-a39cfc999209}
NitroxModel-Subnautica
diff --git a/SharedConfig.targets b/SharedConfig.targets
deleted file mode 100644
index 03d328ca4a..0000000000
--- a/SharedConfig.targets
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
- DevVars.targets
- $(SolutionDir)\$(DevVars)
- C:\Program Files (x86)\Steam\steamapps\common\Subnautica
-
-
-
- false
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SubnauticaDir)\Subnautica_Data\Managed
-
-
-
-
-
-
-
- $(SolutionDir)\bin\$(Configuration)\
-
-