Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Louvenarde committed Jul 29, 2021
1 parent ac0ef6c commit b9f7f13
Show file tree
Hide file tree
Showing 24 changed files with 1,289 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "CommandLineInterface"]
path = CommandLineInterface
url = https://github.com/LouveSystems/CommandLineInterface
1 change: 1 addition & 0 deletions CommandLineInterface
Submodule CommandLineInterface added at 83915a
31 changes: 31 additions & 0 deletions iw4-zone-asset-finder.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31424.327
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iw4-zone-asset-finder", "iw4-zone-asset-finder\iw4-zone-asset-finder.csproj", "{61E61075-537E-44DF-A9B9-078DAB3E2949}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LouveSystems.CommandLineInterface", "CommandLineInterface\LouveSystems.CommandLineInterface.csproj", "{AFC77677-384F-4DBA-9D62-8484B4AFBA97}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{61E61075-537E-44DF-A9B9-078DAB3E2949}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61E61075-537E-44DF-A9B9-078DAB3E2949}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61E61075-537E-44DF-A9B9-078DAB3E2949}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61E61075-537E-44DF-A9B9-078DAB3E2949}.Release|Any CPU.Build.0 = Release|Any CPU
{AFC77677-384F-4DBA-9D62-8484B4AFBA97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AFC77677-384F-4DBA-9D62-8484B4AFBA97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AFC77677-384F-4DBA-9D62-8484B4AFBA97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AFC77677-384F-4DBA-9D62-8484B4AFBA97}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1047545D-F67C-4E48-A3FC-3646913F7519}
EndGlobalSection
EndGlobal
6 changes: 6 additions & 0 deletions iw4-zone-asset-finder/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
105 changes: 105 additions & 0 deletions iw4-zone-asset-finder/Commands/BuildRequirements.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using LouveSystems.CommandLineInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace iw4_zone_asset_finder.Commands
{
public class BuildRequirements : LouveSystems.CommandLineInterface.Command
{
public override string HelpMessage => "Given multiple space-separated asset names and types enclosed by a \", outputs a minimal set of zones as requirement for building a patch zone containing these assets";

public override string HelpfulArguments => $"\"<type>:<name> <type>:<name>...\"";

public override bool Execute(CommandLineInterface cli, string arguments, out string remainder)
{
if (DependencyGraph.Current == null)
{
remainder = string.Empty;
cli.Err("No dependency graph loaded! Please generate a dependency graph with UPDATE, or RELOAD an existing one");
return false;
}

var assets = cli.GetFirstString(arguments, out remainder);

var assetsToFind = new List<string>(assets.Split(' '));

List<string> finalAssets = new List<string>();
List<string> zonesToInclude = new List<string>();

List<DependencyGraph.SearchResult> assetInZones = new List<DependencyGraph.SearchResult>();

foreach (var asset in assetsToFind)
{
var assetSearchResult = DependencyGraph.Current.FindAssetByPreciseName(asset);
if (assetSearchResult == null)
{
var multiSearch = DependencyGraph.Current.FindAssetByName(asset);

if (multiSearch.Count > 0) {
assetSearchResult = multiSearch[0];
cli.Warn($"Warning: Could not find asset named {asset}, performed lose search instead and replaced it with asset {assetSearchResult.Asset}");
}
else
{
cli.Err($"Asset {asset} could not be find in the dependency graph. This asset will be missing");
continue;
}
}

var aWithType = asset.Split(':');
finalAssets.Add($"{aWithType[0]},{aWithType[1]}");
assetInZones.Add(assetSearchResult);

}

Dictionary<string, int> finalZoneScore = new Dictionary<string, int>();
while (assetInZones.Count > 0)
{
Dictionary<string, int> zoneScore = new Dictionary<string, int>();

foreach(var searchResult in assetInZones)
{
foreach (var zone in searchResult.Zones)
{
if (!zoneScore.ContainsKey(zone))
{
zoneScore[zone] = 0;
}

zoneScore[zone]++;
}
}

var nextZone = zoneScore.OrderByDescending(o => o.Value).First().Key;

zonesToInclude.Add(nextZone);
assetInZones.RemoveAll(o => o.Zones.Contains(nextZone));
finalZoneScore[nextZone] = zoneScore[nextZone];
}

cli.Color(ConsoleColor.Gray);
cli.Write($"The following dependencies are suggested: ");

foreach(var zoneScore in finalZoneScore)
{
cli.Color(ConsoleColor.White);
cli.Write(zoneScore.Key);
cli.Color(ConsoleColor.Gray);
cli.Write($"({zoneScore.Value} assets), ");
}

cli.WriteLine("\n\nSource requirements:");

cli.Color(ConsoleColor.Cyan);
cli.WriteLine($"{string.Join("\n", zonesToInclude.Select(o=>$"require,{o}"))}\n");
cli.Color(ConsoleColor.Gray);

cli.WriteLine($"{string.Join("\n", finalAssets)}");

return true;
}
}
}
51 changes: 51 additions & 0 deletions iw4-zone-asset-finder/Commands/FindAsset.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using LouveSystems.CommandLineInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace iw4_zone_asset_finder.Commands
{
public class FindAsset : LouveSystems.CommandLineInterface.Command
{
public override string HelpMessage => "Searches an asset through all zones and lists references";

public override string HelpfulArguments => $"<asset name>";

public override bool Execute(CommandLineInterface cli, string arguments, out string remainder)
{
if (DependencyGraph.Current == null)
{
remainder = string.Empty;
cli.Err("No dependency graph loaded! Please generate a dependency graph with UPDATE, or RELOAD an existing one");
return false;
}

var assetName = cli.GetFirstString(arguments, out remainder);
var type = string.Empty;
List <DependencyGraph.SearchResult> zones;

zones = DependencyGraph.Current.FindAssetByName(assetName);
cli.Color(ConsoleColor.Gray);
cli.Write($"For search term ");
cli.Color(ConsoleColor.Cyan);
cli.Write($"\"{assetName}\"");
cli.Color(ConsoleColor.Gray);
cli.WriteLine(" :");

if (zones.Count > 0)
{
cli.Color(ConsoleColor.Green);
cli.WriteLine($"Found in the following zones:\n\n{string.Join("\n", zones.Select(o=>$"{o.Asset.PadRight(16)} \n {string.Join("\n ", o.Zones)}\n"))}");
}
else
{
cli.Color(ConsoleColor.Red);
cli.WriteLine("No results.");
}

return true;
}
}
}
49 changes: 49 additions & 0 deletions iw4-zone-asset-finder/Commands/FindPreciseAsset.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using LouveSystems.CommandLineInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace iw4_zone_asset_finder.Commands
{
public class FindPreciseAsset : LouveSystems.CommandLineInterface.Command
{
public override string HelpMessage => "Lists all zones referencing a precise asset";

public override string HelpfulArguments => $"<asset type>:<asset name>";

public override bool Execute(CommandLineInterface cli, string arguments, out string remainder)
{
if (DependencyGraph.Current == null)
{
remainder = string.Empty;
cli.Err("No dependency graph loaded! Please generate a dependency graph with UPDATE, or RELOAD an existing one");
return false;
}

var assetName = cli.GetFirstString(arguments, out remainder);

var zone = DependencyGraph.Current.FindAssetByPreciseName(assetName);
cli.Color(ConsoleColor.Gray);
cli.Write($"For asset ");
cli.Color(ConsoleColor.Cyan);
cli.Write($"\"{assetName}\"");
cli.Color(ConsoleColor.Gray);
cli.WriteLine(" :");

if (zone != null)
{
cli.Color(ConsoleColor.Green);
cli.WriteLine($"Found in the following zones:\n\n{zone.Asset.PadRight(16)} \n {string.Join("\n ", zone.Zones)}");
}
else
{
cli.Color(ConsoleColor.Red);
cli.WriteLine("No results. This asset is not present in the dependency graph.");
}

return true;
}
}
}
33 changes: 33 additions & 0 deletions iw4-zone-asset-finder/Commands/Ignore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using LouveSystems.CommandLineInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace iw4_zone_asset_finder.Commands
{
public class Ignore : LouveSystems.CommandLineInterface.Command
{
public override string HelpMessage => "Removes a zone from the dependency graph until it is reloaded again";

public override string HelpfulArguments => $"<zone name>";

public override bool Execute(CommandLineInterface cli, string arguments, out string remainder)
{
if (DependencyGraph.Current == null)
{
remainder = string.Empty;
cli.Err("No dependency graph loaded! Please generate a dependency graph with UPDATE, or LOAD/RELOAD an existing one");
return false;
}

var zoneName = cli.GetFirstString(arguments, out remainder);

DependencyGraph.Current.RemoveZone(zoneName);
cli.WriteLine($"Zone {zoneName} will be ignored from dependencies until the graph is loaded or reloaded.");

return true;
}
}
}
86 changes: 86 additions & 0 deletions iw4-zone-asset-finder/Commands/IwdFiles.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using LouveSystems.CommandLineInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Text.RegularExpressions;

