Skip to content

Commit b548b0d

Browse files
committed
Less static
1 parent b4b50ff commit b548b0d

13 files changed

Lines changed: 135 additions & 108 deletions

File tree

TACTBench/BuildBenchmark.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,22 @@ public async Task EnsureBuildDownloaded()
1616

1717
public async Task LoadBuild()
1818
{
19-
var versions = await CDN.GetProductVersions("wow");
19+
var _build = new BuildInstance();
20+
21+
var versions = await _build.cdn.GetProductVersions("wow");
2022
foreach (var line in versions.Split('\n'))
2123
{
2224
if (!line.StartsWith("us|"))
2325
continue;
2426

2527
var splitLine = line.Split('|');
2628

27-
Settings.BuildConfig ??= splitLine[1];
28-
Settings.CDNConfig ??= splitLine[2];
29+
_build.Settings.BuildConfig ??= splitLine[1];
30+
_build.Settings.CDNConfig ??= splitLine[2];
2931
break;
3032
}
3133

32-
var _build = new BuildInstance(Settings.BuildConfig!, Settings.CDNConfig!);
34+
_build.LoadConfigs(_build.Settings.BuildConfig, _build.Settings.CDNConfig);
3335
_build.Load();
3436
}
3537

TACTSharp.Tests/ExtractionTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ public sealed class ExtractionTests
1111
public void Initialize()
1212
{
1313
// Pinned on 11.1.0.58945, should remain available with archive fallbacks if needed.
14-
build = new BuildInstance("f243bb339503142f617fd44d9170338a", "61ae809fa4cead855609d40da0d815e1");
14+
build = new BuildInstance();
15+
build.LoadConfigs("f243bb339503142f617fd44d9170338a", "61ae809fa4cead855609d40da0d815e1");
1516
build.Load();
1617
}
1718

TACTSharp/BLTE.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public static byte[] Decode(ReadOnlySpan<byte> data, ulong totalDecompSize = 0)
1919
{
2020
if ((char)data[fixedHeaderSize] != 'N' && totalDecompSize == 0)
2121
throw new Exception("totalDecompSize must be set for single non-normal BLTE block");
22-
else if((char)data[fixedHeaderSize] == 'N' && totalDecompSize == 0)
22+
else if ((char)data[fixedHeaderSize] == 'N' && totalDecompSize == 0)
2323
totalDecompSize = (ulong)(data.Length - fixedHeaderSize - 1);
2424

2525
var singleDecompData = new byte[totalDecompSize];

TACTSharp/Build.cs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,32 @@ public class BuildInstance
1111
public IndexInstance? GroupIndex { get; private set; }
1212
public IndexInstance? FileIndex { get; private set; }
1313

14-
public BuildInstance(string buildConfig, string cdnConfig)
14+
public CDN cdn { get; private set; }
15+
16+
public Settings Settings { get; private set; } = new Settings();
17+
18+
public BuildInstance()
19+
{
20+
cdn = new(Settings);
21+
}
22+
23+
public void LoadConfigs(string buildConfig, string cdnConfig)
1524
{
16-
// Always load configs so we have basic information available, loading the full build is optional.
25+
Settings.BuildConfig = buildConfig;
26+
Settings.CDNConfig = cdnConfig;
27+
1728
var timer = new System.Diagnostics.Stopwatch();
1829
timer.Start();
30+
1931
if (File.Exists(buildConfig))
20-
BuildConfig = new Config(buildConfig, true);
32+
BuildConfig = new Config(cdn, buildConfig, true);
2133
else if (buildConfig.Length == 32 && buildConfig.All(c => "0123456789abcdef".Contains(c)))
22-
BuildConfig = new Config(buildConfig, false);
34+
BuildConfig = new Config(cdn, buildConfig, false);
2335

2436
if (File.Exists(cdnConfig))
25-
CDNConfig = new Config(cdnConfig, true);
37+
CDNConfig = new Config(cdn, cdnConfig, true);
2638
else if (cdnConfig.Length == 32 && cdnConfig.All(c => "0123456789abcdef".Contains(c)))
27-
CDNConfig = new Config(cdnConfig, false);
39+
CDNConfig = new Config(cdn, cdnConfig, false);
2840

2941
if (BuildConfig == null || CDNConfig == null)
3042
throw new Exception("Failed to load configs");
@@ -34,13 +46,17 @@ public BuildInstance(string buildConfig, string cdnConfig)
3446

3547
public void Load()
3648
{
49+
if (BuildConfig == null || CDNConfig == null)
50+
throw new Exception("Configs not loaded");
51+
3752
var timer = new System.Diagnostics.Stopwatch();
3853

3954
timer.Start();
4055
if (!CDNConfig.Values.TryGetValue("archive-group", out var groupArchiveIndex))
4156
{
4257
Console.WriteLine("No group index found in CDN config, generating fresh group index...");
43-
var groupIndexHash = TACTSharp.GroupIndex.Generate("", CDNConfig.Values["archives"]);
58+
var groupIndex = new GroupIndex();
59+
var groupIndexHash = groupIndex.Generate(cdn, Settings, "", CDNConfig.Values["archives"]);
4460
var groupIndexPath = Path.Combine(Settings.CacheDir, "wow", "data", groupIndexHash + ".index");
4561
GroupIndex = new IndexInstance(groupIndexPath);
4662
}
@@ -54,7 +70,10 @@ public void Load()
5470
{
5571
var groupIndexPath = Path.Combine(Settings.CacheDir, "wow", "data", groupArchiveIndex[0] + ".index");
5672
if (!File.Exists(groupIndexPath))
57-
TACTSharp.GroupIndex.Generate(groupArchiveIndex[0], CDNConfig.Values["archives"]);
73+
{
74+
var groupIndex = new GroupIndex();
75+
groupIndex.Generate(cdn, Settings, groupArchiveIndex[0], CDNConfig.Values["archives"]);
76+
}
5877
GroupIndex = new IndexInstance(groupIndexPath);
5978
}
6079
}
@@ -71,7 +90,7 @@ public void Load()
7190
}
7291
else
7392
{
74-
var fileIndexPath = CDN.GetFilePath("wow", "data", fileIndex[0] + ".index");
93+
var fileIndexPath = cdn.GetFilePath("wow", "data", fileIndex[0] + ".index");
7594
FileIndex = new IndexInstance(fileIndexPath);
7695
}
7796

@@ -80,7 +99,7 @@ public void Load()
8099

81100
var encodingSize = ulong.Parse(BuildConfig.Values["encoding-size"][0]);
82101
timer.Restart();
83-
Encoding = new EncodingInstance(CDN.GetDecodedFilePath("wow", "data", BuildConfig.Values["encoding"][1], ulong.Parse(BuildConfig.Values["encoding-size"][1]), encodingSize), (int)encodingSize);
102+
Encoding = new EncodingInstance(cdn.GetDecodedFilePath("wow", "data", BuildConfig.Values["encoding"][1], ulong.Parse(BuildConfig.Values["encoding-size"][1]), encodingSize), (int)encodingSize);
84103
timer.Stop();
85104
Console.WriteLine("Encoding loaded in " + Math.Ceiling(timer.Elapsed.TotalMilliseconds) + "ms");
86105

@@ -92,7 +111,7 @@ public void Load()
92111
if (!rootEncodingKeys)
93112
throw new Exception("Root key not found in encoding");
94113

95-
Root = new RootInstance(CDN.GetDecodedFilePath("wow", "data", Convert.ToHexStringLower(rootEncodingKeys[0]), 0, rootEncodingKeys.DecodedFileSize));
114+
Root = new RootInstance(cdn.GetDecodedFilePath("wow", "data", Convert.ToHexStringLower(rootEncodingKeys[0]), 0, rootEncodingKeys.DecodedFileSize), Settings);
96115
timer.Stop();
97116
Console.WriteLine("Root loaded in " + Math.Ceiling(timer.Elapsed.TotalMilliseconds) + "ms");
98117

@@ -104,7 +123,7 @@ public void Load()
104123
if (!installEncodingKeys)
105124
throw new Exception("Install key not found in encoding");
106125

107-
Install = new InstallInstance(CDN.GetDecodedFilePath("wow", "data", Convert.ToHexStringLower(installEncodingKeys[0]), 0, installEncodingKeys.DecodedFileSize));
126+
Install = new InstallInstance(cdn.GetDecodedFilePath("wow", "data", Convert.ToHexStringLower(installEncodingKeys[0]), 0, installEncodingKeys.DecodedFileSize));
108127
timer.Stop();
109128
Console.WriteLine("Install loaded in " + Math.Ceiling(timer.Elapsed.TotalMilliseconds) + "ms");
110129
}
@@ -149,16 +168,16 @@ public byte[] OpenFileByEKey(ReadOnlySpan<byte> eKey, ulong decodedSize = 0)
149168
if (fileIndexEntry.size == -1)
150169
{
151170
Console.WriteLine("Warning: EKey " + Convert.ToHexStringLower(eKey) + " not found in group or file index and might not be available on CDN.");
152-
fileBytes = CDN.GetFile("wow", "data", Convert.ToHexStringLower(eKey), 0, decodedSize, true);
171+
fileBytes = cdn.GetFile("wow", "data", Convert.ToHexStringLower(eKey), 0, decodedSize, true);
153172
}
154173
else
155174
{
156-
fileBytes = CDN.GetFile("wow", "data", Convert.ToHexStringLower(eKey), (ulong)fileIndexEntry.size, decodedSize, true);
175+
fileBytes = cdn.GetFile("wow", "data", Convert.ToHexStringLower(eKey), (ulong)fileIndexEntry.size, decodedSize, true);
157176
}
158177
}
159178
else
160179
{
161-
fileBytes = CDN.GetFileFromArchive(Convert.ToHexStringLower(eKey), "wow", CDNConfig.Values["archives"][archiveIndex], offset, size, decodedSize, true);
180+
fileBytes = cdn.GetFileFromArchive(Convert.ToHexStringLower(eKey), "wow", CDNConfig.Values["archives"][archiveIndex], offset, size, decodedSize, true);
162181
}
163182

