Skip to content

Commit a6f7d41

Browse files
author
Swamp Ig
committed
Nodes edit in place, regexp replace
1 parent a62ced4 commit a6f7d41

2 files changed

Lines changed: 183 additions & 52 deletions

File tree

Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
1818
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
1919

20-
[assembly: AssemblyVersion("2.0.8")]
20+
[assembly: AssemblyVersion("2.0.9")]
2121

2222
// The following attributes are used to specify the signing key for the assembly,
2323
// if desired. See the Mono documentation for more information about signing.

moduleManager.cs

Lines changed: 182 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -94,27 +94,52 @@ public static string RemoveWS(string withWhite)
9494

9595
// ModifyNode applies the ConfigNode mod as a 'patch' to ConfigNode original, then returns the patched ConfigNode.
9696
// it uses FindConfigNodeIn(src, nodeType, nodeName, nodeTag) to recurse.
97-
public static ConfigNode ModifyNode(ConfigNode original, ConfigNode mod)
97+
public ConfigNode ModifyNode(ConfigNode original, ConfigNode mod)
9898
{
9999
if (!IsSane(original) || !IsSane(mod))
100100
{
101-
print("[ModuleManager] A node has an empty name. Skipping it. Original: " + original.name);
101+
print("[ModuleManager] A node has an empty name. Skipping it. Original: " + original);
102102
return original;
103103
}
104104

105105
ConfigNode newNode = original.CreateCopy();
106-
106+
107107
string vals = "[ModuleManager] modding values";
108108
foreach (ConfigNode.Value val in mod.values)
109109
{
110110
vals += "\n " + val.name + "= " + val.value;
111-
if (val.name[0] != '@' && val.name[0] != '!' && val.name[0] != '%')
112-
newNode.AddValue(val.name, val.value);
111+
112+
string valName = val.name;
113+
114+
if (valName[0] != '@' && valName[0] != '!' && valName[0] != '%')
115+
{
116+
int index = int.MaxValue;
117+
if (valName.Contains(",") && int.TryParse(valName.Split(',')[1], out index))
118+
{
119+
// In this case insert the value at position index (with the same node names)
120+
valName = valName.Split(',')[0];
121+
122+
string [] oldValues = newNode.GetValues(valName);
123+
if (index < oldValues.Length)
124+
{
125+
newNode.RemoveValues(valName);
126+
int i = 0;
127+
for(; i < index; ++i)
128+
newNode.AddValue(valName, oldValues[i]);
129+
newNode.AddValue(valName, val.value);
130+
for(; i < oldValues.Length; ++i)
131+
newNode.AddValue(valName, oldValues[i]);
132+
continue;
133+
}
134+
}
135+
136+
newNode.AddValue(valName, val.value);
137+
}
113138
else
114139
{ // Parsing:
115140
// Format is @key = value or @key *= value or @key += value or @key -= value
116141
// or @key,index = value or @key,index *= value or @key,index += value or @key,index -= value
117-
string valName = val.name.Substring(1);
142+
valName = valName.Substring(1);
118143
int index = 0;
119144
if (valName.Contains(","))
120145
{
@@ -126,12 +151,14 @@ public static ConfigNode ModifyNode(ConfigNode original, ConfigNode mod)
126151
{
127152
string value = val.value;
128153
char op = ' ';
129-
if (val.name.Contains(" *")) // @key *= val
154+
if (valName.EndsWith(" *")) // @key *= val
130155
op = '*';
131-
else if (val.name.Contains(" +")) // @key += val
156+
else if (valName.EndsWith(" +")) // @key += val
132157
op = '+';
133-
else if (val.name.Contains(" -")) // @key -= val
158+
else if (valName.EndsWith(" -")) // @key -= val
134159
op = '-';
160+
else if (valName.EndsWith(" ^"))
161+
op = '^';
135162

136163
if (op != ' ')
137164
{
@@ -141,7 +168,19 @@ public static ConfigNode ModifyNode(ConfigNode original, ConfigNode mod)
141168
if (ovalue != null)
142169
{
143170
double s, os;
144-
if (double.TryParse(value, out s) && double.TryParse(ovalue, out os))
171+
if (op == '^')
172+
{
173+
try
174+
{
175+
string[] split = value.Split(value[0]);
176+
value = Regex.Replace(ovalue, split[1], split[2]);
177+
}
178+
catch (Exception ex)
179+
{
180+
print("[ModuleManager] Failed to do a regexp replacement: " + mod.name + " : original value=\"" + ovalue + "\" regexp=\"" + value + "\" \nNote - to use regexp, the first char is used to subdivide the string (much like sed)\n" + ex.ToString());
181+
}
182+
}
183+
else if (double.TryParse(value, out s) && double.TryParse(ovalue, out os))
145184
{
146185
if (op == '*')
147186
value = (s * os).ToString();
@@ -181,11 +220,25 @@ public static ConfigNode ModifyNode(ConfigNode original, ConfigNode mod)
181220
}
182221

183222
char cmd = subMod.name[0];
184-
if (cmd != '@' && cmd != '!' && cmd != '%' && cmd != '$')
185-
newNode.AddNode(subMod);
223+
string name = subMod.name;
224+
225+
if (cmd != '@' && cmd != '!' && cmd != '%' && cmd != '$')
226+
{
227+
int index = int.MaxValue;
228+
if (name.Contains(",") && int.TryParse(name.Split(',')[1], out index))
229+
{
230+
// In this case insert the value at position index (with the same node names)
231+
subMod.name = name = name.Split(',')[0];
232+
233+
InsertNode(newNode, subMod, index);
234+
}
235+
else
236+
{
237+
newNode.AddNode(subMod);
238+
}
239+
}
186240
else
187241
{
188-
string name = subMod.name;
189242
string cond = "";
190243
string tag = "";
191244
string nodeType, nodeName;
@@ -259,14 +312,23 @@ public static ConfigNode ModifyNode(ConfigNode original, ConfigNode mod)
259312
foreach (ConfigNode subNode in subNodes)
260313
{
261314
msg += " Applying subnode " + subMod.name + "\n";
262-
if (cmd != '$')
263-
{// @ and ! both remove the original
264-
newNode.nodes.Remove(subNode);
265-
}
266-
if (cmd != '!')
267-
{ // @ and $ both add the modified
268-
ConfigNode newSubNode = ModifyNode(subNode, subMod);
269-
newNode.nodes.Add(newSubNode);
315+
ConfigNode newSubNode;
316+
switch(cmd) {
317+
case '@':
318+
// @ edits in place
319+
newSubNode = ModifyNode(subNode, subMod);
320+
subNode.ClearData();
321+
newSubNode.CopyTo(subNode);
322+
break;
323+
case '!':
324+
// Delete the node
325+
newNode.nodes.Remove(subNode);
326+
break;
327+
case '$':
328+
// Copy the node
329+
newSubNode = ModifyNode(subNode, subMod);
330+
newNode.nodes.Add(newSubNode);
331+
break;
270332
}
271333
}
272334
}
@@ -277,8 +339,8 @@ public static ConfigNode ModifyNode(ConfigNode original, ConfigNode mod)
277339
{
278340
msg += " Applying subnode " + subMod.name + "\n";
279341
ConfigNode newSubNode = ModifyNode(subNodes[0], subMod);
280-
newNode.nodes.Remove(subNodes[0]);
281-
newNode.nodes.Add(newSubNode);
342+
subNodes[0].ClearData();
343+
newSubNode.CopyTo(subNodes[0]);
282344
}
283345
else
284346
{ // if not add the mod node without the % in its name
@@ -311,6 +373,27 @@ public static ConfigNode ModifyNode(ConfigNode original, ConfigNode mod)
311373
return newNode;
312374
}
313375

376+
private static void InsertNode(ConfigNode newNode, ConfigNode subMod, int index)
377+
{
378+
string modName = subMod.name;
379+
380+
ConfigNode[] oldValues = newNode.GetNodes(modName);
381+
if (index < oldValues.Length)
382+
{
383+
newNode.RemoveNodes(modName);
384+
int i = 0;
385+
for (; i < index; ++i)
386+
newNode.AddNode(oldValues[i]);
387+
newNode.AddNode(subMod);
388+
for (; i < oldValues.Length; ++i)
389+
newNode.AddNode(oldValues[i]);
390+
}
391+
else
392+
{
393+
newNode.AddNode(subMod);
394+
}
395+
}
396+
314397
public static List<UrlDir.UrlConfig> AllConfigsStartingWith(string match)
315398
{
316399
List<UrlDir.UrlConfig> nodes = new List<UrlDir.UrlConfig>();
@@ -454,6 +537,9 @@ orderby ass.GetName().Version descending, a.path ascending
454537
}
455538
log(modlist);
456539

540+
// Do filtering with NEEDS
541+
CheckNeeds(excludePaths);
542+
457543
// :First node (and any node without a :pass)
458544
ApplyPatch(excludePaths, ":FIRST");
459545

@@ -509,24 +595,25 @@ public void OnGUI()
509595
public void ApplyPatch(List<String> excludePaths, string Stage)
510596
{
511597
print("[ModuleManager] " + Stage + (Stage == ":FIRST" ? " (default) pass" : " pass"));
598+
512599
foreach (UrlDir.UrlConfig mod in GameDatabase.Instance.root.AllConfigs.ToArray())
513600
{
514-
if (!IsBraquetBalanced(mod.type))
515-
{
516-
print("[ModuleManager] Skipping a patch with unbalanced square brackets or a space (replace them with a '?') :\n" + mod.name + "\n");
517-
addErrorFiles(mod.parent);
518-
errorCount++;
519-
continue;
520-
}
521-
522-
string name = RemoveWS(mod.type);
523-
524601
int lastErrorCount = errorCount;
525602

526603
try
527604
{
605+
string name = RemoveWS(mod.type);
606+
528607
if (name[0] == '@' || (name[0] == '$') || (name[0] == '!'))
529608
{
609+
if (!IsBraquetBalanced(mod.type))
610+
{
611+
print("[ModuleManager] Skipping a patch with unbalanced square brackets or a space (replace them with a '?') :\n" + mod.name + "\n");
612+
addErrorFiles(mod.parent);
613+
errorCount++;
614+
continue;
615+
}
616+
530617
// Ensure the stage is correct
531618
int stageIdx = name.IndexOf(Stage);
532619
if (stageIdx >= 0)
@@ -543,13 +630,7 @@ public void ApplyPatch(List<String> excludePaths, string Stage)
543630
}
544631

545632
// TODO: do we want to ensure there's only one phase specifier?
546-
547-
if (!CheckNeeds(ref name))
548-
{
549-
print("[ModuleManager] Not applying patch " + mod.url + " - unable to satisfy NEEDS");
550-
continue;
551-
}
552-
633+
553634
char[] sep = new char[] { '[', ']' };
554635
string cond = "";
555636

@@ -576,11 +657,11 @@ public void ApplyPatch(List<String> excludePaths, string Stage)
576657
{
577658
print("[ModuleManager] Applying node " + mod.url + " to " + url.url);
578659
patchCount++;
579-
url.config = ConfigManager.ModifyNode(url.config, mod.config);
660+
url.config = ModifyNode(url.config, mod.config);
580661
}
581662
else if (mod.type[0] == '$')
582663
{
583-
ConfigNode clone = ConfigManager.ModifyNode(url.config, mod.config);
664+
ConfigNode clone = ModifyNode(url.config, mod.config);
584665
if (url.config.name != mod.name)
585666
{
586667
print("[ModuleManager] Copying Node " + url.config.name + " into " + clone.name);
@@ -600,7 +681,31 @@ public void ApplyPatch(List<String> excludePaths, string Stage)
600681
}
601682
}
602683
}
603-
else if(Stage == ":FIRST" && mod.type.Contains(":NEEDS["))
684+
}
685+
catch (Exception e)
686+
{
687+
print("[ModuleManager] Exception while processing node : " + mod.url + "\n" + e.ToString());
688+
addErrorFiles(mod.parent);
689+
}
690+
finally
691+
{
692+
if (lastErrorCount < errorCount)
693+
addErrorFiles(mod.parent, errorCount - lastErrorCount);
694+
}
695+
}
696+
}
697+
698+
private void CheckNeeds(List<String> excludePaths)
699+
{
700+
// Check the NEEDS parts first.
701+
foreach (UrlDir.UrlConfig mod in GameDatabase.Instance.root.AllConfigs.ToArray())
702+
{
703+
try
704+
{
705+
if (IsPathInList(mod.url, excludePaths))
706+
continue;
707+
708+
if (mod.type.Contains(":NEEDS["))
604709
{
605710
mod.parent.configs.Remove(mod);
606711
string type = mod.type;
@@ -612,25 +717,50 @@ public void ApplyPatch(List<String> excludePaths, string Stage)
612717
continue;
613718
}
614719
Debug.LogWarning(type);
615-
720+
616721
ConfigNode copy = new ConfigNode(type);
617722
mod.config.CopyTo(copy);
723+
CheckNeeds(copy);
618724

619725
mod.parent.configs.Add(new UrlDir.UrlConfig(mod.parent, copy));
620-
726+
}
727+
else
728+
{
729+
CheckNeeds(mod.config);
621730
}
622731
}
623-
catch (Exception e)
732+
catch (Exception ex)
624733
{
625-
print("[ModuleManager] Exception while processing node : " + mod.url + "\n" + e.ToString());
626-
addErrorFiles(mod.parent);
734+
print("[ModuleManager] Exception while checking needs : " + mod.url + "\n" + ex.ToString());
627735
}
628-
finally
736+
}
737+
}
738+
739+
private void CheckNeeds(ConfigNode subMod)
740+
{
741+
ConfigNode copy = new ConfigNode();
742+
for (int i = 0; i < subMod.values.Count; ++i)
743+
{
744+
ConfigNode.Value val = subMod.values[i];
745+
string name = val.name;
746+
if (CheckNeeds(ref name))
747+
copy.AddValue(name, val.value);
748+
}
749+
750+
for (int i = 0; i < subMod.nodes.Count; ++i)
751+
{
752+
ConfigNode node = subMod.nodes[i];
753+
string name = node.name;
754+
if (CheckNeeds(ref name))
629755
{
630-
if (lastErrorCount < errorCount)
631-
addErrorFiles(mod.parent, errorCount - lastErrorCount);
756+
node.name = name;
757+
CheckNeeds(node);
758+
copy.AddNode(node);
632759
}
633760
}
761+
762+
subMod.ClearData();
763+
copy.CopyTo(subMod);
634764
}
635765

636766
private bool CheckNeeds(ref string name)
@@ -669,6 +799,7 @@ private bool CheckNeeds(ref string name)
669799
return true;
670800
}
671801

802+
672803
public void addErrorFiles(UrlDir.UrlFile file, int n=1)
673804
{
674805
string key = file.url + "." + file.fileExtension;

0 commit comments

Comments
 (0)