diff --git a/.editorconfig b/.editorconfig
index 1592dd774..229463f20 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -29,9 +29,9 @@ dotnet_style_predefined_type_for_locals_parameters_members=true:hint
dotnet_style_predefined_type_for_member_access=true:hint
# Parentheses preferences
-dotnet_style_parentheses_in_arithmetic_binary_operators=always_for_clarity:silent
-dotnet_style_parentheses_in_relational_binary_operators=always_for_clarity:silent
-dotnet_style_parentheses_in_other_binary_operators=always_for_clarity:silent
+dotnet_style_parentheses_in_arithmetic_binary_operators=never_if_unnecessary:silent
+dotnet_style_parentheses_in_relational_binary_operators=never_if_unnecessary:silent
+dotnet_style_parentheses_in_other_binary_operators=never_if_unnecessary:silent
dotnet_style_parentheses_in_other_operators=never_if_unnecessary:silent
# Modifier preferences
diff --git a/.gitignore b/.gitignore
index 8675d7757..dc7f17eeb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@ obj
/Ships
/GameData/FerramAerospaceResearch/Custom*.cfg
/GameData/FerramAerospaceResearch/FARForceDataUpdate.cfg
+GameData/FerramAerospaceResearch/Plugins/FARLogger_*
*.suo
*.DotSettings
*.user
@@ -20,9 +21,6 @@ releases
.pytest_cache
*.pyc
-// unignore Debug build DLLs
-!bin/[Dd]ebug/[Ff]erram*.dll
-
// Rider
.idea
@@ -35,6 +33,7 @@ Unity/FerramAerospaceResearch*/[Oo]bj/
Unity/FerramAerospaceResearch*/[Bb]uild/
Unity/FerramAerospaceResearch*/[Bb]uilds/
Unity/FerramAerospaceResearch*/[Ll]ogs/
+Unity/[Bb]uild/
# Never ignore Asset meta data
!Unity/FerramAerospaceResearch*/[Aa]ssets/**/*.meta
@@ -91,10 +90,14 @@ Unity/FerramAerospaceResearch*/[Aa]ssets/PartTools
Unity/FerramAerospaceResearch*/[Aa]ssets/SquadCore
# External editor scripts
-Unity/FerramAerospaceResearch*/[Aa]ssets/Editor/**/*
+Unity/FerramAerospaceResearch*/[Aa]ssets/Editor/*
!Unity/FerramAerospaceResearch*/[Aa]ssets/Editor/Bundle.cs
!Unity/FerramAerospaceResearch*/[Aa]ssets/Editor/Assets.cs
+!Unity/FerramAerospaceResearch*/[Aa]ssets/Editor/Tests/
# Rider generated files in Unity directory
Unity/FerramAerospaceResearch*/[Aa]ssets/Plugins/Editor*
Unity/FerramAerospaceResearch*/.idea
+
+# burst compiler
+Logs/*
diff --git a/Directory.Build.props b/Directory.Build.props
index 8f72270cc..14ad2bc20 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,8 +1,8 @@
-
- C:\Zaidimai\KSP 1.9.0\
-
+
+ C:\Zaidimai\KSP 1.10\
+
cd "$(SolutionDir)""
python -m buildtools postbuild -f "$(SolutionDir)config.json" -c "$(Configuration)" -t
-
+
diff --git a/FerramAerospaceResearch.Base/Config/DebugConfig.cs b/FerramAerospaceResearch.Base/Config/DebugConfig.cs
new file mode 100644
index 000000000..94b232855
--- /dev/null
+++ b/FerramAerospaceResearch.Base/Config/DebugConfig.cs
@@ -0,0 +1,19 @@
+using FerramAerospaceResearch.Reflection;
+
+namespace FerramAerospaceResearch.Config
+{
+ [ConfigNode("Debug")]
+ public class DebugConfig
+ {
+ [ConfigValue("logLevel")]
+ public static LogLevel Level
+ {
+ get { return FARLogger.Level; }
+ set { FARLogger.Level = value; }
+ }
+
+ // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global - reflection
+ [ConfigValue("dumpOnLoad")]
+ public bool DumpOnLoad { get; set; } = false;
+ }
+}
diff --git a/FerramAerospaceResearch.Base/Config/FlightLogConfig.cs b/FerramAerospaceResearch.Base/Config/FlightLogConfig.cs
new file mode 100644
index 000000000..64b32fd37
--- /dev/null
+++ b/FerramAerospaceResearch.Base/Config/FlightLogConfig.cs
@@ -0,0 +1,29 @@
+using FerramAerospaceResearch.Reflection;
+
+namespace FerramAerospaceResearch.Config
+{
+ [ConfigNode("FlightLog")]
+ public class FlightLogConfig
+ {
+ private string directory = PathUtil.Combine(PathUtil.PParentDir, "Logs", PathUtil.ModDirectoryName);
+
+ [ConfigValue("directory")]
+ public string Directory
+ {
+ get { return directory; }
+ set { directory = PathUtil.Combine(PathUtil.PParentDir, value); }
+ }
+
+ [ConfigValue("nameFormat")]
+ public StringFormatter NameFormat { get; } = new StringFormatter("<<>>_<<>>.csv");
+
+ [ConfigValue("datetimeFormat")]
+ public string DatetimeFormat { get; set; } = "yyyy_MM_dd_HH_mm_ss";
+
+ [ConfigValue("period")]
+ public Observable LogPeriod { get; } = new Observable(50);
+
+ [ConfigValue("flushPeriod")]
+ public Observable FlushPeriod { get; } = new Observable(10);
+ }
+}
diff --git a/FerramAerospaceResearch.Base/Config/GUIColors.cs b/FerramAerospaceResearch.Base/Config/GUIColors.cs
new file mode 100644
index 000000000..26141a23e
--- /dev/null
+++ b/FerramAerospaceResearch.Base/Config/GUIColors.cs
@@ -0,0 +1,44 @@
+using FerramAerospaceResearch.Reflection;
+using UnityEngine;
+
+namespace FerramAerospaceResearch.Config
+{
+ [ConfigNode("GuiColors")]
+ public class GUIColors
+ {
+ private readonly Color[] colors = {Color.cyan, Color.red, Color.yellow, Color.green};
+
+ [ConfigValue]
+ public Color ClColor
+ {
+ get { return colors[0]; }
+ set { colors[0] = value; }
+ }
+
+ [ConfigValue]
+ public Color CdColor
+ {
+ get { return colors[1]; }
+ set { colors[1] = value; }
+ }
+
+ [ConfigValue]
+ public Color CmColor
+ {
+ get { return colors[2]; }
+ set { colors[2] = value; }
+ }
+
+ [ConfigValue("L_DColor")]
+ public Color LdColor
+ {
+ get { return colors[3]; }
+ set { colors[3] = value; }
+ }
+
+ public Color GetColor(int index)
+ {
+ return colors[index];
+ }
+ }
+}
diff --git a/FerramAerospaceResearch.Base/Config/ResourceNode.cs b/FerramAerospaceResearch.Base/Config/ResourceNode.cs
new file mode 100644
index 000000000..5faf0f95c
--- /dev/null
+++ b/FerramAerospaceResearch.Base/Config/ResourceNode.cs
@@ -0,0 +1,52 @@
+using FerramAerospaceResearch.Reflection;
+
+namespace FerramAerospaceResearch.Config
+{
+ public class ResourceNode
+ {
+ public ResourceNode(string url = "", string loader = "default")
+ {
+ Url.Value = url;
+ Loader.Value = loader;
+ }
+
+ [ConfigValue("url")]
+ public Observable Url { get; } = new Observable();
+
+ [ConfigValue("loader")]
+ public Observable Loader { get; } = new Observable("default");
+
+ public static implicit operator string(ResourceNode node)
+ {
+ return node.Url;
+ }
+ }
+
+ [ConfigNode("TEXTURE")]
+ public class TextureNode : ResourceNode
+ {
+ public TextureNode(string url = "", string loader = "default") : base(url, loader)
+ {
+ }
+ }
+
+ [ConfigNode("SHADER")]
+ public class ShaderNode : ResourceNode
+ {
+ public ShaderNode(string url = "", string loader = "default") : base(url, loader)
+ {
+ }
+ }
+
+ [ConfigNode("SHADER")]
+ public class DebugVoxelNode : ShaderNode
+ {
+ public DebugVoxelNode(string url = "", string loader = "default") : base(url, loader)
+ {
+ }
+
+ [ConfigValue("_Cutoff")]
+ // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global - reflection
+ public float Cutoff { get; set; } = 0.45f;
+ }
+}
diff --git a/FerramAerospaceResearch.Base/Config/ShaderConfig.cs b/FerramAerospaceResearch.Base/Config/ShaderConfig.cs
new file mode 100644
index 000000000..cbaec9681
--- /dev/null
+++ b/FerramAerospaceResearch.Base/Config/ShaderConfig.cs
@@ -0,0 +1,32 @@
+using FerramAerospaceResearch.Reflection;
+
+namespace FerramAerospaceResearch.Config
+{
+ [ConfigNode("Shaders")]
+ public class ShaderConfig
+ {
+ [ConfigValue("bundleLinux")]
+ public Observable BundleLinux { get; } =
+ new Observable("FerramAerospaceResearch/Assets/farshaders_linux.far",
+ PathUtil.CombineDelegate(PathUtil.ParentDir));
+
+ [ConfigValue("bundleWindows")]
+ public Observable BundleWindows { get; } =
+ new Observable("FerramAerospaceResearch/Assets/farshaders_windows.far",
+ PathUtil.CombineDelegate(PathUtil.ParentDir));
+
+ [ConfigValue("bundleMac")]
+ public Observable BundleMac { get; } =
+ new Observable("FerramAerospaceResearch/Assets/farshaders_macosx.far",
+ PathUtil.CombineDelegate(PathUtil.ParentDir));
+
+ [ConfigValue("debugVoxel")]
+ public DebugVoxelNode DebugVoxel { get; } = new DebugVoxelNode("FerramAerospaceResearch/Debug Voxel Mesh");
+
+ [ConfigValue("lineRenderer")]
+ public ShaderNode LineRenderer { get; } = new ShaderNode("Hidden/Internal-Colored");
+
+ [ConfigValue("debugVoxelFallback")]
+ public ShaderNode DebugVoxelFallback { get; } = new ShaderNode("Sprites/Default");
+ }
+}
diff --git a/FerramAerospaceResearch.Base/Config/TextureConfig.cs b/FerramAerospaceResearch.Base/Config/TextureConfig.cs
new file mode 100644
index 000000000..b7b60e862
--- /dev/null
+++ b/FerramAerospaceResearch.Base/Config/TextureConfig.cs
@@ -0,0 +1,20 @@
+using FerramAerospaceResearch.Reflection;
+
+namespace FerramAerospaceResearch.Config
+{
+ [ConfigNode("Textures")]
+ public class TextureConfig
+ {
+ [ConfigValue("iconButtonBlizzy")]
+ public TextureNode IconButtonBlizzy { get; } =
+ new TextureNode("FerramAerospaceResearch/Textures/icon_button_blizzy");
+
+ [ConfigValue("iconButtonStock")]
+ public TextureNode IconButtonStock { get; } =
+ new TextureNode("FerramAerospaceResearch/Textures/icon_button_stock");
+
+ [ConfigValue("spriteDebugVoxel")]
+ public TextureNode SpriteDebugVoxel { get; } =
+ new TextureNode("FerramAerospaceResearch/Textures/sprite_debug_voxel");
+ }
+}
diff --git a/FerramAerospaceResearch.Base/FARAddonAttribute.cs b/FerramAerospaceResearch.Base/FARAddonAttribute.cs
new file mode 100644
index 000000000..c67683270
--- /dev/null
+++ b/FerramAerospaceResearch.Base/FARAddonAttribute.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace FerramAerospaceResearch
+{
+ [AttributeUsage(AttributeTargets.Class, Inherited = false)]
+ public class FARAddonAttribute : Attribute
+ {
+ ///
+ /// Whether this addon should have its reference kept after instantiation
+ ///
+ public readonly bool Persistant;
+
+ ///
+ /// Priority of instantiation, higher values get instantiated earlier
+ ///
+ public readonly int Priority;
+
+ public FARAddonAttribute(int priority = 0, bool persistant = false)
+ {
+ Priority = priority;
+ Persistant = persistant;
+ }
+ }
+}
diff --git a/FerramAerospaceResearch.Base/FARAddonLoader.cs b/FerramAerospaceResearch.Base/FARAddonLoader.cs
new file mode 100644
index 000000000..e38d8df22
--- /dev/null
+++ b/FerramAerospaceResearch.Base/FARAddonLoader.cs
@@ -0,0 +1,175 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using FerramAerospaceResearch.Interfaces;
+using FerramAerospaceResearch.Reflection;
+using UnityEngine;
+
+namespace FerramAerospaceResearch
+{
+ ///
+ /// Class to handle instantiation of marked addons, specific implementation needs some entry point to start this
+ ///
+ public class FARAddonLoader : MonoSingleton
+ {
+ ///
+ /// Dictionary of all instantiated (addons, reloadable) objects
+ ///
+ private readonly Dictionary instantiatedTypes = new Dictionary();
+
+ ///
+ /// Dictionary of found addons and their corresponding types
+ ///
+ public List> AddonTypes { get; } = new List>();
+
+ ///
+ /// Dictionary of types found that implement interface/>
+ ///
+ public List ReloadableTypes { get; } = new List();
+
+ ///
+ /// List of persistant addons
+ ///
+ public List