Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/X606/SpaceWarp
Browse files Browse the repository at this point in the history
  • Loading branch information
shanepaton committed Feb 27, 2023
2 parents f1b282e + f202237 commit c680451
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 108 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ Note: Use at your own risk, as this is an early version that is expected to unde

To compile this project, you will need to follow these steps:

1. Copy everything in the `Kerbal Space Program 2\KSP2_x64_Data\Managed` folder into the `external_dlls/` folder.
2. Run one of the build scripts (see below for more info) and copy the contents from the correct build output directory into the KSP2 root directory.
3. Launch KSP2 and wait until the title screen appears. You should see a mods folder under the `SpaceWarp` folder.
4. Drag any mods that follow the structure below into that mods folder.
1. Install NuGet
2. Copy everything in the `Kerbal Space Program 2\KSP2_x64_Data\Managed` folder into the `external_dlls/` folder.
3. Run one of the build scripts (see below for more info) and copy the contents from the correct build output directory into the KSP2 root directory.
4. Launch KSP2 and wait until the title screen appears. You should see a mods folder under the `SpaceWarp` folder.
5. Drag any mods that follow the structure below into that mods folder.

Mods are currently implemented as monobehaviours with two fields: a `Logger` for logging and a `Manager` that points to Spacewarp. A mod template generator exists as a Python script.

Expand Down
2 changes: 1 addition & 1 deletion SpaceWarp/API/Logging/ModLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private void InternalLog(LogLevel level, string message)

protected override void Log(LogLevel level, string message)
{
if ((int)level >= StartupManager.SpaceWarpObject.SpaceWarpConfiguration.LogLevel)
if ((int)level >= SpaceWarpGlobalConfiguration.Instance.LogLevel)
{
InternalLog(level,message);
}
Expand Down
56 changes: 53 additions & 3 deletions SpaceWarp/API/SpaceWarpGlobalConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,63 @@
using System.ComponentModel;
using System;
using System.ComponentModel;
using System.IO;
using Newtonsoft.Json;
using UnityEngine;

namespace SpaceWarp.API
{
[JsonObject(MemberSerialization.OptIn)]
public class SpaceWarpGlobalConfiguration
{
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue((int)Logging.LogLevel.Info)]
public static SpaceWarpGlobalConfiguration Instance;
private const string MODS_FOLDER_NAME = "Mods";
public static string SPACE_WARP_PATH = Directory.GetCurrentDirectory() + "/SpaceWarp/";
public static string MODS_FULL_PATH = SPACE_WARP_PATH + MODS_FOLDER_NAME;

private static string SPACEWARP_CONFIG_FULL_PATH = MODS_FULL_PATH + "/" + SPACE_WARP_CONFIG_FILE_NAME;
private const string SPACE_WARP_CONFIG_FILE_NAME = "space_warp_config.json";

/// <summary>
/// Loading Global Configuration and puting it into Instance.
/// </summary>
public static void Init()
{
if (!File.Exists(SPACEWARP_CONFIG_FULL_PATH))
{
Instance = new SpaceWarpGlobalConfiguration();
Instance.ApplyDefaultValues();
}
else
{
try
{
string json = File.ReadAllText(SPACEWARP_CONFIG_FULL_PATH);
Instance = JsonConvert.DeserializeObject<SpaceWarpGlobalConfiguration>(json);
}
catch (Exception exception)
{
//TODO: log this in a nicer way, for now I guess we can just construct a new logger
Debug.LogError($"Loading space warp config failed\nException: {exception}");

File.Delete(SPACEWARP_CONFIG_FULL_PATH);
Init();
return;
}
}

try
{
File.WriteAllLines(SPACEWARP_CONFIG_FULL_PATH, new[] { JsonConvert.SerializeObject(Instance) });
}
catch (Exception exception)
{
//TODO: log this in a nicer way, for now I guess we can just construct a new logger
Debug.LogError($"Saving the spacewarp config failed\nException: {exception}");
}
}

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue((int)Logging.LogLevel.Info)]
public int LogLevel { get; set; }

public void ApplyDefaultValues()
Expand Down
46 changes: 1 addition & 45 deletions SpaceWarp/API/SpaceWarpManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ public class SpaceWarpManager : Manager
public static string SPACE_WARP_PATH = Directory.GetCurrentDirectory() + "/SpaceWarp/";
public static string MODS_FULL_PATH = SPACE_WARP_PATH + MODS_FOLDER_NAME;

private const string SPACE_WARP_CONFIG_FILE_NAME = "space_warp_config.json";
private static string SPACEWARP_CONFIG_FULL_PATH = MODS_FULL_PATH + "/" + SPACE_WARP_CONFIG_FILE_NAME;

public SpaceWarpGlobalConfiguration SpaceWarpConfiguration;

private readonly List<Mod> _allModScripts = new List<Mod>();
Expand All @@ -56,7 +53,6 @@ protected override void Start()
private void Initialize()
{
InitializeConfigManager();
InitializeSpaceWarpConfig();

InitializeModLogger();

Expand Down Expand Up @@ -481,7 +477,7 @@ private void InitializeModConfig(Type config_type, string mod_id)
_modLogger.Error($"Loading mod config failed\nException: {exception}");

File.Delete(config_path);
InitializeSpaceWarpConfig();
InitializeModConfig(config_type, mod_id);
return;
}
}
Expand All @@ -500,46 +496,6 @@ private void InitializeModConfig(Type config_type, string mod_id)
configurationManager.Add(mod_id,(config_type,modConfiguration,config_path));
}
}

