Skip to content

Commit

Permalink
Add PatchExtractor
Browse files Browse the repository at this point in the history
Extracts patches from the game database and sorts them
  • Loading branch information
blowfishpro committed Sep 14, 2017
1 parent 7138bbc commit 9a55a65
Show file tree
Hide file tree
Showing 4 changed files with 470 additions and 0 deletions.
1 change: 1 addition & 0 deletions ModuleManager/ModuleManager.csproj
Expand Up @@ -47,6 +47,7 @@
<Compile Include="MMPatchLoader.cs" />
<Compile Include="ModuleManager.cs" />
<Compile Include="PatchContext.cs" />
<Compile Include="PatchExtractor.cs" />
<Compile Include="PatchList.cs" />
<Compile Include="PatchProgress.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down
153 changes: 153 additions & 0 deletions ModuleManager/PatchExtractor.cs
@@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using ModuleManager.Extensions;

namespace ModuleManager
{
public static class PatchExtractor
{
private static readonly Regex firstRegex = new Regex(@":FIRST", RegexOptions.IgnoreCase);
private static readonly Regex finalRegex = new Regex(@":FINAL", RegexOptions.IgnoreCase);
private static readonly Regex beforeRegex = new Regex(@":BEFORE\[([^\[\]]+)\]", RegexOptions.IgnoreCase);
private static readonly Regex forRegex = new Regex(@":FOR\[([^\[\]]+)\]", RegexOptions.IgnoreCase);
private static readonly Regex afterRegex = new Regex(@":AFTER\[([^\[\]]+)\]", RegexOptions.IgnoreCase);

public static PatchList SortAndExtractPatches(UrlDir databaseRoot, IEnumerable<string> modList, IPatchProgress progress)
{
PatchList list = new PatchList(modList);

foreach (UrlDir.UrlConfig url in databaseRoot.AllConfigs.ToArray())
{
try
{
Command command = CommandParser.Parse(url.type, out _);;

Match firstMatch = firstRegex.Match(url.type);
Match finalMatch = finalRegex.Match(url.type);
Match beforeMatch = beforeRegex.Match(url.type);
Match forMatch = forRegex.Match(url.type);
Match afterMatch = afterRegex.Match(url.type);

int matchCount = 0;

if (firstMatch.Success) matchCount++;
if (finalMatch.Success) matchCount++;
if (beforeMatch.Success) matchCount++;
if (forMatch.Success) matchCount++;
if (afterMatch.Success) matchCount++;

if (firstMatch.NextMatch().Success) matchCount++;
if (finalMatch.NextMatch().Success) matchCount++;
if (beforeMatch.NextMatch().Success) matchCount++;
if (forMatch.NextMatch().Success) matchCount++;
if (afterMatch.NextMatch().Success) matchCount++;

bool error = false;

if (command == Command.Insert && matchCount > 0)
{
progress.Error(url, $"Error - pass specifier detected on an insert node (not a patch): {url.parent.url}/{url.type}");
error = true;
}
if (matchCount > 1)
{
progress.Error(url, $"Error - more than one pass specifier on a node: {url.parent.url}/{url.type}");
error = true;
}
if (error)
{
url.parent.configs.Remove(url);
continue;
}

if (command == Command.Insert) continue;

url.parent.configs.Remove(url);

Match theMatch = null;
List<UrlDir.UrlConfig> thePass = null;
bool modNotFound = false;

if (firstMatch.Success)
{
theMatch = firstMatch;
thePass = list.firstPatches;
}
else if (finalMatch.Success)
{
theMatch = finalMatch;
thePass = list.finalPatches;
}
else if (beforeMatch.Success)
{
if (CheckMod(beforeMatch, list.modPasses, out string theMod))
{
theMatch = beforeMatch;
thePass = list.modPasses[theMod].beforePatches;
}
else
{
modNotFound = true;
}
}
else if (forMatch.Success)
{
if (CheckMod(forMatch, list.modPasses, out string theMod))
{
theMatch = forMatch;
thePass = list.modPasses[theMod].forPatches;
}
else
{
modNotFound = true;
}
}
else if (afterMatch.Success)
{
if (CheckMod(afterMatch, list.modPasses, out string theMod))
{
theMatch = afterMatch;
thePass = list.modPasses[theMod].afterPatches;
}
else
{
modNotFound = true;
}
}
else
{
thePass = list.legacyPatches;
}

if (modNotFound) continue;

UrlDir.UrlConfig newUrl = url;
if (theMatch != null)
{
string newName = url.type.Remove(theMatch.Index, theMatch.Length);
ConfigNode newNode = new ConfigNode(newName) { id = url.config.id };
newNode.ShallowCopyFrom(url.config);
newUrl = new UrlDir.UrlConfig(url.parent, newNode);
}

thePass.Add(newUrl);
}
catch(Exception e)
{
progress.Exception(url, $"Exception while parsing pass for config: {url.parent.url}/{url.type}", e);
}
}

return list;
}

private static bool CheckMod(Match match, PatchList.ModPassCollection modPasses, out string theMod)
{
theMod = match.Groups[1].Value.Trim().ToLower();
return modPasses.HasMod(theMod);
}
}
}
1 change: 1 addition & 0 deletions ModuleManagerTests/ModuleManagerTests.csproj
Expand Up @@ -57,6 +57,7 @@
<Compile Include="Extensions\ConfigNodeExtensionsTest.cs" />
<Compile Include="Extensions\NodeStackExtensionsTest.cs" />
<Compile Include="Logging\ModLoggerTest.cs" />
<Compile Include="PatchExtractorTest.cs" />
<Compile Include="PatchProgressTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
Expand Down

0 comments on commit 9a55a65

Please sign in to comment.