namespace iw4_zone_asset_finder.Commands
{
public class IwdFiles : LouveSystems.CommandLineInterface.Command
{
public override string HelpMessage => "Lists IWD files used by a map";

public override string HelpfulArguments => "<zone name>";

readonly string[] GAME_EXECUTABLES = new string[] { "iw4x.exe", "iw4_direct.exe" };

public override bool Execute(CommandLineInterface cli, string arguments, out string remainder)
{

string zoneName = cli.GetFirstString(arguments, out remainder);

if (!File.Exists(GAME_EXECUTABLES[0]) && !File.Exists(GAME_EXECUTABLES[1]))
{
cli.Err($"Could not find a game executable ({string.Join(" or ", GAME_EXECUTABLES)})");
return false;
}

string output = string.Empty;
int result = -1;

foreach (var exe in GAME_EXECUTABLES)
{
if (File.Exists(exe))
{
cli.WriteLine($"Loading {zoneName}...");
output = Helper.GetProgramOutput(exe, $"-nosteam -zonebuilder -stdout +loadzone {zoneName} +listRawImages +listStreamedSounds 9 +quit", out result);
break;
}
}

if (result == 0)
{
var dumpFile = $"{zoneName}_iwd.txt";

using (FileStream fs = new FileStream(dumpFile, FileMode.Create))
{
using (StreamWriter sw = new StreamWriter(fs))
{
var reg = new Regex(@"(\([a-z]+ [0-9]\)) (.*)");
var matches = reg.Matches(output);

foreach (Match match in matches)
{
// Group #1 is nothing
// Group #2 is asset name

if (match.Groups.Count == 3)
{
string assetName = match.Groups[2].Value.Trim();

cli.WriteLine(assetName);
sw.WriteLine(assetName);

}
}
}
}

cli.Color(ConsoleColor.Green);
cli.Write($"\nSuccessfully wrote all referenced iwd-files in ");
cli.Color(ConsoleColor.Cyan);
cli.WriteLine(dumpFile);
return true;
}
else
{
cli.WriteLine();
cli.Err($"Zonebuilder exited with code {result} for this zone. Aborting.");
return false;
}
}
}
}
Loading

0 comments on commit b9f7f13

Please sign in to comment.