Skip to content

Instantly share code, notes, and snippets.

@StollD
Created December 6, 2015 18:28
Show Gist options
  • Save StollD/0366e9952055b95900e9 to your computer and use it in GitHub Desktop.
Save StollD/0366e9952055b95900e9 to your computer and use it in GitHub Desktop.
Plugin that makes ConfigNodes temporary compatible with ModuleManager
/**
* Compatible Module Manager
* Copyright (c) 2015 Thomas P.
* License: MIT
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace CompatibleModuleManager
{
[KSPAddon(KSPAddon.Startup.Instantly, true)]
public class CompatibleModuleManager : MonoBehaviour
{
/// <summary>
/// Nodes
/// </summary>
public static List<ConfigNode> nodes { get; set; }
/// <summary>
/// Add our own loaders
/// </summary>
void Start()
{
nodes = new List<ConfigNode>();
LoadingScreen.Instance.loaders.Insert(1, new GameObject("CMM_PRE").AddComponent<CMM_Pre>());
LoadingScreen.Instance.loaders.Insert(3, new GameObject("CMM_POST").AddComponent<CMM_Post>());
}
}
/// <summary>
/// Base-Loader
/// </summary>
public class CMM_Base : LoadingSystem
{
/// <summary>
/// Whether we're done
/// </summary>
public bool isReady = false;
/// <summary>
/// Whether we're done
/// </summary>
public override bool IsReady()
{
return isReady;
}
/// <summary>
/// Progress
/// </summary>
public float maxConfigs, doneConfigs = 0;
/// <summary>
/// Progress
/// </summary>
/// <returns></returns>
public override float ProgressFraction()
{
return doneConfigs / maxConfigs;
}
/// <summary>
/// Some stuff
/// </summary>
public override string ProgressTitle()
{
return "Compatibility MM Patcher";
}
/// <summary>
/// Get the configs and create the loader
/// </summary>
public override void StartLoad()
{
UrlDir.UrlConfig[] configs = GameDatabase.Instance.GetConfigs("Compatibility");
maxConfigs = configs.Length;
StartCoroutine(ProcessConfigs(configs));
}
/// <summary>
/// Processes the configs
/// </summary>
protected virtual IEnumerator<object> ProcessConfigs(UrlDir.UrlConfig[] configs)
{
yield break;
}
/// <summary>
/// Finds configs
/// </summary>
protected IEnumerable<ConfigNode> FindNodesRecursive(ref ConfigNode[] nodes, List<string> names)
{
/// List
List<ConfigNode> list = new List<ConfigNode>();
/// Null Check
if (names.Count == 0) return list;
if (nodes.Length == 0) return list;
/// Go through the nodes
foreach (ConfigNode node in nodes)
{
/// Name matches
if (names[0] == node.name && names.Count == 1)
list.AddRange(node.nodes.Cast<ConfigNode>());
}
/// Recursivly wrap child nodes
names.RemoveAt(0);
ConfigNode[] subNodes = nodes.SelectMany(n => n.nodes.Cast<ConfigNode>()).ToArray();
foreach (ConfigNode node in FindNodesRecursive(ref subNodes, names))
list.Add(node);
return list;
}
}
/// <summary>
/// Pre-Loader
/// </summary>
public class CMM_Pre : CMM_Base
{
/// <summary>
/// Config Processor
/// </summary>
protected override IEnumerator<object> ProcessConfigs(UrlDir.UrlConfig[] configs)
{
/// Go through the cfgs
for (doneConfigs = 1; doneConfigs <= maxConfigs; doneConfigs++)
{
ConfigNode node = configs[(int)doneConfigs - 1].config;
if (!node.HasValue("parent") || !node.HasValue("name") || !node.HasValue("target")) continue;
List<string> parent = node.GetValue("parent").Split('.').ToList();
string name = node.GetValue("name");
string target = node.GetValue("target");
ConfigNode[] gdbNodes = GameDatabase.Instance.GetConfigs(parent[0]).Select(c => c.config).ToArray();
IEnumerable<ConfigNode> nodes = FindNodesRecursive(ref gdbNodes, parent);
CompatibleModuleManager.nodes.AddRange(nodes);
foreach (ConfigNode subNode in nodes)
{
subNode.AddValue(target, subNode.name);
subNode.name = name;
}
yield return null;
}
isReady = true;
}
}
/// <summary>
/// Post-Loader
/// </summary>
public class CMM_Post : CMM_Base
{
/// <summary>
/// Config Processor
/// </summary>
protected override IEnumerator<object> ProcessConfigs(UrlDir.UrlConfig[] configs)
{
/// Go through the cfgs
for (doneConfigs = 1; doneConfigs <= maxConfigs; doneConfigs++)
{
ConfigNode node = configs[(int)doneConfigs - 1].config;
if (!node.HasValue("parent") || !node.HasValue("name") || !node.HasValue("target")) continue;
List<string> parent = node.GetValue("parent").Split('.').ToList();
string name = node.GetValue("name");
string target = node.GetValue("target");
ConfigNode[] gdbNodes = GameDatabase.Instance.GetConfigs(parent[0]).Select(c => c.config).ToArray();
IEnumerable<ConfigNode> nodes = FindNodesRecursive(ref gdbNodes, parent);
foreach (ConfigNode subNode in nodes)
{
if (subNode.name == name)
{
subNode.name = subNode.GetValue(target);
subNode.RemoveValue(target);
}
}
yield return null;
}
isReady = true;
}
}
}
Compatibility
{
parent = Test.Toast
name = Toaster
target = name
}
Test
{
Toast
{
Blah1
{
value = sth
}
Blah2
{
uuu = aaa
}
}
}
UrlConfig
{
name = Test
type = Test
parentUrl = /CMM
url = /CMM/Test
Test
{
Toast
{
Toaster
{
value = sth
name = Blah1
}
Toaster
{
uuu = aaa
name = Blah2
}
}
}
}
// After MM finished, its reset to the state of EXAMPLE.cfg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment