-
-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
79 changed files
with
1,673 additions
and
1,429 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
using System.IO.Compression; | ||
using System.Security.Cryptography; | ||
|
||
namespace StatisticAnalysisTool.Extractor; | ||
|
||
public static class BinaryDecrypter | ||
{ | ||
private static readonly byte[] Key = { 48, 239, 114, 71, 66, 242, 4, 50 }; | ||
private static readonly byte[] Iv = { 14, 166, 220, 137, 219, 237, 220, 79 }; | ||
|
||
public static async Task DecryptBinaryFileAsync(string inputPath, Stream outputStream) | ||
{ | ||
await using var inputFile = File.OpenRead(inputPath); | ||
var fileBuffer = new byte[inputFile.Length]; | ||
_ = await inputFile.ReadAsync(fileBuffer, 0, fileBuffer.Length); | ||
|
||
var tDes = new DESCryptoServiceProvider | ||
{ | ||
IV = Iv, | ||
Mode = CipherMode.CBC, | ||
Key = Key | ||
}; | ||
var outBuffer = tDes.CreateDecryptor().TransformFinalBlock(fileBuffer, 0, fileBuffer.Length); | ||
|
||
const int size = 4096; | ||
var buffer = new byte[size]; | ||
int bytesRead; | ||
|
||
await using GZipStream decompression = new GZipStream(new MemoryStream(outBuffer), CompressionMode.Decompress); | ||
while ((bytesRead = decompression.Read(buffer, 0, buffer.Length)) > 0) | ||
{ | ||
await outputStream.WriteAsync(buffer, 0, bytesRead); | ||
} | ||
} | ||
|
||
public static async Task<MemoryStream> DecryptAndDecompressAsync(string inputPath) | ||
{ | ||
await using var inputFile = File.OpenRead(inputPath); | ||
var fileBuffer = new byte[inputFile.Length]; | ||
int bytesRead = await inputFile.ReadAsync(fileBuffer, 0, fileBuffer.Length); | ||
|
||
var tDes = new DESCryptoServiceProvider | ||
{ | ||
IV = Iv, | ||
Mode = CipherMode.CBC, | ||
Key = Key | ||
}; | ||
var outBuffer = tDes.CreateDecryptor().TransformFinalBlock(fileBuffer, 0, bytesRead); | ||
|
||
const int size = 4096; | ||
var buffer = new byte[size]; | ||
int decompressedBytesRead; | ||
|
||
await using GZipStream decompression = new GZipStream(new MemoryStream(outBuffer), CompressionMode.Decompress); | ||
await using MemoryStream outputMemoryStream = new MemoryStream(); | ||
|
||
while ((decompressedBytesRead = await decompression.ReadAsync(buffer, 0, buffer.Length)) > 0) | ||
{ | ||
await outputMemoryStream.WriteAsync(buffer, 0, decompressedBytesRead); | ||
} | ||
|
||
return outputMemoryStream; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using Newtonsoft.Json; | ||
using System.Xml; | ||
using Formatting = Newtonsoft.Json.Formatting; | ||
|
||
namespace StatisticAnalysisTool.Extractor; | ||
|
||
public class BinaryDumper | ||
{ | ||
public static async Task ExtractAsync(string mainGameFolder, string outputFolderPath, string[] binFileNamesToExtract) | ||
{ | ||
var allFiles = GetBinFilePaths(mainGameFolder, binFileNamesToExtract); | ||
var outFiles = (string[]) allFiles.Clone(); | ||
for (var i = 0; i < outFiles.Length; i++) | ||
{ | ||
outFiles[i] = outFiles[i].Remove(0, outFiles[i].LastIndexOf("GameData\\", StringComparison.Ordinal) + "GameData\\".Length); | ||
} | ||
|
||
foreach (string binFilePath in allFiles) | ||
{ | ||
await DecryptBinFileAsync(outputFolderPath, binFilePath); | ||
} | ||
} | ||
|
||
private static string[] GetBinFilePaths(string mainGameFolder, IEnumerable<string> binFileNamesToExtract) | ||
{ | ||
return binFileNamesToExtract.Select(fileName => Path.Combine(ExtractorUtilities.GetBinFilePath(mainGameFolder), $"{fileName}.bin")) | ||
.ToArray(); | ||
} | ||
|
||
private static async Task DecryptBinFileAsync(string outputFolderPath, string binFilePath) | ||
{ | ||
var binFileWoe = Path.GetFileNameWithoutExtension(binFilePath); | ||
|
||
if (binFileWoe.StartsWith("profanity", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
return; | ||
} | ||
|
||
var finalJsonPath = Path.Combine(outputFolderPath, binFileWoe + ".json"); | ||
|
||
await using var memoryStream = new MemoryStream(); | ||
await BinaryDecrypter.DecryptBinaryFileAsync(binFilePath, memoryStream); | ||
memoryStream.Position = 0; | ||
|
||
var xmlDocument = new XmlDocument(); | ||
var xmlReaderSettings = new XmlReaderSettings | ||
{ | ||
IgnoreComments = true | ||
}; | ||
var xmlReader = XmlReader.Create(memoryStream, xmlReaderSettings); | ||
xmlDocument.Load(xmlReader); | ||
|
||
await File.WriteAllTextAsync(finalJsonPath, JsonConvert.SerializeXmlNode(xmlDocument, Formatting.Indented, false)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace StatisticAnalysisTool.Extractor.Enums; | ||
|
||
public enum ServerType | ||
{ | ||
Live, | ||
Staging, | ||
Playground | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
using StatisticAnalysisTool.Extractor.Enums; | ||
|
||
namespace StatisticAnalysisTool.Extractor; | ||
|
||
public class Extractor | ||
{ | ||
private readonly LocalizationData _localizationData = new(); | ||
private readonly string _mainGameServerFolderString; | ||
|
||
public Extractor(string mainGameFolder, ServerType serverType) | ||
{ | ||
string mainGameFolderString = Path.Combine(mainGameFolder, GetServerTypeString(serverType)); | ||
_mainGameServerFolderString = mainGameFolderString.Replace("'", ""); | ||
} | ||
|
||
private async Task LoadLocationDataAsync() | ||
{ | ||
if (_localizationData.IsDataLoaded()) | ||
{ | ||
return; | ||
} | ||
|
||
await _localizationData.LoadDataAsync(_mainGameServerFolderString); | ||
} | ||
|
||
public async Task ExtractIndexedItemGameDataAsync(string outputDirPath, string indexedItemsFileName) | ||
{ | ||
await LoadLocationDataAsync(); | ||
await ItemData.CreateItemDataAsync(_mainGameServerFolderString, _localizationData, outputDirPath, indexedItemsFileName); | ||
} | ||
|
||
public async Task ExtractGameDataAsync(string outputDirPath, string[] binFileNamesToExtract) | ||
{ | ||
await LoadLocationDataAsync(); | ||
await BinaryDumper.ExtractAsync(_mainGameServerFolderString, outputDirPath, binFileNamesToExtract); | ||
} | ||
|
||
private static string GetServerTypeString(ServerType serverType) | ||
{ | ||
string serverTypeString = serverType switch | ||
{ | ||
ServerType.Staging => "staging", | ||
ServerType.Playground => "playground", | ||
_ => "game" | ||
}; | ||
|
||
return serverTypeString; | ||
} | ||
|
||
public static bool IsBinFileNewer(string toolFilePath, string mainGameFolder, ServerType serverType, string binFileName) | ||
{ | ||
try | ||
{ | ||
string mainGameFolderPath = Path.Combine(mainGameFolder, GetServerTypeString(serverType)); | ||
var binFilePath = Path.Combine(ExtractorUtilities.GetBinFilePath(mainGameFolderPath), $"{binFileName}.bin"); | ||
var toolFileDateTime = File.GetLastWriteTime(toolFilePath); | ||
|
||
if (!File.Exists(binFilePath)) | ||
{ | ||
return false; | ||
} | ||
|
||
try | ||
{ | ||
if (File.GetLastWriteTime(binFilePath) > toolFileDateTime) | ||
{ | ||
return true; | ||
} | ||
} | ||
catch | ||
{ | ||
return false; | ||
} | ||
|
||
return false; | ||
} | ||
catch | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
public static bool IsValidMainGameFolder(string mainGameFolder, ServerType serverType) | ||
{ | ||
string mainGameFolderPath = Path.Combine(mainGameFolder, GetServerTypeString(serverType)); | ||
|
||
var itemsBinFilePath = Path.Combine(ExtractorUtilities.GetBinFilePath(mainGameFolderPath), "items.bin"); | ||
var mobsBinFilePath = Path.Combine(ExtractorUtilities.GetBinFilePath(mainGameFolderPath), "mobs.bin"); | ||
var spellsBinFilePath = Path.Combine(ExtractorUtilities.GetBinFilePath(mainGameFolderPath), "spells.bin"); | ||
var worldBinFilePath = Path.Combine(ExtractorUtilities.GetBinFilePath(mainGameFolderPath), "cluster", "world.bin"); | ||
|
||
return File.Exists(itemsBinFilePath) | ||
&& File.Exists(mobsBinFilePath) | ||
&& File.Exists(spellsBinFilePath) | ||
&& File.Exists(worldBinFilePath); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
_localizationData.Dispose(); | ||
GC.SuppressFinalize(this); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using System.Text; | ||
using System.Text.Json; | ||
|
||
namespace StatisticAnalysisTool.Extractor; | ||
|
||
public static class ExtractorUtilities | ||
{ | ||
private static readonly JsonWriterOptions JsonWriterOptions = new () | ||
{ | ||
Indented = true, | ||
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping | ||
}; | ||
|
||
public static void WriteItem(Stream stream, IdContainer idContainer, bool first = false) | ||
{ | ||
if (!first) | ||
{ | ||
stream.WriteByte((byte) ','); | ||
stream.WriteByte((byte) '\n'); | ||
} | ||
|
||
using var writer = new Utf8JsonWriter(stream, JsonWriterOptions); | ||
if (idContainer is ItemContainer itemContainer) | ||
{ | ||
JsonSerializer.Serialize(writer, itemContainer); | ||
} | ||
else | ||
{ | ||
JsonSerializer.Serialize(writer, idContainer); | ||
} | ||
} | ||
|
||
public static void WriteString(Stream stream, string val) | ||
{ | ||
var buffer = Encoding.UTF8.GetBytes(val); | ||
stream.Write(buffer, 0, buffer.Length); | ||
} | ||
|
||
public static string GetBinFilePath(string mainGameFolder) | ||
{ | ||
return Path.Combine(mainGameFolder, ".\\Albion-Online_Data\\StreamingAssets\\GameData"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace StatisticAnalysisTool.Extractor; | ||
|
||
public class IdContainer | ||
{ | ||
public string Index { get; set; } | ||
public string UniqueName { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace StatisticAnalysisTool.Extractor; | ||
|
||
public class ItemContainer : IdContainer | ||
{ | ||
public string LocalizationNameVariable { get; set; } | ||
public string LocalizationDescriptionVariable { get; set; } | ||
public Dictionary<string, string> LocalizedNames { get; set; } | ||
public Dictionary<string, string> LocalizedDescriptions { get; set; } | ||
} |
Oops, something went wrong.