/// <summary>
/// Tried to find the SpaceWarp config file in the game, if none is found one is created.
/// </summary>
/// <param name="spaceWarpGlobalConfiguration"></param>
private void InitializeSpaceWarpConfig()
{
if (!File.Exists(SPACEWARP_CONFIG_FULL_PATH))
{
SpaceWarpConfiguration = new SpaceWarpGlobalConfiguration();
SpaceWarpConfiguration.ApplyDefaultValues();
}
else
{
try
{
string json = File.ReadAllText(SPACEWARP_CONFIG_FULL_PATH);
SpaceWarpConfiguration = JsonConvert.DeserializeObject<SpaceWarpGlobalConfiguration>(json);
}
catch (Exception exception)
{
//TODO: log this in a nicer way, for now I guess we can just construct a new logger
new ModLogger("Space Warp").Error($"Loading space warp config failed\nException: {exception}");

File.Delete(SPACEWARP_CONFIG_FULL_PATH);
InitializeSpaceWarpConfig();
return;
}
}

try
{
File.WriteAllLines(SPACEWARP_CONFIG_FULL_PATH, new[] { JsonConvert.SerializeObject(SpaceWarpConfiguration) });
}
catch(Exception exception)
{
//TODO: log this in a nicer way, for now I guess we can just construct a new logger
new ModLogger("Space Warp").Error($"Saving the spacewarp config failed\nException: {exception}");
}
}

/// <summary>
/// Initializes a mod object.
Expand Down
20 changes: 19 additions & 1 deletion SpaceWarp/Compilation/ModCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,26 @@ private static Assembly CompileNewAssemblyAndCache(string modID, string modSrcPa

var compilation = CSharpCompilation.Create(modID + ".dll", trees, references,
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true));

var result = compilation.Emit(CACHE_LOCATION + modID + ".dll");
return Assembly.LoadFile(CACHE_LOCATION + modID + ".dll");
foreach (Diagnostic diagnostic in result.Diagnostics)
{
if (diagnostic.WarningLevel == 0)
{
_logger.Error(diagnostic.ToString());
}
else
{
_logger.Info(diagnostic.ToString());
}
}

_logger.Info(result.ToString());
if (!result.Success)
{
File.Delete(CACHE_LOCATION + modID + ".dll");
}
return !result.Success ? null : Assembly.LoadFile(CACHE_LOCATION + modID + ".dll");
}
}
}
3 changes: 3 additions & 0 deletions SpaceWarp/Entrypoint.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using HarmonyLib;
using KSP.Logging;
using SpaceWarp.API;
using SpaceWarp.UI;
using System.Reflection;
using UnityEngine.SceneManagement;
Expand All @@ -22,6 +23,8 @@ public class SpaceWarpEntrypoint
/// </summary>
public static void Start()
{
SpaceWarpGlobalConfiguration.Init();

SceneManager.sceneLoaded += OnSceneLoaded;

KspLogManager.AddLogCallback(SpaceWarpConsoleLogListener.LogCallback);
Expand Down
4 changes: 2 additions & 2 deletions SpaceWarp/UI/ModConfigurationSection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class ModConfigurationSection
{
public bool Open = false;

public readonly List<(string name, FieldInfo info, object confAttribute)> Properties = new List<(string name, FieldInfo info, object confAttribute)>();
public readonly List<(string name, FieldInfo info, object confAttribute, string currentStringValue)> Properties = new List<(string name, FieldInfo info, object confAttribute, string currentStringValue)>();
public readonly List<(string path, ModConfigurationSection section)> SubSections = new List<(string path, ModConfigurationSection section)>();

private ModConfigurationSection TouchSubSection(string subsection)
Expand All @@ -25,7 +25,7 @@ private ModConfigurationSection TouchSubSection(string subsection)
return sub2;

}
public void Insert(string[] path, (string name, FieldInfo info, object confAttribute) property)
public void Insert(string[] path, (string name, FieldInfo info, object confAttribute, string currentStringValue) property)
{
StringBuilder sb = new StringBuilder();
foreach (string t in path)
Expand Down
72 changes: 48 additions & 24 deletions SpaceWarp/UI/ModConfigurationUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using SpaceWarp.API.Configuration;
using SpaceWarp.API.Managers;
using UnityEngine;
using UnityEngine.Serialization;

namespace SpaceWarp.UI
{
Expand All @@ -14,16 +15,15 @@ public class ModConfigurationUI : KerbalMonoBehaviour
public Type ConfigurationType;
public object ConfigurationObject;

public string ModName;
public string ModID;
[FormerlySerializedAs("ModID")] public string modID;

private int _windowWidth = 350;
private int _windowHeight = 700;
private Rect _windowRect;

private static GUIStyle _boxStyle;

private readonly ModConfigurationSection _rootSection = new ModConfigurationSection();
private ModConfigurationSection _rootSection;

private void Awake()
{
Expand All @@ -33,6 +33,7 @@ private void Awake()

public void Start()
{
_rootSection = new ModConfigurationSection();
foreach (FieldInfo field in ConfigurationType.GetFields(BindingFlags.Instance | BindingFlags.Public))
{
object attribute;
Expand All @@ -48,17 +49,19 @@ public void Start()

ConfigFieldAttribute fieldAttribute = field.GetCustomAttribute<ConfigFieldAttribute>();

if (fieldAttribute != null)
if (fieldAttribute == null)
{
attribute = fieldAttribute;
attributeName = fieldAttribute.Name;
_rootSection.Insert(section.Split(new []{'/'},StringSplitOptions.RemoveEmptyEntries), (attributeName, field, attribute));
// attribute = fieldAttribute;
// attributeName = fieldAttribute.Name;
// _rootSection.Insert(section.Split(new []{'/'},StringSplitOptions.RemoveEmptyEntries), (attributeName, field, attribute, field.GetValue(ConfigurationObject).ToString()));
continue;
}

attribute = fieldAttribute;
attributeName = fieldAttribute?.Name;
attributeName = fieldAttribute.Name;

_rootSection.Insert(section.Split(new []{'/'},StringSplitOptions.RemoveEmptyEntries), (attributeName, field, attribute));
var value = field.GetValue(ConfigurationObject);
_rootSection.Insert(section.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries),
(attributeName, field, attribute, value != null ? value.ToString() : ""));
}

_windowRect = new Rect((Screen.width * 0.15f), (Screen.height * 0.15f), 0, 0);
Expand All @@ -67,42 +70,56 @@ public void Start()
public void OnGUI()
{
int controlID = GUIUtility.GetControlID(FocusType.Passive);
string header = $"{ModID} configuration";
string header = $"{modID} configuration";

GUILayoutOption width = GUILayout.Width((float)(_windowWidth * 0.5));
GUILayoutOption height = GUILayout.Height((float)(_windowHeight * 0.5));

_windowRect = GUILayout.Window(controlID, _windowRect, FillWindow, header, width, height);
}

private void EditorInputField(string fieldName, FieldInfo info)
private string EditorInputField(string fieldName, FieldInfo info, string current)
{
var result = "";
GUILayout.BeginHorizontal();

if (info.FieldType != typeof(bool))
{
GUILayout.Label(fieldName);

string rawInputValue = GUILayout.TextField(info.GetValue(ConfigurationObject).ToString());
object convertedInputValue = TypeDescriptor.GetConverter(info.FieldType).ConvertFromInvariantString(rawInputValue);

info.SetValue(ConfigurationObject, convertedInputValue);
string rawInputValue = GUILayout.TextField(current);
result = rawInputValue;
try
{
object convertedInputValue = TypeDescriptor.GetConverter(info.FieldType)
.ConvertFromInvariantString(rawInputValue);
info.SetValue(ConfigurationObject, convertedInputValue);
}
catch
{
// ignored
}
}
else
{
bool toggleValue = GUILayout.Toggle((bool)info.GetValue(ConfigurationObject), fieldName);

result = toggleValue.ToString();
info.SetValue(ConfigurationObject, toggleValue);
}

GUILayout.EndHorizontal();
return result;
}

private void EditorForField((string name, FieldInfo info, object confAttribute) field)
private string EditorForField((string name, FieldInfo info, object confAttribute, string currentStringValue) field)
{
if (field.confAttribute is ConfigFieldAttribute)
{
EditorInputField(field.name, field.info);
return EditorInputField(field.name, field.info, field.currentStringValue);
}
else
{
return "";
}
}

Expand All @@ -118,9 +135,13 @@ private void SectionPropertyViewer(string sectionName, ModConfigurationSection s
return;
}

foreach ((string name, FieldInfo info, object confAttribute) property in section.Properties)

for (int i = 0; i < section.Properties.Count; i++)
{
EditorForField(property);
var prop = section.Properties[i];
var str = EditorForField(prop);
prop.currentStringValue = str;
section.Properties[i] = prop;
}

foreach ((string path, ModConfigurationSection section) sub in section.SubSections)
Expand All @@ -140,9 +161,12 @@ private void FillWindow(int windowID)
GUILayout.BeginVertical();

// These are the root properties
foreach ((string name, FieldInfo info, object confAttribute) field in _rootSection.Properties)
for (int i = 0; i < _rootSection.Properties.Count; i++)
{
EditorForField(field);
var prop = _rootSection.Properties[i];
var str = EditorForField(prop);
prop.currentStringValue = str;
_rootSection.Properties[i] = prop;
}

foreach ((string path, ModConfigurationSection section) section in _rootSection.SubSections)
Expand All @@ -155,7 +179,7 @@ private void FillWindow(int windowID)
//Run saving code from the configuration manager
if (ManagerLocator.TryGet(out ConfigurationManager configurationManager))
{
configurationManager.UpdateConfiguration(ModID);
configurationManager.UpdateConfiguration(modID);
}
Destroy(this);
}
Expand Down
Loading

0 comments on commit c680451

Please sign in to comment.