Skip to content

Commit 6471c8c

Browse files
committed
#1: add component modification support
1 parent 6a07e09 commit 6471c8c

File tree

4 files changed

+125
-5
lines changed

4 files changed

+125
-5
lines changed

GameData/Mutiny/test.cfg

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ SCENE_PATCH
66

77
VABmodern
88
{
9-
active = false
9+
Components
10+
{
11+
Transform
12+
{
13+
localScale = 0.1, 0.1, 0.1
14+
}
15+
}
1016
}
1117
}

Source/ModifyObject.cs

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
using HarmonyLib;
2+
using System;
23
using System.Collections.Generic;
34
using System.Reflection;
45
using System.Security.AccessControl;
@@ -60,8 +61,7 @@ private static Action<object> CreateMutator(ConfigNode.Value configValue, Type o
6061
return null;
6162
}
6263

63-
64-
private static void CreateMutators(ConfigNode configNode, Type objectType, List<Action<object>> mutators)
64+
private static void CreateObjectMutators(ConfigNode configNode, Type objectType, List<Action<object>> mutators)
6565
{
6666
foreach (ConfigNode.Value configValue in configNode.values.values)
6767
{
@@ -71,12 +71,81 @@ private static void CreateMutators(ConfigNode configNode, Type objectType, List<
7171
mutators.Add(mutator);
7272
}
7373
}
74+
75+
var customNodeHandlers = x_customNodeHandlers.GetValueOrDefault(objectType);
76+
77+
foreach (ConfigNode childNode in configNode.nodes.nodes)
78+
{
79+
// TODO: support arbitrary nested objects
80+
81+
if (customNodeHandlers != null && customNodeHandlers.TryGetValue(childNode.name, out var customNodeHandler))
82+
{
83+
customNodeHandler.Invoke(childNode, objectType, mutators);
84+
}
85+
}
86+
}
87+
88+
static Dictionary<Type, Dictionary<string, Action<ConfigNode, Type, List<Action<object>>>>> x_customNodeHandlers = new()
89+
{
90+
{
91+
typeof(GameObject), new Dictionary<string, Action<ConfigNode, Type, List<Action<object>>>>
92+
{
93+
{ "Components", CreateComponentMutators },
94+
}
95+
},
96+
};
97+
98+
private static void CreateComponentMutators(ConfigNode configNode, Type type, List<Action<object>> mutators)
99+
{
100+
foreach (ConfigNode componentNode in configNode.nodes.nodes)
101+
{
102+
string componentTypeName = componentNode.name;
103+
Type componentType = typeof(Component).GetSubclassNamed(componentTypeName);
104+
105+
if (componentType == null) continue;
106+
107+
bool createNew = false;
108+
if (componentNode.TryGetValue("create", ref createNew))
109+
{
110+
componentNode.RemoveValue("create");
111+
}
112+
113+
Action<object>[] componentMutators = CreateMutators(componentNode, componentType);
114+
115+
mutators.Add(obj =>
116+
{
117+
GameObject gameObject = (GameObject)obj;
118+
var component = gameObject.GetComponent(componentType);
119+
if (component == null)
120+
{
121+
if (createNew)
122+
{
123+
component = gameObject.AddComponent(componentType);
124+
}
125+
else
126+
{
127+
Log.Error($"Component {componentTypeName} not found on GameObject {gameObject.name}");
128+
return;
129+
}
130+
}
131+
else if (createNew)
132+
{
133+
// maybe we should still add a new one?
134+
Log.Warning($"Component {componentTypeName} already existed on Gamebject {gameObject.name}");
135+
}
136+
137+
foreach (var mutator in componentMutators)
138+
{
139+
mutator.Invoke(component);
140+
}
141+
});
142+
}
74143
}
75144

76145
private static Action<object>[] CreateMutators(ConfigNode configNode, Type objectType)
77146
{
78147
List<Action<object>> mutators = new List<Action<object>>();
79-
CreateMutators(configNode, objectType, mutators);
148+
CreateObjectMutators(configNode, objectType, mutators);
80149
return mutators.ToArray();
81150
}
82151

Source/Mutiny.csproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net4.8</TargetFramework>
5+
<LangVersion>9</LangVersion>
56
</PropertyGroup>
67

78
<PropertyGroup>
@@ -17,6 +18,21 @@
1718
</KSPVersionFile>
1819
</ItemGroup>
1920

21+
<ItemGroup>
22+
<Reference Include="$(KSPRoot)/GameData/000_Harmony/0Harmony.dll">
23+
<Private>false</Private>
24+
<CKANIdentifier>Harmony2</CKANIdentifier>
25+
<KSPAssemblyName>HarmonyKSP</KSPAssemblyName>
26+
<KSPAssemblyVersion>1.0.0</KSPAssemblyVersion>
27+
</Reference>
28+
<Reference Include="$(KSPRoot)/GameData/ModuleManager*.dll">
29+
<Private>false</Private>
30+
<CKANIdentifier>ModuleManager</CKANIdentifier>
31+
<KSPAssemblyName>ModuleManager</KSPAssemblyName>
32+
<KSPAssemblyVersion>2.5.0</KSPAssemblyVersion>
33+
</Reference>
34+
</ItemGroup>
35+
2036
<ItemGroup>
2137
<Publicize Include="Assembly-CSharp" />
2238
</ItemGroup>

Source/TypeExtensions.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using HarmonyLib;
2+
using KSPBuildTools;
3+
using System;
4+
using System.Collections.Generic;
5+
using UniLinq;
6+
7+
namespace Mutiny
8+
{
9+
static public class TypeExtensions
10+
{
11+
public static Type GetSubclassNamed(this Type thisType, string name)
12+
{
13+
// This doesn't work because GetSubclassesOfParentClass doesn't include the builtin unity types
14+
//List<Type> subclassTypes = AssemblyLoader.GetSubclassesOfParentClass(thisType);
15+
//Type result = subclassTypes.FirstOrDefault(t => t.Name == name);
16+
17+
// probably horribly slow, but we can cache it later.
18+
19+
Type result = AccessTools.TypeByName(name);
20+
21+
if (result == null || !thisType.IsAssignableFrom(result))
22+
{
23+
Log.Error($"Could not find subclass of {thisType.Name} named {name}");
24+
}
25+
26+
return result;
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)