private static void DoExport(string exportFormat, string outDir, params string[] files) { JsonSerializer jsonserializer = new JsonSerializer { NullValueHandling = NullValueHandling.Ignore }; DBDXMLSerializer xmlserializer = new DBDXMLSerializer(); foreach (var file in files) { Console.WriteLine("Exporting " + file); var reader = new DBDReader(); var target = Path.Combine(outDir, Path.ChangeExtension(Path.GetFileName(file), exportFormat)); Console.WriteLine($"Saving {exportFormat.ToUpper()} to {target}"); using (StreamWriter writer = File.CreateText(target)) { switch (exportFormat) { case "json": jsonserializer.Serialize(writer, reader.Read(file)); break; case "xml": xmlserializer.Serialize(writer, reader.Read(file)); break; } } } }
static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: <definitionsdir>"); Environment.Exit(1); } var definitionDir = args[0]; var rewrite = true; foreach (var file in Directory.GetFiles(definitionDir)) { var dbName = Path.GetFileNameWithoutExtension(file); var reader = new DBDReader(); definitionCache.Add(dbName, reader.Read(file, true)); Console.WriteLine("Read " + definitionCache[dbName].versionDefinitions.Length + " versions and " + definitionCache[dbName].columnDefinitions.Count + " columns for " + dbName); if (rewrite) { var writer = new DBDWriter(); writer.Save(definitionCache[dbName], Path.Combine(definitionDir, dbName + ".dbd")); } } Console.WriteLine("Read " + definitionCache.Count + " database definitions!"); var foreignKeys = 0; foreach (var definition in definitionCache) { foreach (var columnDefinition in definition.Value.columnDefinitions) { if (!string.IsNullOrEmpty(columnDefinition.Value.foreignTable) || !string.IsNullOrEmpty(columnDefinition.Value.foreignColumn)) { if (definitionCache.ContainsKey(columnDefinition.Value.foreignTable) && definitionCache[columnDefinition.Value.foreignTable].columnDefinitions.ContainsKey(columnDefinition.Value.foreignColumn)) { Console.ForegroundColor = ConsoleColor.Green; //Console.WriteLine(definition.Key + "." + columnDefinition.Key + " has a foreign key to " + columnDefinition.Value.foreignTable + "." + columnDefinition.Value.foreignColumn); } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(definition.Key + "." + columnDefinition.Key + " has a foreign key to " + columnDefinition.Value.foreignTable + "." + columnDefinition.Value.foreignColumn + " WHICH DOES NOT EXIST!"); } foreignKeys++; Console.ResetColor(); } } } Console.WriteLine("Checked " + foreignKeys + " foreign keys!"); Console.WriteLine("Done, press enter to exit"); Console.ReadLine(); }
static void Main(string[] args) { if (args.Length < 1 || args.Length > 3) { throw new ArgumentException("Invalid argument count, need at least 1 argument: indbdfile/indbddir (outdir, default current dir) (json)"); } var inFile = args[0]; var outDir = Directory.GetCurrentDirectory(); var exportFormat = "json"; if (args.Length >= 2) { outDir = args[1]; if (!Directory.Exists(outDir)) { Directory.CreateDirectory(outDir); } } if (args.Length == 3) { if (args[2] == "json") { exportFormat = args[2]; } else { throw new ArgumentException("Export format should be json"); } } if (Directory.Exists(args[0])) { foreach (var file in Directory.GetFiles(args[0])) { var reader = new DBDReader(); Console.WriteLine("Exporting " + file); if (exportFormat == "json") { var target = Path.Combine(outDir, Path.GetFileNameWithoutExtension(file) + ".json");; ExportJSON(reader.Read(file), target); } } } else if (File.Exists(args[0])) { var reader = new DBDReader(); Console.WriteLine("Exporting " + args[0]); if (exportFormat == "json") { var target = Path.Combine(outDir, Path.GetFileNameWithoutExtension(args[0]) + ".json");; ExportJSON(reader.Read(args[0]), target); } } else { throw new FileNotFoundException("Unable to find directory/file " + args[0]); } }
public VersionDefinitions[] GetVersionDefinitionsForDB2(string db2File) { var dbdStream = dbdProvider.StreamForTableName(db2File, null); var dbdReader = new DBDReader(); var databaseDefinition = dbdReader.Read(dbdStream); return(databaseDefinition.versionDefinitions); }
private void ValidateDefinition() { Regex buildmatch = new Regex(@"\d\.\d{1,2}.\d.\d{4,}", RegexOptions.Compiled); string file = Path.GetFileNameWithoutExtension(txtFile1.Text).ToUpper(); Dictionary <Build, string> dbbuilds = new Dictionary <Build, string>(); foreach (var db in AllDBs[file]) { dbbuilds.Add(new Build(Directory.GetParent(db).Name.ToUpper().Replace("A", "")), db); } if (dbbuilds.Count == 0 || !AllDBDs.Any(x => Path.GetFileNameWithoutExtension(x).ToUpper() == file)) { return; } DBDReader reader = new DBDReader(); string dbdfile = AllDBDs.First(x => Path.GetFileNameWithoutExtension(x).ToUpper() == file); var dbd = reader.Read(dbdfile); var builds = dbd.versionDefinitions.SelectMany(x => x.builds).ToArray(); var ranges = dbd.versionDefinitions.SelectMany(x => x.buildRanges).ToArray(); List <ValidateResult> validationResults = new List <ValidateResult>(); foreach (var b in dbbuilds) { Application.DoEvents(); if (builds.Any(x => x.build == b.Key.build) || ranges.Any(x => x.ContainsV2(b.Key))) { var result = DBReader.Validate(b.Value, dbdfile, b.Key); if (result.Issues != DBIssues.NONE) { validationResults.Add(result); } } } if (validationResults.Count > 0) { new Popup() { Data = validationResults }.ShowDialog(); } else { MessageBox.Show("Smashing job!"); } }
internal Type Build(Stream dbc, Stream dbd, string name = null, string build = null) { var dbdReader = new DBDReader(); var dbcReader = ReaderForDBC(dbc); if (name == null) { name = Guid.NewGuid().ToString(); } var databaseDefinition = dbdReader.Read(dbd); Structs.VersionDefinitions?versionDefinition = null; if (string.IsNullOrWhiteSpace(build) == false) { Utils.GetVersionDefinitionByBuild(databaseDefinition, new Build(build), out versionDefinition); } if (versionDefinition == null) { var layoutHash = dbcReader.LayoutHash.ToString("X8"); Utils.GetVersionDefinitionByLayoutHash(databaseDefinition, layoutHash, out versionDefinition); } if (versionDefinition == null) { throw new FileNotFoundException("No definition found for this file."); } var typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public); var fields = versionDefinition.Value.definitions; foreach (var fieldDefinition in fields) { var columnDefinition = databaseDefinition.columnDefinitions[fieldDefinition.name]; var type = FieldDefinitionToType(fieldDefinition, columnDefinition); var field = typeBuilder.DefineField(fieldDefinition.name, type, FieldAttributes.Public); if (fieldDefinition.isID) { var constructorParameters = new Type[] { }; var constructorInfo = typeof(IndexAttribute).GetConstructor(constructorParameters); var displayNameAttributeBuilder = new CustomAttributeBuilder(constructorInfo, new object[] { }); field.SetCustomAttribute(displayNameAttributeBuilder); } } return(typeBuilder.CreateTypeInfo()); }
private void PopulateBuilds() { Regex buildmatch = new Regex(@"\d\.\d{1,2}.\d.\d{4,}", RegexOptions.Compiled); string file = Path.GetFileNameWithoutExtension(txtFile1.Text).ToUpper(); var dbbuilds = AllDBs[file].Select(x => Directory.GetParent(x).Name.ToUpper().Replace("A", "")).Where(x => buildmatch.IsMatch(x)).ToArray(); // flatten cbBuild1.DataSource = null; cbBuild2.DataSource = null; if (dbbuilds.Length == 0 || !AllDBDs.Any(x => Path.GetFileNameWithoutExtension(x).ToUpper() == file)) { return; } DBDReader reader = new DBDReader(); var dbd = reader.Read(AllDBDs.First(x => Path.GetFileNameWithoutExtension(x).ToUpper() == file)); var builds = new HashSet <string>(dbd.versionDefinitions.SelectMany(x => x.builds.Select(y => y.ToString())).Intersect(dbbuilds)); var ranges = dbd.versionDefinitions.SelectMany(x => x.buildRanges).ToArray(); foreach (var b in dbbuilds) { Build build = new Build(b); foreach (var range in ranges) { if (range.ContainsV2(build)) { builds.Add(b); break; } } } // load cbBuild1.DataSource = builds.Select(x => new Build(x)).OrderBy(x => x.expansion).ThenBy(x => x.build).Select(x => x.ToString()).ToList(); cbBuild2.DataSource = (cbBuild1.DataSource as List <string>).ToList(); // binding issues cbBuild2.SelectedIndex = cbBuild2.Items.Count - 1; }
internal Tuple <Type, DBCDInfo> Build(DBReader dbcReader, Stream dbd, string name, string build) { var dbdReader = new DBDReader(); if (name == null) { name = Guid.NewGuid().ToString(); } var databaseDefinition = dbdReader.Read(dbd); Structs.VersionDefinitions?versionDefinition = null; if (!string.IsNullOrWhiteSpace(build)) { var dbBuild = new Build(build); locStringSize = GetLocStringSize(dbBuild); Utils.GetVersionDefinitionByBuild(databaseDefinition, dbBuild, out versionDefinition); } if (versionDefinition == null && dbcReader.LayoutHash != 0) { var layoutHash = dbcReader.LayoutHash.ToString("X8"); Utils.GetVersionDefinitionByLayoutHash(databaseDefinition, layoutHash, out versionDefinition); } if (versionDefinition == null) { throw new FileNotFoundException("No definition found for this file."); } if (locStringSize > 1 && (int)locale >= locStringSize) { throw new FormatException("Invalid locale for this file."); } var typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public); var fields = versionDefinition.Value.definitions; var columns = new List <string>(fields.Length); bool localiseStrings = locale != Locale.None; foreach (var fieldDefinition in fields) { var columnDefinition = databaseDefinition.columnDefinitions[fieldDefinition.name]; bool isLocalisedString = columnDefinition.type == "locstring" && locStringSize > 1; Type fieldType; if (fieldDefinition.isRelation && fieldDefinition.isNonInline) { fieldType = fieldDefinition.arrLength == 0 ? typeof(int) : typeof(int[]); } else { fieldType = FieldDefinitionToType(fieldDefinition, columnDefinition, localiseStrings); } var field = typeBuilder.DefineField(fieldDefinition.name, fieldType, FieldAttributes.Public); columns.Add(fieldDefinition.name); if (fieldDefinition.isID) { AddAttribute <IndexAttribute>(field, fieldDefinition.isNonInline); } if (fieldDefinition.arrLength > 1) { AddAttribute <CardinalityAttribute>(field, fieldDefinition.arrLength); } if (fieldDefinition.isRelation && fieldDefinition.isNonInline) { var metaDataFieldType = FieldDefinitionToType(fieldDefinition, columnDefinition, localiseStrings); AddAttribute <NonInlineRelationAttribute>(field, metaDataFieldType); } if (isLocalisedString) { if (localiseStrings) { AddAttribute <LocaleAttribute>(field, (int)locale, locStringSize); } else { AddAttribute <CardinalityAttribute>(field, locStringSize); // add locstring mask field typeBuilder.DefineField(fieldDefinition.name + "_mask", typeof(uint), FieldAttributes.Public); columns.Add(fieldDefinition.name + "_mask"); } } } var type = typeBuilder.CreateTypeInfo(); var info = new DBCDInfo { availableColumns = columns.ToArray(), tableName = name }; return(new Tuple <Type, DBCDInfo>(type, info)); }
private static Dictionary <string, TypeCode> BuildStructure(string filename, Build build, out bool defissue) { DBDReader reader = new DBDReader(); var dbd = reader.Read(filename); Dictionary <string, TypeCode> typeLookup = new Dictionary <string, TypeCode>(); void AddColumn(TypeCode type, string name, int arrlength) { for (int i = 0; i < arrlength || i < 1; i++) { typeLookup.Add(name + (arrlength > 1 ? "_" + (i + 1) : ""), type); } } // size, signed type, unsigned type var intTypes = new Dictionary <int, Tuple <TypeCode, TypeCode> >() { { 08, new Tuple <TypeCode, TypeCode>(TypeCode.Byte, TypeCode.Byte) }, { 16, new Tuple <TypeCode, TypeCode>(TypeCode.Int16, TypeCode.UInt16) }, { 32, new Tuple <TypeCode, TypeCode>(TypeCode.Int32, TypeCode.UInt32) }, { 64, new Tuple <TypeCode, TypeCode>(TypeCode.Int64, TypeCode.UInt64) }, }; var vers = dbd.versionDefinitions.Where(y => y.Contains(build)); defissue = vers.Count() != 1; var ver = vers.FirstOrDefault(); if (!ver.IsDefault()) { foreach (var def in ver.definitions) { string name = def.name; if (def.isID && !def.isNonInline) { name = "$id$" + name; } switch (dbd.columnDefinitions[def.name].type) { case "int": AddColumn(intTypes[def.size].Item1, name, def.arrLength); break; case "uint": AddColumn(intTypes[def.size].Item2, name, def.arrLength); break; case "float": AddColumn(TypeCode.Single, name, def.arrLength); break; case "string": AddColumn(TypeCode.String, name, def.arrLength); break; case "locstring": { int len = (build.expansion > 3 ? def.arrLength : (build.build < 6692 ? 8 : 16)); // string or locstring AddColumn(TypeCode.String, name, len); if (build.expansion <= 3) { AddColumn(TypeCode.Int32, name + "_mask", 1); // mask } } break; } } } return(typeLookup); }
static void Main(string[] args) { if (args.Length < 3) { Console.WriteLine("Usage: <firstdir> <seconddir> <outdir>"); Environment.Exit(1); } var firstDir = args[0]; var secondDir = args[1]; var targetDir = args[2]; var firstDirFiles = new DirectoryInfo(firstDir).GetFiles().Select(o => o.Name).ToList(); var secondDirFiles = new DirectoryInfo(secondDir).GetFiles().Select(o => o.Name).ToList(); var newDefinitions = new Dictionary <string, DBDefinition>(); var reader = new DBDReader(); foreach (var file in secondDirFiles) { var dbName = Path.GetFileNameWithoutExtension(file); if (firstDirFiles.Contains(file)) { // Both directories have this file. Merge! var firstFile = reader.Read(Path.Combine(firstDir, file)); var secondFile = reader.Read(Path.Combine(secondDir, file)); var newDefinition = firstFile; // Merge column definitions foreach (var columnDefinition2 in secondFile.columnDefinitions) { var foundCol = false; foreach (var columnDefinition1 in firstFile.columnDefinitions) { if (Utils.NormalizeColumn(columnDefinition2.Key).ToLower() == Utils.NormalizeColumn(columnDefinition1.Key).ToLower()) { foundCol = true; if (columnDefinition2.Value.type != columnDefinition1.Value.type) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Types are different for (1)" + dbName + "::" + columnDefinition1.Key + " = " + columnDefinition1.Value.type + " and (2)" + dbName + "::" + columnDefinition2.Key + " = " + columnDefinition2.Value.type + ", using type " + columnDefinition2.Value.type + " from 2"); // If this is an uncommon conversion (not uint -> int or vice versa) throw an error if ((columnDefinition1.Value.type == "uint" && columnDefinition2.Value.type == "int") || (columnDefinition1.Value.type == "int" && columnDefinition2.Value.type == "uint")) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Type difference for column (1)" + dbName + "::" + columnDefinition1.Key + " = " + columnDefinition1.Value.type + " and(2)" + dbName + "::" + columnDefinition2.Key + " = " + columnDefinition2.Value.type + ", ignoring.."); } else { throw new Exception("bad type difference, refusing to handle"); } Console.ResetColor(); } if (columnDefinition2.Key != columnDefinition1.Key) { if (Utils.NormalizeColumn(columnDefinition2.Key, true) == columnDefinition1.Key) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Automagically fixed casing issue between (1)" + dbName + "::" + columnDefinition1.Key + " and (2)" + dbName + "::" + columnDefinition2.Key); for (var i = 0; i < secondFile.versionDefinitions.Length; i++) { for (var j = 0; j < secondFile.versionDefinitions[i].definitions.Length; j++) { if (secondFile.versionDefinitions[i].definitions[j].name == columnDefinition2.Key) { secondFile.versionDefinitions[i].definitions[j].name = Utils.NormalizeColumn(columnDefinition2.Key, true); break; } } } } else { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Unable to automagically fix casing issue between (1)" + dbName + "::" + columnDefinition1.Key + " and (2)" + dbName + "::" + columnDefinition2.Key + ", falling back to (1) naming"); for (var i = 0; i < secondFile.versionDefinitions.Length; i++) { for (var j = 0; j < secondFile.versionDefinitions[i].definitions.Length; j++) { if (secondFile.versionDefinitions[i].definitions[j].name == columnDefinition2.Key) { secondFile.versionDefinitions[i].definitions[j].name = columnDefinition1.Key; break; } } } } Console.ResetColor(); } break; } } if (!foundCol) { // Column was not found, add it Console.WriteLine(dbName + "::" + columnDefinition2.Key + " was not found found in first file!"); newDefinition.columnDefinitions.Add(columnDefinition2.Key, columnDefinition2.Value); } } // Merge version definitions foreach (var versionDefinition2 in secondFile.versionDefinitions) { var foundVersion = false; foreach (var versionDefinition1 in firstFile.versionDefinitions) { foreach (var layoutHash2 in versionDefinition2.layoutHashes) { if (versionDefinition1.layoutHashes.Contains(layoutHash2)) { foundVersion = true; break; } } // If layouthash was found, don't check builds if (foundVersion) { break; } // Check builds foreach (var build2 in versionDefinition2.builds) { foreach (var build1 in versionDefinition1.builds) { if (build1.Equals(build2)) { foundVersion = true; break; } } foreach (var buildranges1 in versionDefinition1.buildRanges) { if (build2.expansion == buildranges1.minBuild.expansion && build2.major == buildranges1.minBuild.major && build2.minor == buildranges1.minBuild.minor) { if (build2.build >= buildranges1.minBuild.build && build2.build <= buildranges1.maxBuild.build) { //Console.WriteLine("Build match? Build " + Utils.BuildToString(build2) + " seem to match with " + Utils.BuildToString(buildranges1.minBuild) + "-" + Utils.BuildToString(buildranges1.maxBuild)); foundVersion = true; break; } } } } } if (!foundVersion) { // TODO: Only for secondFile, not firstFile! var mergedWithPreviousBuild = false; var newVersions = newDefinition.versionDefinitions.ToList(); for (var i = 0; i < newVersions.Count; i++) { if (newVersions[i].definitions.SequenceEqual(versionDefinition2.definitions)) { Console.WriteLine("Looks like these two definition arrays are the same!"); // Make list from current builds var curBuilds = newVersions[i].builds.ToList(); curBuilds.AddRange(versionDefinition2.builds.ToList()); // Make list of current layouthashes var curLayouthashes = newVersions[i].layoutHashes.ToList(); curLayouthashes.AddRange(versionDefinition2.layoutHashes.ToList()); // Create temporary version object based of newVersion var tempVersion = newVersions[i]; // Override builds with new list tempVersion.builds = curBuilds.Distinct().ToArray(); // Override layoutHashes with new list tempVersion.layoutHashes = curLayouthashes.Distinct().ToArray(); // Override newVersion with temporary version object newVersions[i] = tempVersion; mergedWithPreviousBuild = true; } } if (!mergedWithPreviousBuild) { // Version was not found/merged, add it! newVersions.Add(versionDefinition2); } newDefinition.versionDefinitions = newVersions.ToArray(); } else { // Version exists, compare stuff and add build if needed, TODO make less bad var newVersions = newDefinition.versionDefinitions.ToList(); for (var i = 0; i < newVersions.Count; i++) { foreach (var layoutHash2 in versionDefinition2.layoutHashes) { if (newVersions[i].layoutHashes.Contains(layoutHash2)) { // Make list from current builds var curBuilds = newVersions[i].builds.ToList(); curBuilds.AddRange(versionDefinition2.builds.ToList()); // Make list of current layouthashes var curLayouthashes = newVersions[i].layoutHashes.ToList(); curLayouthashes.AddRange(versionDefinition2.layoutHashes.ToList()); // Create temporary version object based of newVersion var tempVersion = newVersions[i]; // Override builds with new list tempVersion.builds = curBuilds.Distinct().ToArray(); // Override layoutHashes with new list tempVersion.layoutHashes = curLayouthashes.Distinct().ToArray(); for (var j = 0; j < versionDefinition2.definitions.Count(); j++) { // Merge signedness from second file if it is different from current if (versionDefinition2.definitions[j].isSigned != tempVersion.definitions[j].isSigned) { tempVersion.definitions[j].isSigned = versionDefinition2.definitions[j].isSigned; } } // Override newVersion with temporary version object newVersions[i] = tempVersion; } } } newDefinition.versionDefinitions = newVersions.ToArray(); } } newDefinitions.Add(dbName, newDefinition); } else { // Only 2nd dir has this file, use that newDefinitions.Add(dbName, reader.Read(Path.Combine(secondDir, file))); } } foreach (var file in firstDirFiles) { if (!secondDirFiles.Contains(file)) { // Only 1st dir has this file, use that newDefinitions.Add(Path.GetFileNameWithoutExtension(file), reader.Read(Path.Combine(firstDir, file))); } } var writer = new DBDWriter(); foreach (var entry in newDefinitions) { writer.Save(entry.Value, Path.Combine(targetDir, entry.Key + ".dbd")); } //Console.ReadLine(); }
static void Main(string[] args) { if (args.Length < 3) { Console.WriteLine("Usage: <firstdir> <seconddir> <outdir>"); Environment.Exit(1); } var numLayoutsAdded = 0; var firstDir = args[0]; var secondDir = args[1]; var targetDir = args[2]; var firstDirFiles = new DirectoryInfo(firstDir).GetFiles().Select(o => o.Name).ToList(); var secondDirFiles = new DirectoryInfo(secondDir).GetFiles().Select(o => o.Name).ToList(); var firstDirFilesLC = new DirectoryInfo(firstDir).GetFiles().Select(o => o.Name.ToLower()).ToList(); var secondDirFilesLC = new DirectoryInfo(secondDir).GetFiles().Select(o => o.Name.ToLower()).ToList(); var newDefinitions = new Dictionary <string, DBDefinition>(); var reader = new DBDReader(); foreach (var file in secondDirFiles) { var dbName = Path.GetFileNameWithoutExtension(file); if (firstDirFilesLC.Contains(file.ToLower())) { // Both directories have this file. Merge! var firstFileName = Path.Combine(firstDir, firstDirFiles.ElementAt(firstDirFilesLC.IndexOf(file.ToLower()))); var firstFile = reader.Read(firstFileName); var secondFile = reader.Read(Path.Combine(secondDir, file)); var newDefinition = firstFile; // Merge column definitions foreach (var columnDefinition2 in secondFile.columnDefinitions) { var foundCol = false; foreach (var columnDefinition1 in firstFile.columnDefinitions) { if (Utils.NormalizeColumn(columnDefinition2.Key).ToLower() == Utils.NormalizeColumn(columnDefinition1.Key).ToLower()) { foundCol = true; if (columnDefinition2.Value.type != columnDefinition1.Value.type) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Types are different for (1)" + dbName + "::" + columnDefinition1.Key + " = " + columnDefinition1.Value.type + " and (2)" + dbName + "::" + columnDefinition2.Key + " = " + columnDefinition2.Value.type + ", using type " + columnDefinition2.Value.type + " from 2"); // If this is an uncommon conversion (not uint -> int or vice versa) throw an error if ((columnDefinition1.Value.type == "uint" && columnDefinition2.Value.type == "int") || (columnDefinition1.Value.type == "int" && columnDefinition2.Value.type == "uint")) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Type difference for column (1)" + dbName + "::" + columnDefinition1.Key + " = " + columnDefinition1.Value.type + " and(2)" + dbName + "::" + columnDefinition2.Key + " = " + columnDefinition2.Value.type + ", ignoring.."); } else { throw new Exception("bad type difference, refusing to handle"); } Console.ResetColor(); } if (columnDefinition2.Key != columnDefinition1.Key) { if (Utils.NormalizeColumn(columnDefinition2.Key, true) == columnDefinition1.Key) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Automagically fixed casing issue between (1)" + dbName + "::" + columnDefinition1.Key + " and (2)" + dbName + "::" + columnDefinition2.Key); for (var i = 0; i < secondFile.versionDefinitions.Length; i++) { for (var j = 0; j < secondFile.versionDefinitions[i].definitions.Length; j++) { if (secondFile.versionDefinitions[i].definitions[j].name == columnDefinition2.Key) { secondFile.versionDefinitions[i].definitions[j].name = Utils.NormalizeColumn(columnDefinition2.Key, true); break; } } } } else { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Unable to automagically fix casing issue between (1)" + dbName + "::" + columnDefinition1.Key + " and (2)" + dbName + "::" + columnDefinition2.Key + ", falling back to (1) naming"); for (var i = 0; i < secondFile.versionDefinitions.Length; i++) { for (var j = 0; j < secondFile.versionDefinitions[i].definitions.Length; j++) { if (secondFile.versionDefinitions[i].definitions[j].name == columnDefinition2.Key) { secondFile.versionDefinitions[i].definitions[j].name = columnDefinition1.Key; break; } } } } Console.ResetColor(); } // Merge comments if (columnDefinition2.Value.comment != columnDefinition1.Value.comment) { for (var i = 0; i < secondFile.versionDefinitions.Length; i++) { for (var j = 0; j < secondFile.versionDefinitions[i].definitions.Length; j++) { if (secondFile.versionDefinitions[i].definitions[j].name == columnDefinition2.Key) { var colDef = newDefinition.columnDefinitions[columnDefinition1.Key]; if (columnDefinition2.Value.comment == null) { colDef.comment = columnDefinition1.Value.comment; } else if (columnDefinition1.Value.comment == null) { colDef.comment = columnDefinition2.Value.comment; } else { throw new Exception("Do not support merging 2 comments yet!"); } newDefinition.columnDefinitions[columnDefinition1.Key] = colDef; } } } } // Merge foreignTable/foreignKey if (columnDefinition2.Value.foreignTable != columnDefinition1.Value.foreignTable || columnDefinition2.Value.foreignColumn != columnDefinition1.Value.foreignColumn) { for (var i = 0; i < secondFile.versionDefinitions.Length; i++) { for (var j = 0; j < secondFile.versionDefinitions[i].definitions.Length; j++) { if (secondFile.versionDefinitions[i].definitions[j].name == columnDefinition2.Key) { var colDef = newDefinition.columnDefinitions[columnDefinition1.Key]; if (columnDefinition2.Value.foreignTable == null && columnDefinition2.Value.foreignColumn == null) { colDef.foreignTable = columnDefinition1.Value.foreignTable; colDef.foreignColumn = columnDefinition1.Value.foreignColumn; } else if (columnDefinition1.Value.foreignTable == null && columnDefinition1.Value.foreignColumn == null) { colDef.foreignTable = columnDefinition2.Value.foreignTable; colDef.foreignColumn = columnDefinition2.Value.foreignColumn; } else { throw new Exception("Do not support merging 2 FKs yet!"); } newDefinition.columnDefinitions[columnDefinition1.Key] = colDef; } } } } break; } } if (!foundCol) { // Column was not found, add it newDefinition.columnDefinitions.Add(columnDefinition2.Key, columnDefinition2.Value); } } // Merge version definitions foreach (var versionDefinition2 in secondFile.versionDefinitions) { var foundVersion = false; foreach (var versionDefinition1 in firstFile.versionDefinitions) { foreach (var layoutHash2 in versionDefinition2.layoutHashes) { if (versionDefinition1.layoutHashes.Contains(layoutHash2)) { foundVersion = true; break; } } // If layouthash was found, don't check builds if (foundVersion) { break; } // Check builds foreach (var build2 in versionDefinition2.builds) { foreach (var build1 in versionDefinition1.builds) { if (build1.Equals(build2)) { foundVersion = true; break; } } // Stop checking if build already exists if (foundVersion) { break; } foreach (var buildranges1 in versionDefinition1.buildRanges) { if (buildranges1.Contains(build2)) { Console.WriteLine(build2.ToString() + " is in build range " + buildranges1.ToString()); foundVersion = true; break; } } // Stop checking if build exists in ranges if (foundVersion) { break; } } } if (!foundVersion) { // TODO: Only for secondFile, not firstFile! var mergedWithPreviousBuild = false; var newVersions = newDefinition.versionDefinitions.ToList(); for (var i = 0; i < newVersions.Count; i++) { if (newVersions[i].definitions.SequenceEqual(versionDefinition2.definitions)) { Console.WriteLine("Looks like these two definition arrays are the same!"); // Make list from current builds var curBuilds = newVersions[i].builds.ToList(); curBuilds.AddRange(versionDefinition2.builds.ToList()); // Make list from current build ranges var curBuildRanges = newVersions[i].buildRanges.ToList(); curBuildRanges.AddRange(versionDefinition2.buildRanges.ToList()); // Make list of current layouthashes var curLayouthashes = newVersions[i].layoutHashes.ToList(); curLayouthashes.AddRange(versionDefinition2.layoutHashes.ToList()); // Create temporary version object based of newVersion var tempVersion = newVersions[i]; // Override builds with new list tempVersion.builds = curBuilds.Distinct().ToArray(); // Override buildranges with new list tempVersion.buildRanges = curBuildRanges.Distinct().ToArray(); // Override layoutHashes with new list tempVersion.layoutHashes = curLayouthashes.Distinct().ToArray(); // Override newVersion with temporary version object newVersions[i] = tempVersion; mergedWithPreviousBuild = true; } } if (!mergedWithPreviousBuild) { // Version was not found/merged, add it! newVersions.Add(versionDefinition2); numLayoutsAdded++; } newDefinition.versionDefinitions = newVersions.ToArray(); } else { // Version exists, compare stuff and add build if needed, TODO make less bad var newVersions = newDefinition.versionDefinitions.ToList(); for (var i = 0; i < newVersions.Count; i++) { foreach (var layoutHash2 in versionDefinition2.layoutHashes) { if (newVersions[i].layoutHashes.Contains(layoutHash2)) { // Make list from current builds var curBuilds = newVersions[i].builds.ToList(); curBuilds.AddRange(versionDefinition2.builds.ToList()); // Make list from current build ranges var curBuildRanges = newVersions[i].buildRanges.ToList(); curBuildRanges.AddRange(versionDefinition2.buildRanges.ToList()); // Make list of current layouthashes var curLayouthashes = newVersions[i].layoutHashes.ToList(); curLayouthashes.AddRange(versionDefinition2.layoutHashes.ToList()); // Create temporary version object based of newVersion var tempVersion = newVersions[i]; // Override builds with new list tempVersion.builds = curBuilds.Distinct().ToArray(); // Override buildranges with new list tempVersion.buildRanges = curBuildRanges.Distinct().ToArray(); // Override layoutHashes with new list tempVersion.layoutHashes = curLayouthashes.Distinct().ToArray(); for (var j = 0; j < versionDefinition2.definitions.Count(); j++) { // Merge signedness from second file if it is different from current if (versionDefinition2.definitions[j].isSigned != tempVersion.definitions[j].isSigned) { tempVersion.definitions[j].isSigned = versionDefinition2.definitions[j].isSigned; } } // Override newVersion with temporary version object newVersions[i] = tempVersion; } } } newDefinition.versionDefinitions = newVersions.ToArray(); } } newDefinitions.Add(Path.GetFileNameWithoutExtension(firstFileName), newDefinition); } else { // Only 2nd dir has this file, use that newDefinitions.Add(dbName, reader.Read(Path.Combine(secondDir, file))); } } foreach (var file in firstDirFiles) { if (!secondDirFilesLC.Contains(file.ToLower())) { // Only 1st dir has this file, use that newDefinitions.Add(Path.GetFileNameWithoutExtension(file), reader.Read(Path.Combine(firstDir, file))); } } var writer = new DBDWriter(); foreach (var entry in newDefinitions) { var definitionCopy = entry.Value; var versionDefinitionCopy = definitionCopy.versionDefinitions.ToList(); for (var i = 0; i < versionDefinitionCopy.Count(); i++) { for (var j = 0; j < versionDefinitionCopy.Count(); j++) { if (i == j) { continue; // Do not compare same entry } if (versionDefinitionCopy[i].definitions.SequenceEqual(versionDefinitionCopy[j].definitions)) { if (versionDefinitionCopy[i].layoutHashes.Length > 0 && versionDefinitionCopy[j].layoutHashes.Length > 0 && !versionDefinitionCopy[i].layoutHashes.SequenceEqual(versionDefinitionCopy[j].layoutHashes)) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(Path.GetFileNameWithoutExtension(entry.Key) + " has 2 identical version definitions (" + (i + 1) + " and " + (j + 1) + ") but two different layouthashes, ignoring..."); Console.ResetColor(); } else { // Make list from current builds var curBuilds = versionDefinitionCopy[i].builds.ToList(); curBuilds.AddRange(versionDefinitionCopy[j].builds.ToList()); // Make list from current build ranges var curBuildRanges = versionDefinitionCopy[i].buildRanges.ToList(); curBuildRanges.AddRange(versionDefinitionCopy[j].buildRanges.ToList()); // Make list of current layouthashes var curLayouthashes = versionDefinitionCopy[i].layoutHashes.ToList(); curLayouthashes.AddRange(versionDefinitionCopy[j].layoutHashes.ToList()); // Create temporary version object based of newVersion var tempVersion = versionDefinitionCopy[i]; // Override builds with new list tempVersion.builds = curBuilds.Distinct().ToArray(); // Override buildranges with new list tempVersion.buildRanges = curBuildRanges.Distinct().ToArray(); // Override layoutHashes with new list tempVersion.layoutHashes = curLayouthashes.Distinct().ToArray(); // Override newVersion with temporary version object versionDefinitionCopy[i] = tempVersion; versionDefinitionCopy.RemoveAt(j); definitionCopy.versionDefinitions = versionDefinitionCopy.ToArray(); } } } } // Run through column definitions to see if there's any unused columns var columnDefinitionsCopy = definitionCopy.columnDefinitions.ToList(); foreach (var columnDefinition in columnDefinitionsCopy) { var columnUsed = false; foreach (var versionDefinition in definitionCopy.versionDefinitions) { foreach (var definition in versionDefinition.definitions) { if (definition.name == columnDefinition.Key) { columnUsed = true; } } } if (!columnUsed) { definitionCopy.columnDefinitions.Remove(columnDefinition.Key); } } writer.Save(definitionCopy, Path.Combine(targetDir, entry.Key + ".dbd"), true); } Console.WriteLine("Done, " + numLayoutsAdded + " new layouts added!"); //Console.ReadLine(); }
static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: <definitionsdir> (rewrite when done: bool, default false) (verbose: bool, default true) (rawRepoDir: location of WoWDBDefsRaw repository, default none)"); Environment.Exit(1); } var definitionDir = args[0]; var rewrite = false; var verbose = true; var checkRaw = false; var rawRepoDir = ""; if (args.Length >= 2 && args[1] == "true") { rewrite = true; } if (args.Length >= 3 && args[2] == "false") { verbose = false; } if (args.Length >= 4) { checkRaw = true; rawRepoDir = args[3]; } var errorEncountered = new List <string>(); foreach (var file in Directory.GetFiles(definitionDir)) { var dbName = Path.GetFileNameWithoutExtension(file); var reader = new DBDReader(); try { definitionCache.Add(dbName, reader.Read(file, true)); if (verbose) { Console.WriteLine("Read " + definitionCache[dbName].versionDefinitions.Length + " versions and " + definitionCache[dbName].columnDefinitions.Count + " columns for " + dbName); } if (rewrite) { var writer = new DBDWriter(); writer.Save(definitionCache[dbName], Path.Combine(definitionDir, dbName + ".dbd"), true); } } catch (Exception ex) { errorEncountered.Add(dbName); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Failed to read " + dbName + ": " + ex); Console.ResetColor(); } } Console.WriteLine("Read " + definitionCache.Count + " database definitions!"); var foreignKeys = 0; foreach (var definition in definitionCache) { foreach (var columnDefinition in definition.Value.columnDefinitions) { if (!string.IsNullOrEmpty(columnDefinition.Value.foreignTable) || !string.IsNullOrEmpty(columnDefinition.Value.foreignColumn)) { if (definitionCache.ContainsKey(columnDefinition.Value.foreignTable) && definitionCache[columnDefinition.Value.foreignTable].columnDefinitions.ContainsKey(columnDefinition.Value.foreignColumn)) { Console.ForegroundColor = ConsoleColor.Green; //Console.WriteLine(definition.Key + "." + columnDefinition.Key + " has a foreign key to " + columnDefinition.Value.foreignTable + "." + columnDefinition.Value.foreignColumn); } else { errorEncountered.Add(definition.Key); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(definition.Key + "." + columnDefinition.Key + " has a foreign key to " + columnDefinition.Value.foreignTable + "." + columnDefinition.Value.foreignColumn + " WHICH DOES NOT EXIST!"); } foreignKeys++; Console.ResetColor(); } } } Console.WriteLine("Checked " + foreignKeys + " foreign keys!"); if (checkRaw) { Console.WriteLine("Checking for differences between raw definitions and target definitions (limited to 9.0+)"); if (!Directory.Exists(rawRepoDir)) { throw new DirectoryNotFoundException("Could not find WoWDBDefsRaw repository"); } foreach (var definition in definitionCache) { foreach (var versionDefinition in definition.Value.versionDefinitions) { foreach (var build in versionDefinition.builds) { // TODO: There are issues in older expansions, but limit to 9.0+ for now if (build.expansion < 9) { continue; } var rawDefLocation = Path.Combine(rawRepoDir, build.ToString(), definition.Key + ".dbd"); // Definitions for really old versions aren't in raw repo, we can't check those. if (!File.Exists(rawDefLocation)) { continue; } var rawDefReader = new DBDReader(); var rawDef = rawDefReader.Read(rawDefLocation); if (versionDefinition.definitions.Length != rawDef.versionDefinitions[0].definitions.Length) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("[" + definition.Key + "] [" + build + "] Column count mismatch between raw (" + rawDef.versionDefinitions[0].definitions.Length + ") and target definition (" + versionDefinition.definitions.Length + ")"); errorEncountered.Add(definition.Key); continue; } for (var i = 0; i < versionDefinition.definitions.Length; i++) { var targetColDef = versionDefinition.definitions[i]; var rawColDef = rawDef.versionDefinitions[0].definitions[i]; if (rawColDef.isSigned != targetColDef.isSigned) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("[" + definition.Key + "] [" + build + "] " + rawColDef.name + " <-> " + targetColDef.name + " signedness mismatch: " + rawColDef.isSigned + " <-> " + targetColDef.isSigned); errorEncountered.Add(definition.Key); } if (rawColDef.size != targetColDef.size) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("[" + definition.Key + "] [" + build + "] " + rawColDef.name + " <-> " + targetColDef.name + " size mismatch: " + rawColDef.size + " <-> " + targetColDef.size); errorEncountered.Add(definition.Key); } if (rawColDef.arrLength != targetColDef.arrLength) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("[" + definition.Key + "] [" + build + "] " + rawColDef.name + " <-> " + targetColDef.name + " array length mismatch: " + rawColDef.arrLength + " <-> " + targetColDef.arrLength); errorEncountered.Add(definition.Key); } if (rawColDef.isRelation != targetColDef.isRelation) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("[" + definition.Key + "] [" + build + "] " + rawColDef.name + " <-> " + targetColDef.name + " relation mismatch: " + rawColDef.isRelation + " <-> " + targetColDef.isRelation); errorEncountered.Add(definition.Key); } Console.ResetColor(); } } } } } errorEncountered = errorEncountered.Distinct().ToList(); if (errorEncountered.Count != 0) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("There have been errors in the following DBDs:"); foreach (var dbName in errorEncountered) { Console.WriteLine(" - " + dbName); } Environment.Exit(1); } else { Console.WriteLine("Done"); } }
static void Main(string[] args) { if (args.Length < 3) { Console.WriteLine("Usage: <firstdir> <seconddir> <outdir>"); Environment.Exit(1); } var firstDir = args[0]; var secondDir = args[1]; var targetDir = args[2]; var firstDirFiles = new DirectoryInfo(firstDir).GetFiles().Select(o => o.Name).ToList(); var secondDirFiles = new DirectoryInfo(secondDir).GetFiles().Select(o => o.Name).ToList(); var newDefinitions = new Dictionary <string, DBDefinition>(); var reader = new DBDReader(); foreach (var file in secondDirFiles) { var dbName = Path.GetFileNameWithoutExtension(file); if (firstDirFiles.Contains(file)) { // Both directories have this file. Merge! var firstFile = reader.Read(Path.Combine(firstDir, file)); var secondFile = reader.Read(Path.Combine(secondDir, file)); var newDefinition = firstFile; // Merge column definitions foreach (var columnDefinition2 in secondFile.columnDefinitions) { var foundCol = false; foreach (var columnDefinition1 in firstFile.columnDefinitions) { if (columnDefinition2.Key.ToLower() == columnDefinition1.Key.ToLower()) { foundCol = true; var typeOverride = ""; if (columnDefinition2.Value.type != columnDefinition1.Value.type) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Types are different for (1)" + dbName + "::" + columnDefinition1.Key + " = " + columnDefinition1.Value.type + " and (2)" + dbName + "::" + columnDefinition2.Key + " = " + columnDefinition2.Value.type + ", using type " + columnDefinition2.Value.type + " from 2"); typeOverride = columnDefinition2.Value.type; // If this is an uncommon conversion (not uint -> int) override the version's column type if ((columnDefinition1.Value.type == "uint" && columnDefinition2.Value.type == "int") || (columnDefinition1.Value.type == "int" && columnDefinition2.Value.type == "uint")) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Type difference for column (1)" + dbName + "::" + columnDefinition1.Key + " = " + columnDefinition1.Value.type + " and(2)" + dbName + "::" + columnDefinition2.Key + " = " + columnDefinition2.Value.type + ", ignoring.."); } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Unexpected type difference for column (1)" + dbName + "::" + columnDefinition1.Key + " = " + columnDefinition1.Value.type + " and(2)" + dbName + "::" + columnDefinition2.Key + " = " + columnDefinition2.Value.type); Console.WriteLine("Adding override to type " + columnDefinition2.Value.type + " for the column in this version!"); for (var i = 0; i < secondFile.versionDefinitions.Length; i++) { for (var j = 0; j < secondFile.versionDefinitions[i].definitions.Length; j++) { if (secondFile.versionDefinitions[i].definitions[j].name == columnDefinition2.Key) { secondFile.versionDefinitions[i].definitions[j].typeOverride = columnDefinition2.Value.type; break; } } } } // Only change type in column definitions if we're not already overriding it if (string.IsNullOrWhiteSpace(typeOverride)) { var tempDefs = newDefinition.columnDefinitions; newDefinition.columnDefinitions = new Dictionary <string, ColumnDefinition>(); // TODO: Figure out a better way to "rebuild" column dictionary foreach (var columnDef1 in tempDefs) { if (columnDef1.Key == columnDefinition1.Key) { var newVal = columnDef1.Value; // Use newer type to override old one newVal.type = columnDefinition2.Value.type; newDefinition.columnDefinitions.Add(columnDef1.Key, newVal); } else { newDefinition.columnDefinitions.Add(columnDef1.Key, columnDef1.Value); } } } Console.ResetColor(); } if (columnDefinition2.Key != columnDefinition1.Key) { if (Utils.NormalizeColumn(columnDefinition2.Key, true) == columnDefinition1.Key) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Automagically fixed casing issue between (1)" + dbName + "::" + columnDefinition1.Key + " and (2)" + dbName + "::" + columnDefinition2.Key); for (var i = 0; i < secondFile.versionDefinitions.Length; i++) { for (var j = 0; j < secondFile.versionDefinitions[i].definitions.Length; j++) { if (secondFile.versionDefinitions[i].definitions[j].name == columnDefinition2.Key) { secondFile.versionDefinitions[i].definitions[j].name = Utils.NormalizeColumn(columnDefinition2.Key, true); break; } } } } else { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Unable to automagically fix casing issue between (1)" + dbName + "::" + columnDefinition1.Key + " and (2)" + dbName + "::" + columnDefinition2.Key + ", falling back to (1) naming"); for (var i = 0; i < secondFile.versionDefinitions.Length; i++) { for (var j = 0; j < secondFile.versionDefinitions[i].definitions.Length; j++) { if (secondFile.versionDefinitions[i].definitions[j].name == columnDefinition2.Key) { secondFile.versionDefinitions[i].definitions[j].name = columnDefinition1.Key; break; } } } } Console.ResetColor(); } break; } } if (!foundCol) { // Column was not found, add it Console.WriteLine(dbName + "::" + columnDefinition2.Key + " was not found found in first file!"); newDefinition.columnDefinitions.Add(columnDefinition2.Key, columnDefinition2.Value); } } // Merge version definitions foreach (var versionDefinition2 in secondFile.versionDefinitions) { var foundVersion = false; foreach (var versionDefinition1 in firstFile.versionDefinitions) { foreach (var layoutHash2 in versionDefinition2.layoutHashes) { if (versionDefinition1.layoutHashes.Contains(layoutHash2)) { foundVersion = true; break; } } // If layouthash was found, don't check builds if (foundVersion) { break; } // Check builds foreach (var build2 in versionDefinition2.builds) { foreach (var build1 in versionDefinition1.builds) { if (build1.Equals(build2)) { foundVersion = true; break; } } foreach (var buildranges1 in versionDefinition1.buildRanges) { if (build2.expansion == buildranges1.minBuild.expansion && build2.major == buildranges1.minBuild.major && build2.minor == buildranges1.minBuild.minor) { if (build2.build >= buildranges1.minBuild.build && build2.build <= buildranges1.maxBuild.build) { //Console.WriteLine("Build match? Build " + Utils.BuildToString(build2) + " seem to match with " + Utils.BuildToString(buildranges1.minBuild) + "-" + Utils.BuildToString(buildranges1.maxBuild)); foundVersion = true; break; } } } } } if (!foundVersion) { // Version was not found, add it! // TODO: Only for secondFile, not firstFile! var mergedWithPreviousBuild = false; var newVersions = newDefinition.versionDefinitions.ToList(); for (var i = 0; i < newVersions.Count; i++) { if (newVersions[i].definitions.SequenceEqual(versionDefinition2.definitions)) { Console.WriteLine("Looks like these two definition arrays are the same!"); var curBuilds = newVersions[i].builds.ToList(); curBuilds.AddRange(versionDefinition2.builds.ToList()); var tempVersion = newVersions[i]; tempVersion.builds = curBuilds.ToArray(); newVersions[i] = tempVersion; mergedWithPreviousBuild = true; } } if (!mergedWithPreviousBuild) { newVersions.Add(versionDefinition2); } newDefinition.versionDefinitions = newVersions.ToArray(); } else { // Version exists, compare stuff // TODO } } newDefinitions.Add(dbName, newDefinition); } else { // Only 2nd dir has this file, use that newDefinitions.Add(dbName, reader.Read(Path.Combine(secondDir, file))); } } foreach (var file in firstDirFiles) { if (!secondDirFiles.Contains(file)) { // Only 1st dir has this file, use that newDefinitions.Add(Path.GetFileNameWithoutExtension(file), reader.Read(Path.Combine(firstDir, file))); } } var writer = new DBDWriter(); foreach (var entry in newDefinitions) { writer.Save(entry.Value, Path.Combine(targetDir, entry.Key + ".dbd")); } //Console.ReadLine(); }
static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: <definitionsdir>"); Environment.Exit(1); } var definitionDir = args[0]; var buildList = new List <string>(); foreach (var file in Directory.GetFiles(definitionDir)) { var reader = new DBDReader(); definitionCache.Add(Path.GetFileNameWithoutExtension(file).ToLower(), reader.Read(file)); foreach (var versionDef in definitionCache[Path.GetFileNameWithoutExtension(file).ToLower()].versionDefinitions) { foreach (var versionBuild in versionDef.builds) { var buildString = versionBuild.ToString(); if (!buildList.Contains(buildString)) { buildList.Add(buildString); } } } } foreach (var dir in Directory.GetDirectories("Z:/DBCs/")) { var buildDir = dir.Replace("Z:/DBCs/", ""); if (!buildList.Contains(buildDir)) { continue; } if (Directory.Exists(Path.Combine(dir, "DBFilesClient"))) { foreach (var file in Directory.GetFiles(Path.Combine(dir, "DBFilesClient"))) { LoadDBC(file); } } else { foreach (var file in Directory.GetFiles(dir)) { LoadDBC(file); } } } if (foundError) { Environment.Exit(1); } }
static void Main(string[] args) { /* Check arguments */ if (args.Length < 3) { throw new ArgumentException("<path to DBCache.bin file> <path to DBD definitions directory> <SQLite file to use as unpatched base>"); } var hotfixFile = args[0]; if (!File.Exists(hotfixFile)) { throw new FileNotFoundException("Hotfix file " + hotfixFile + " not found!"); } var definitionDir = args[1]; if (!Directory.Exists(definitionDir)) { throw new FileNotFoundException("DBD definition directory " + definitionDir + " not found!"); } var inputDB = args[2]; if (!File.Exists(inputDB)) { throw new FileNotFoundException("Input SQLite DB not found!"); } /* Back up non-hotfix database to new database */ Console.WriteLine("Backing up non-hotfix database to new database.."); SQLiteConnection dbIn = new SQLiteConnection("Data Source= " + inputDB + ";foreign keys=True;Version=3;Read Only=True;"); SQLiteConnection dbNew = new SQLiteConnection("Data Source=export_withhotfix.db3;foreign keys=True;Version=3;"); dbIn.Open(); dbNew.Open(); dbIn.BackupDatabase(dbNew, "main", "main", -1, null, -1); dbIn.Close(); /* Read DBCache.bin */ Console.WriteLine("Reading hotfix file.."); var hotfixes = ReadHotfixFile(hotfixFile, definitionDir); var hotfixesCopy = hotfixes.ToList(); /* Sort and clean up data so we only have status 1/2 hotfixes left */ foreach (var hotfix in hotfixes) { if (hotfix.header.isValid == 4) { //Console.WriteLine("Removing hotfix of status 4 for " + hotfix.tableName + " " + hotfix.header.recordID); hotfixesCopy.Remove(hotfix); } else if (hotfix.header.isValid == 3) { //Console.WriteLine("Removing hotfixes before PushID " + hotfix.header.pushID + " for " + hotfix.tableName + " " + hotfix.header.recordID); foreach (var targetHotfix in hotfixes) { if (targetHotfix.tableName == hotfix.tableName && targetHotfix.header.recordID == hotfix.header.recordID && targetHotfix.header.pushID < hotfix.header.pushID) { //Console.WriteLine(" Removed hotfix " + targetHotfix.header.pushID + " for " + hotfix.tableName + " " + hotfix.header.recordID); hotfixesCopy.Remove(targetHotfix); } } hotfixesCopy.Remove(hotfix); } } hotfixes = hotfixesCopy; Dictionary <string, string> queryCache = new Dictionary <string, string>(); /* Parse hotfixes and update database */ Console.WriteLine("Parsing hotfix record data.."); foreach (var hotfix in hotfixes) { DBDefinition dbd; if (!dbdCache.ContainsKey(hotfix.tableName)) { if (!File.Exists(Path.Combine(definitionDir, hotfix.tableName + ".dbd"))) { Console.WriteLine("DBD for " + hotfix.tableName + " not found in DBD definitions, skipping hotfix.."); continue; } var reader = new DBDReader(); dbd = reader.Read(Path.Combine(definitionDir, hotfix.tableName + ".dbd")); dbdCache.Add(hotfix.tableName, dbd); } else { dbd = dbdCache[hotfix.tableName]; } var buildFound = false; VersionDefinitions?versionToUse = null; foreach (var definition in dbd.versionDefinitions) { foreach (var versionBuild in definition.builds) { if (versionBuild.build == hotfix.header.build) { versionToUse = definition; buildFound = true; } } } if (!buildFound) { Console.WriteLine("\nNo matching build found for table " + hotfix.tableName + " and build " + hotfix.header.build + ", skipping hotfix.."); continue; } var versionDef = (VersionDefinitions)versionToUse; var idField = ""; foreach (var field in versionDef.definitions) { if (field.isID) { idField = field.name; } } if (idField == "") { Console.WriteLine("Could not establish ID field name for " + hotfix.tableName + ", using ID.."); idField = "ID"; } if (hotfix.header.isValid == 2) { // Delete record if exists Console.Write("D"); //Console.WriteLine("Deleting DB record for hotfix " + hotfix.header.pushID + " for " + hotfix.tableName + " " + hotfix.header.recordID); using (var deleteCMD = new SQLiteCommand("DELETE FROM " + hotfix.tableName + " WHERE " + idField + " = " + hotfix.header.recordID, dbNew)) { deleteCMD.ExecuteNonQuery(); } continue; } var insertQueryString = ""; if (!queryCache.TryGetValue(hotfix.tableName, out insertQueryString)) { var sqlFields = new List <string>(); foreach (var field in versionDef.definitions) { var fieldName = field.name; if (field.name.ToLower() == "default") { fieldName = "_Default"; } if (field.name.ToLower() == "order") { fieldName = "_Order"; } if (field.name.ToLower() == "index") { fieldName = "_Index"; } if (field.arrLength > 0) { for (var i = 0; i < field.arrLength; i++) { sqlFields.Add(fieldName + "_" + i); } } else { sqlFields.Add(fieldName); } } insertQueryString = "INSERT INTO " + hotfix.tableName + "(`" + string.Join("`, `", sqlFields.ToArray()) + "`) VALUES(@" + string.Join(", @", sqlFields.ToArray()) + ")"; insertQueryString += " ON CONFLICT(" + idField + ") DO UPDATE SET "; for (var i = 0; i < sqlFields.Count; i++) { if (sqlFields[i] == idField) { continue; } insertQueryString += "`" + sqlFields[i] + "`" + " = @U" + sqlFields[i]; if (i != sqlFields.Count - 1) { insertQueryString += ", "; } } } var cmd = new SQLiteCommand(insertQueryString, dbNew); // Console.WriteLine(hotfix.tableName + " " + hotfix.header.recordID); //try //{ using (var dataBin = new BinaryReader(new MemoryStream(hotfix.data))) { foreach (var field in versionDef.definitions) { if (dataBin.BaseStream.Position == dataBin.BaseStream.Length) { continue; } if (field.isNonInline && field.isID) { cmd.Parameters.AddWithValue("@" + idField, hotfix.header.recordID); continue; } // Add parameter SetupParameter(cmd, dataBin, dbd, field); } if (dataBin.BaseStream.Length != dataBin.BaseStream.Position) { var tableHash = dataBin.ReadUInt32(); if (tableHash == 0) { continue; } dataBin.ReadBytes((int)(dataBin.BaseStream.Length - dataBin.BaseStream.Position)); //Console.WriteLine("Encountered an extra " + tableHash.ToString("X8") + " record of " + (dataBin.BaseStream.Length - dataBin.BaseStream.Position) + " bytes in " + hotfix.tableName + " ID " + hotfix.header.recordID); } } Console.Write("I"); cmd.ExecuteNonQuery(); //} //catch (Exception e) //{ // Console.WriteLine("Encountered exception while reading or updating record data:" + e.Message); //} } Console.WriteLine("\nCleaning up new database file and closing.."); using (var cmd = new SQLiteCommand("VACUUM", dbNew)) { cmd.ExecuteNonQuery(); } dbNew.Dispose(); }
public Type Generate(DBReader dbcReader, Stream dbd, Dictionary <string, string> dbs) { var dbdReader = new DBDReader(); var databaseDefinition = dbdReader.Read(dbd); Structs.VersionDefinitions?versionDefinition = null; if (!string.IsNullOrWhiteSpace(Build)) { var dbBuild = new Build(Build); LocStringSize = GetLocStringSize(dbBuild); Utils.GetVersionDefinitionByBuild(databaseDefinition, dbBuild, out versionDefinition); } if (versionDefinition == null && dbcReader.LayoutHash != 0) { var layoutHash = dbcReader.LayoutHash.ToString("X8"); Utils.GetVersionDefinitionByLayoutHash(databaseDefinition, layoutHash, out versionDefinition); } if (versionDefinition == null) { throw new FileNotFoundException("No definition found for this file."); } if (LocStringSize > 1 && (int)Locale >= LocStringSize) { throw new FormatException("Invalid locale for this file."); } var typeBuilder = ModuleBuilder.DefineType(Name, TypeAttributes.Public); var fields = versionDefinition.Value.definitions; var localiseStrings = Locale != Locale.None; foreach (var fieldDefinition in fields) { var columnInfo = databaseDefinition.columnDefinitions[fieldDefinition.name]; var isLocalisedString = columnInfo.type == "locstring" && LocStringSize > 1; var fieldType = FieldDefinitionToType(fieldDefinition, columnInfo, localiseStrings); var field = typeBuilder.DefineField(fieldDefinition.name, fieldType, FieldAttributes.Public); if (fieldDefinition.isID) { AddAttribute <IndexAttribute>(field, fieldDefinition.isNonInline); } if (fieldDefinition.arrLength > 1) { AddAttribute <CardinalityAttribute>(field, fieldDefinition.arrLength); } if (fieldDefinition.isRelation && fieldDefinition.isNonInline) { var metaDataFieldType = FieldDefinitionToType(fieldDefinition, columnInfo, localiseStrings); AddAttribute <NonInlineRelationAttribute>(field, metaDataFieldType); } if (isLocalisedString) { if (localiseStrings) { AddAttribute <LocaleAttribute>(field, (int)Locale, LocStringSize); } else { AddAttribute <CardinalityAttribute>(field, LocStringSize); typeBuilder.DefineField(fieldDefinition.name + "_mask", typeof(uint), FieldAttributes.Public); } } // export comments if (!string.IsNullOrEmpty(columnInfo.comment)) { AddAttribute <CommentAttribute>(field, columnInfo.comment); } // only add foreign keys that can be created if (fieldDefinition.isRelation && columnInfo.foreignTable != null && dbs.ContainsKey(columnInfo.foreignTable)) { AddAttribute <ForeignKeyAttribute>(field, columnInfo.foreignTable, columnInfo.foreignColumn); } } return(typeBuilder.CreateTypeInfo()); }
static void Main(string[] args) { if (args.Length < 2) { Console.WriteLine("Usage: <definitionsdir> <dbcdir>"); Environment.Exit(1); } var definitionDir = args[0]; if (!Directory.Exists(definitionDir)) { throw new DirectoryNotFoundException("Directory " + definitionDir + " does not exist!"); } dbcDir = args[1]; if (!Directory.Exists(dbcDir)) { throw new DirectoryNotFoundException("Directory " + dbcDir + " does not exist!"); } foreach (var file in Directory.GetFiles(definitionDir)) { var reader = new DBDReader(); definitionCache.Add(Path.GetFileNameWithoutExtension(file).ToLower(), reader.Read(file)); } var builds = new List <Build>(); foreach (var dir in Directory.GetDirectories(dbcDir)) { builds.Add(new Build(dir.Replace(dbcDir + "\\", ""))); } builds.Sort(); foreach (var build in builds) { if (build.expansion != 8 || build.major != 1) { continue; } Console.WriteLine("Checking " + build + ".."); if (Directory.Exists(Path.Combine(dbcDir, build.ToString(), "DBFilesClient"))) { foreach (var file in Directory.GetFiles(Path.Combine(dbcDir, build.ToString(), "DBFilesClient"))) { LoadDBC(file); } } else { foreach (var file in Directory.GetFiles(Path.Combine(dbcDir, build.ToString()))) { LoadDBC(file); } } } if (foundError) { Environment.Exit(1); } }
static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: <definitionsdir>"); Environment.Exit(1); } var definitionDir = args[0]; var rewrite = false; var verbose = true; if (args.Length >= 2 && args[1] == "true") { rewrite = true; } if (args.Length >= 3 && args[2] == "false") { verbose = false; } var errorEncountered = new List <string>(); foreach (var file in Directory.GetFiles(definitionDir)) { var dbName = Path.GetFileNameWithoutExtension(file); var reader = new DBDReader(); try { definitionCache.Add(dbName, reader.Read(file, true)); if (verbose) { Console.WriteLine("Read " + definitionCache[dbName].versionDefinitions.Length + " versions and " + definitionCache[dbName].columnDefinitions.Count + " columns for " + dbName); } if (rewrite) { var writer = new DBDWriter(); writer.Save(definitionCache[dbName], Path.Combine(definitionDir, dbName + ".dbd")); } } catch (Exception ex) { errorEncountered.Add(dbName); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Failed to read " + dbName + ": " + ex); Console.ResetColor(); } } Console.WriteLine("Read " + definitionCache.Count + " database definitions!"); var foreignKeys = 0; foreach (var definition in definitionCache) { foreach (var columnDefinition in definition.Value.columnDefinitions) { if (!string.IsNullOrEmpty(columnDefinition.Value.foreignTable) || !string.IsNullOrEmpty(columnDefinition.Value.foreignColumn)) { if (definitionCache.ContainsKey(columnDefinition.Value.foreignTable) && definitionCache[columnDefinition.Value.foreignTable].columnDefinitions.ContainsKey(columnDefinition.Value.foreignColumn)) { Console.ForegroundColor = ConsoleColor.Green; //Console.WriteLine(definition.Key + "." + columnDefinition.Key + " has a foreign key to " + columnDefinition.Value.foreignTable + "." + columnDefinition.Value.foreignColumn); } else { errorEncountered.Add(definition.Key); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(definition.Key + "." + columnDefinition.Key + " has a foreign key to " + columnDefinition.Value.foreignTable + "." + columnDefinition.Value.foreignColumn + " WHICH DOES NOT EXIST!"); } foreignKeys++; Console.ResetColor(); } } } Console.WriteLine("Checked " + foreignKeys + " foreign keys!"); if (errorEncountered.Count != 0) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("There have been errors in the following dbds:"); foreach (var dbName in errorEncountered) { Console.WriteLine(" - " + dbName); } Environment.Exit(1); } else { Console.WriteLine("Done"); } }
static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: <definitionsdir>"); Environment.Exit(1); } var definitionDir = args[0]; foreach (var file in Directory.GetFiles(definitionDir)) { var reader = new DBDReader(); definitionCache.Add(Path.GetFileNameWithoutExtension(file).ToLower(), reader.Read(file)); } foreach (var dir in Directory.GetDirectories("Z:/DBCs/")) { if (Directory.Exists(Path.Combine(dir, "DBFilesClient"))) { foreach (var file in Directory.GetFiles(Path.Combine(dir, "DBFilesClient"))) { LoadDBC(file); } } else { foreach (var file in Directory.GetFiles(dir)) { LoadDBC(file); } } } Console.ReadLine(); }
static void Main(string[] args) { if (args.Length < 2) { throw new ArgumentException("Need DBCache.bin location and DBef dir location!"); } var actuallyV8 = false; var dumpKeys = false; if (args.Length == 3 && args[2] == "true") { dumpKeys = true; } var hotfixFile = args[0]; if (!File.Exists(hotfixFile)) { throw new FileNotFoundException("File " + hotfixFile + " not found!"); } var definitionDir = args[1]; if (!Directory.Exists(definitionDir)) { throw new FileNotFoundException("DBD definition directory " + definitionDir + " not found!"); } var tableHashes = new Dictionary <uint, string>(); foreach (var file in Directory.GetFiles(definitionDir)) { var dbName = Path.GetFileNameWithoutExtension(file); tableHashes.Add(Utils.Hash(dbName.ToUpper()), dbName); } var xfthMagic = 'X' << 0 | 'F' << 8 | 'T' << 16 | 'H' << 24; uint build; var hotfixes = new List <DBCacheEntry>(); using (var ms = new MemoryStream(File.ReadAllBytes(hotfixFile))) using (var bin = new BinaryReader(ms)) { if (bin.ReadUInt32() != xfthMagic) { throw new Exception("Invalid hotfix file!"); } var version = bin.ReadUInt32(); if (version != 7 && version != 8) { throw new Exception("Unsupported version: " + version); } build = bin.ReadUInt32(); var hash = bin.ReadBytes(32); // --- Temporary code to detect if DBCache is actually V8 or not by checking if next hotfix magic is in the right spot or not if (version == 8) { var prePos = bin.BaseStream.Position; if (bin.ReadUInt32() != xfthMagic) { throw new Exception("Invalid hotfix entry magic!"); } bin.ReadUInt32(); // PushID bin.ReadUInt32(); // UniqueID but also maybe not! bin.ReadUInt32(); // TableHash bin.ReadUInt32(); // RecordID var dataSize = bin.ReadInt32(); // DataSize bin.ReadBytes(dataSize + 4); if (bin.ReadUInt32() != xfthMagic) { actuallyV8 = false; } else { actuallyV8 = true; } bin.BaseStream.Position = prePos; } // -- End of temp code while (bin.BaseStream.Length > bin.BaseStream.Position) { var hotfix = new DBCacheEntry(); hotfix.header = new DBCacheEntryHeader(); hotfix.header.magic = bin.ReadUInt32(); hotfix.header.pushID = bin.ReadInt32(); if (actuallyV8) { hotfix.header.uniqueID = bin.ReadUInt32(); } hotfix.header.tableHash = bin.ReadUInt32(); hotfix.header.recordID = bin.ReadUInt32(); hotfix.header.dataSize = bin.ReadInt32(); hotfix.header.isValid = bin.ReadByte(); hotfix.header.pad0 = bin.ReadByte(); hotfix.header.pad1 = bin.ReadByte(); hotfix.header.pad2 = bin.ReadByte(); //hotfix.header = bin.Read<DBCacheEntryHeader>(); if (hotfix.header.magic != xfthMagic) { throw new Exception("Invalid hotfix entry magic!"); } if (tableHashes.ContainsKey(hotfix.header.tableHash)) { hotfix.tableName = tableHashes[hotfix.header.tableHash]; } else { hotfix.tableName = "UNKNOWN " + hotfix.header.tableHash.ToString("X8"); } hotfix.data = bin.ReadBytes(hotfix.header.dataSize); hotfixes.Add(hotfix); } } var dbdCache = new Dictionary <string, DBDefinition>(); var filteredList = new List <HotfixEntry>(); foreach (var hotfix in hotfixes) { var hotfixDataMD5 = ""; if (hotfix.data.Length > 0) { using (var md5 = System.Security.Cryptography.MD5.Create()) { md5.TransformFinalBlock(hotfix.data, 0, hotfix.data.Length); hotfixDataMD5 = BitConverter.ToString(md5.Hash).Replace("-", string.Empty).ToLower(); } } filteredList.Add(new HotfixEntry { pushID = hotfix.header.pushID, recordID = hotfix.header.recordID, isValid = hotfix.header.isValid, tableName = hotfix.tableName, dataMD5 = hotfixDataMD5 }); if (dumpKeys) { if (!dbdCache.ContainsKey(hotfix.tableName) && File.Exists(Path.Combine(definitionDir, hotfix.tableName + ".dbd"))) { var reader = new DBDReader(); var dbd = reader.Read(Path.Combine(definitionDir, hotfix.tableName + ".dbd")); dbdCache.Add(hotfix.tableName, dbd); } if (dbdCache.ContainsKey(hotfix.tableName) && hotfix.header.isValid == 1) { var dbd = dbdCache[hotfix.tableName]; VersionDefinitions?versionToUse = null; var buildFound = false; foreach (var definition in dbd.versionDefinitions) { foreach (var versionBuild in definition.builds) { if (versionBuild.build == build) { versionToUse = definition; buildFound = true; } } } if (buildFound) { long dataLength = 0; var versionDef = (VersionDefinitions)versionToUse; //Console.WriteLine(hotfix.header.pad0 + " " + hotfix.header.pad1 + " " + hotfix.header.pad2 + " " + hotfix.tableName + " " + hotfix.header.recordID); try { using (var dataBin = new BinaryReader(new MemoryStream(hotfix.data))) { foreach (var field in versionDef.definitions) { if (dataBin.BaseStream.Position == dataBin.BaseStream.Length) { continue; } if (field.isNonInline && field.isID) { continue; } if (field.arrLength > 0) { for (var i = 0; i < field.arrLength; i++) { if (dataBin.BaseStream.Position == dataBin.BaseStream.Length) { continue; } if (field.size == 0) { if (dbd.columnDefinitions[field.name].type == "float") { dataBin.ReadSingle(); dataLength += 4; } else { var prevPos = dataBin.BaseStream.Position; dataBin.ReadCString(); dataLength += dataBin.BaseStream.Position - prevPos; } } else { dataLength += field.size / 8; dataBin.ReadBytes(field.size / 8); } } } else { if (field.size == 0) { if (dbd.columnDefinitions[field.name].type == "float") { dataBin.ReadSingle(); dataLength += 4; } else { var prevPos = dataBin.BaseStream.Position; dataBin.ReadCString(); dataLength += dataBin.BaseStream.Position - prevPos; } } else { dataLength += field.size / 8; dataBin.ReadBytes(field.size / 8); } } } if (dataBin.BaseStream.Length != dataBin.BaseStream.Position) { var tableHash = dataBin.ReadUInt32(); if (tableHash == 0) { continue; } if (!tableHashes.ContainsKey(tableHash)) { Console.WriteLine("Encountered an extra " + tableHash.ToString("X8") + " (unk table) record of " + (dataBin.BaseStream.Length - dataBin.BaseStream.Position) + " bytes in " + hotfix.tableName + " ID " + hotfix.header.recordID); } else { Console.WriteLine("Encountered an extra " + tableHashes[tableHash] + " record of " + (dataBin.BaseStream.Length - dataBin.BaseStream.Position) + " bytes in " + hotfix.tableName + " ID " + hotfix.header.recordID); if (tableHashes[tableHash] == "TactKey") { var lookup = dataBin.ReadUInt64(); var keyBytes = dataBin.ReadBytes(16); Console.WriteLine(lookup.ToString("X8").PadLeft(16, '0') + " " + BitConverter.ToString(keyBytes).Replace("-", "")); } } } } } catch (Exception e) { Console.WriteLine("Encountered exception while reading record data:" + e.Message); } } } } } var cache = new DBCache(); cache.build = build; cache.entries = filteredList.ToArray(); if (!dumpKeys) { Console.WriteLine(JsonConvert.SerializeObject(cache, Formatting.None)); } }
static void Main(string[] args) { if (!Directory.Exists(args[0])) { throw new DirectoryNotFoundException("Directory " + args[0] + " does not exist!"); } var builds = File.ReadAllLines("builds.txt"); var files = Directory.GetFiles(args[0]); var textWriter = new StreamWriter("output.csv"); var csv = new CsvWriter(textWriter); csv.WriteField(""); for (var b = 0; b < builds.Length; b++) { string rotatedString = ""; foreach (var character in builds[b]) { rotatedString += character + Environment.NewLine; } csv.WriteField(rotatedString); } csv.NextRecord(); for (var f = 0; f < files.Length; f++) { var file = files[f]; var dbName = Path.GetFileNameWithoutExtension(file); var reader = new DBDReader(); var dbd = reader.Read(file); csv.WriteField(dbName); for (var b = 0; b < builds.Length; b++) { var containsBuild = false; var build = new Build(builds[b]); foreach (var versionDefinition in dbd.versionDefinitions) { if (versionDefinition.builds.Contains(build)) { containsBuild = true; } foreach (var buildRange in versionDefinition.buildRanges) { if (buildRange.Contains(build)) { containsBuild = true; } } } if (containsBuild) { csv.WriteField("X"); } else { csv.WriteField(""); } } csv.NextRecord(); } csv.Flush(); }