164183
return fileBytes;

TACTSharp/BuildInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public struct AvailableBuild
1717

1818
public List<AvailableBuild> Entries = [];
1919

20-
public BuildInfo(string path)
20+
public BuildInfo(string path, Settings Settings, CDN CDN)
2121
{
2222
var headerMap = new Dictionary<string, byte>();
2323

TACTSharp/CDN.cs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@
44

55
namespace TACTSharp
66
{
7-
public static class CDN
7+
public class CDN
88
{
9-
private static readonly HttpClient Client = new();
10-
private static readonly List<string> CDNServers = [];
11-
private static readonly ConcurrentDictionary<string, Lock> FileLocks = [];
12-
private static readonly Lock cdnLock = new();
13-
private static bool HasLocal = false;
14-
private static readonly Dictionary<byte, CASCIndexInstance> CASCIndexInstances = [];
9+
private readonly HttpClient Client = new();
10+
private readonly List<string> CDNServers = [];
11+
private readonly ConcurrentDictionary<string, Lock> FileLocks = [];
12+
private readonly Lock cdnLock = new();
13+
private bool HasLocal = false;
14+
private readonly Dictionary<byte, CASCIndexInstance> CASCIndexInstances = [];
15+
private Settings Settings;
1516

1617
// TODO: Memory mapped cache file access?
17-
// TODO: Product is build-specific so that might not be good to have statically in Settings/used below
18-
static CDN()
18+
public CDN(Settings settings)
1919
{
20+
Settings = settings;
2021
if (Settings.BaseDir != null)
2122
{
2223
try
@@ -34,7 +35,7 @@ static CDN()
3435
}
3536
}
3637

37-
public static void SetCDNs(string[] cdns)
38+
public void SetCDNs(string[] cdns)
3839
{
3940
foreach (var cdn in cdns)
4041
{
@@ -48,7 +49,7 @@ public static void SetCDNs(string[] cdns)
4849
}
4950
}
5051

51-
private static void LoadCDNs()
52+
private void LoadCDNs()
5253
{
5354
var timer = new Stopwatch();
5455
timer.Start();
@@ -89,7 +90,7 @@ private static void LoadCDNs()
8990
timer.Stop();
9091
Console.WriteLine("Pinged " + CDNServers.Count + " in " + Math.Round(timer.Elapsed.TotalMilliseconds) + "ms, fastest CDNs in order: " + string.Join(", ", CDNServers));
9192
}
92-
private static void LoadCASCIndices()
93+
private void LoadCASCIndices()
9394
{
9495
if (Settings.BaseDir != null)
9596
{
@@ -111,12 +112,12 @@ private static void LoadCASCIndices()
111112
}
112113
}
113114

114-
public static async Task<string> GetProductVersions(string product)
115+
public async Task<string> GetProductVersions(string product)
115116
{
116117
return await Client.GetStringAsync($"https://{Settings.Region}.version.battle.net/{product}/versions");
117118
}
118119

119-
private static byte[] DownloadFile(string tprDir, string type, string hash, ulong size = 0, CancellationToken token = new())
120+
private byte[] DownloadFile(string tprDir, string type, string hash, ulong size = 0, CancellationToken token = new())
120121
{
121122
if (HasLocal)
122123
{
@@ -202,7 +203,7 @@ public static async Task<string> GetProductVersions(string product)
202203
return null;
203204
}
204205

205-
public static unsafe bool TryGetLocalFile(string eKey, out ReadOnlySpan<byte> data)
206+
public unsafe bool TryGetLocalFile(string eKey, out ReadOnlySpan<byte> data)
206207
{
207208
var eKeyBytes = Convert.FromHexString(eKey);
208209
var i = eKeyBytes[0] ^ eKeyBytes[1] ^ eKeyBytes[2] ^ eKeyBytes[3] ^ eKeyBytes[4] ^ eKeyBytes[5] ^ eKeyBytes[6] ^ eKeyBytes[7] ^ eKeyBytes[8];
@@ -251,7 +252,7 @@ public static unsafe bool TryGetLocalFile(string eKey, out ReadOnlySpan<byte> da
251252
return false;
252253
}
253254

254-
private static byte[] DownloadFileFromArchive(string eKey, string tprDir, string archive, int offset, int size, CancellationToken token = new())
255+
private byte[] DownloadFileFromArchive(string eKey, string tprDir, string archive, int offset, int size, CancellationToken token = new())
255256
{
256257
if (HasLocal)
257258
{
@@ -328,7 +329,7 @@ public static unsafe bool TryGetLocalFile(string eKey, out ReadOnlySpan<byte> da
328329
return null;
329330
}
330331

331-
public static byte[] GetFile(string tprDir, string type, string hash, ulong compressedSize = 0, ulong decompressedSize = 0, bool decoded = false, CancellationToken token = new())
332+
public byte[] GetFile(string tprDir, string type, string hash, ulong compressedSize = 0, ulong decompressedSize = 0, bool decoded = false, CancellationToken token = new())
332333
{
333334
var data = DownloadFile(tprDir, type, hash, compressedSize, token);
334335
if (!decoded)
@@ -337,7 +338,7 @@ public static unsafe bool TryGetLocalFile(string eKey, out ReadOnlySpan<byte> da
337338
return BLTE.Decode(data, decompressedSize);
338339
}
339340

340-
public static byte[] GetFileFromArchive(string eKey, string tprDir, string archive, int offset, int length, ulong decompressedSize = 0, bool decoded = false, CancellationToken token = new())
341+
public byte[] GetFileFromArchive(string eKey, string tprDir, string archive, int offset, int length, ulong decompressedSize = 0, bool decoded = false, CancellationToken token = new())
341342
{
342343
var data = DownloadFileFromArchive(eKey, tprDir, archive, offset, length, token);
343344
if (!decoded)
@@ -346,7 +347,7 @@ public static unsafe bool TryGetLocalFile(string eKey, out ReadOnlySpan<byte> da
346347
return BLTE.Decode(data, decompressedSize);
347348
}
348349

349-
public static string GetFilePath(string tprDir, string type, string hash, ulong compressedSize = 0, CancellationToken token = new())
350+
public string GetFilePath(string tprDir, string type, string hash, ulong compressedSize = 0, CancellationToken token = new())
350351
{
351352
var cachePath = Path.Combine(Settings.CacheDir, tprDir, type, hash);
352353
if (File.Exists(cachePath))
@@ -362,7 +363,7 @@ public static unsafe bool TryGetLocalFile(string eKey, out ReadOnlySpan<byte> da
362363
return cachePath;
363364
}
364365

365-
public static string GetDecodedFilePath(string tprDir, string type, string hash, ulong compressedSize = 0, ulong decompressedSize = 0, CancellationToken token = new())
366+
public string GetDecodedFilePath(string tprDir, string type, string hash, ulong compressedSize = 0, ulong decompressedSize = 0, CancellationToken token = new())
366367
{
367368
var cachePath = Path.Combine(Settings.CacheDir, tprDir, type, hash + ".decoded");
368369
if (File.Exists(cachePath))

TACTSharp/Config.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ namespace TACTSharp
55
public class Config
66
{
77
public Dictionary<string, string[]> Values = [];
8-
public Config(string path, bool isFile)
8+
public Config(CDN cdn, string path, bool isFile)
99
{
1010
if (!isFile)
1111
{
12-
foreach (var line in Encoding.UTF8.GetString(CDN.GetFile("wow", "config", path)).Split('\n'))
12+
foreach (var line in Encoding.UTF8.GetString(cdn.GetFile("wow", "config", path)).Split('\n'))
1313
{
1414
var splitLine = line.Split('=');
1515
if (splitLine.Length > 1)

TACTSharp/GroupIndex.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
namespace TACTSharp
55
{
66
// roughly based on schlumpf's implementation
7-
public static class GroupIndex
7+
public class GroupIndex
88
{
99
private struct IndexEntry
1010
{
@@ -14,10 +14,10 @@ private struct IndexEntry
1414
public uint Offset;
1515
}
1616

17-
private static readonly List<IndexEntry> Entries = [];
18-
private static readonly Lock entryLock = new();
17+
private readonly List<IndexEntry> Entries = [];
18+
private readonly Lock entryLock = new();
1919

20-
public static string Generate(string? hash, string[] archives)
20+
public string Generate(CDN CDN, Settings Settings, string? hash, string[] archives)
2121
{
2222
if (string.IsNullOrEmpty(hash))
2323
Console.WriteLine("Generating group index for unknown group-index");

0 commit comments

Comments
 (0)