public Task ExportToDbc(IDatabaseAdapter adapter, MainWindow.UpdateProgressFunc updateProgress, string IdKey, string bindingName) { return(Task.Run(() => { var binding = BindingManager.GetInstance().FindBinding(bindingName); if (binding == null) { throw new Exception("Binding not found: " + bindingName); } var orderClause = binding.Fields.FirstOrDefault(f => f.Name.Equals(IdKey)) != null ? $" ORDER BY `{IdKey}`" : ""; var rows = adapter.Query(string.Format($"SELECT * FROM `{bindingName}`{orderClause}")).Rows; uint numRows = uint.Parse(rows.Count.ToString()); // Hardcode for 3.3.5a 12340 Header = new DBCHeader(); Header.FieldCount = (uint)binding.Fields.Count(); Header.Magic = 1128416343; Header.RecordCount = numRows; Header.RecordSize = (uint)binding.CalcRecordSize(); Header.StringBlockSize = 0; var body = new DBCBodyToSerialize(); body.Records = new List <DataRow>((int)Header.RecordCount); for (int i = 0; i < numRows; ++i) { body.Records.Add(rows[i]); } Header.StringBlockSize = body.GenerateStringOffsetsMap(binding); SaveDbcFile(updateProgress, body, binding); })); }
public Task ExportToDbc(IDatabaseAdapter adapter, MainWindow.UpdateProgressFunc updateProgress, string IdKey, string bindingName) { return(Task.Run(() => { var binding = BindingManager.GetInstance().FindBinding(bindingName); if (binding == null) { throw new Exception("Binding not found: " + bindingName); } var body = new DBCBodyToSerialize(); var orderClause = ""; if (binding.OrderOutput) { orderClause = binding.Fields.FirstOrDefault(f => f.Name.Equals(IdKey)) != null ? $" ORDER BY `{IdKey}`" : ""; } body.Records = LoadRecords(adapter, bindingName, orderClause, updateProgress); var numRows = body.Records.Count(); if (numRows == 0) { throw new Exception("No rows to export"); } Header = new DBCHeader { FieldCount = (uint)binding.Fields.Count(), // Magic is always 'WDBC' https://wowdev.wiki/DBC Magic = 1128416343, RecordCount = (uint)numRows, RecordSize = (uint)binding.CalcRecordSize(), StringBlockSize = body.GenerateStringOffsetsMap(binding) }; SaveDbcFile(updateProgress, body, binding); })); }
public Task export(DBAdapter adapter, MainWindow.UpdateProgressFunc updateProgress) { return(Task.Run(() => { var rows = adapter.query(string.Format("SELECT * FROM `{0}` ORDER BY `ID`", adapter.Table)).Rows; uint numRows = UInt32.Parse(rows.Count.ToString()); // Hardcode for 3.3.5a 12340 header = new DBC_Header(); header.FieldCount = 234; header.Magic = 1128416343; header.RecordCount = numRows; header.RecordSize = 936; header.StringBlockSize = 0; body.records = new Spell_DBC_RecordMap[numRows]; for (int i = 0; i < numRows; ++i) { body.records[i] = new Spell_DBC_RecordMap(); if (i % 250 == 0) { updateProgress((double)i / (double)numRows); } body.records[i].record = new Spell_DBC_Record(); body.records[i].spellName = new string[9]; body.records[i].spellDesc = new string[9]; body.records[i].spellRank = new string[9]; body.records[i].spellTool = new string[9]; body.records[i].record.SpellName = new UInt32[9]; body.records[i].record.SpellDescription = new UInt32[9]; body.records[i].record.SpellRank = new UInt32[9]; body.records[i].record.SpellToolTip = new UInt32[9]; body.records[i].record.SpellNameFlag = new UInt32[8]; body.records[i].record.SpellDescriptionFlags = new UInt32[8]; body.records[i].record.SpellRankFlags = new UInt32[8]; body.records[i].record.SpellToolTipFlags = new UInt32[8]; var fields = body.records[i].record.GetType().GetFields(); foreach (var f in fields) { switch (Type.GetTypeCode(f.FieldType)) { case TypeCode.UInt32: { f.SetValueForValueType(ref body.records[i].record, UInt32.Parse(rows[i][f.Name].ToString())); break; } case TypeCode.Int32: { f.SetValueForValueType(ref body.records[i].record, Int32.Parse(rows[i][f.Name].ToString())); break; } case TypeCode.Single: { f.SetValueForValueType(ref body.records[i].record, Single.Parse(rows[i][f.Name].ToString())); break; } case TypeCode.Object: { var attr = f.GetCustomAttribute <HandleField>(); if (attr != null) { if (attr.Method == 1) { switch (attr.Type) { case 1: { for (int j = 0; j < attr.Count; ++j) { body.records[i].spellName[j] = rows[i]["SpellName" + j].ToString(); } break; } case 2: { for (int j = 0; j < attr.Count; ++j) { body.records[i].spellRank[j] = rows[i]["SpellRank" + j].ToString(); } break; } case 3: { for (int j = 0; j < attr.Count; ++j) { body.records[i].spellDesc[j] = rows[i]["SpellDescription" + j].ToString(); } break; } case 4: { for (int j = 0; j < attr.Count; ++j) { body.records[i].spellTool[j] = rows[i]["SpellToolTip" + j].ToString(); } break; } default: throw new Exception("ERROR: Unhandled type: " + f.FieldType + " on field: " + f.Name + " TYPE: " + attr.Type); } break; } else if (attr.Method == 2) { switch (attr.Type) { case 1: { for (int j = 0; j < attr.Count; ++j) { body.records[i].record.SpellNameFlag[j] = UInt32.Parse(rows[i]["SpellNameFlag" + j].ToString()); } break; } case 2: { for (int j = 0; j < attr.Count; ++j) { body.records[i].record.SpellRankFlags[j] = UInt32.Parse(rows[i]["SpellRankFlags" + j].ToString()); } break; } case 3: { for (int j = 0; j < attr.Count; ++j) { body.records[i].record.SpellDescriptionFlags[j] = UInt32.Parse(rows[i]["SpellDescriptionFlags" + j].ToString()); } break; } case 4: { for (int j = 0; j < attr.Count; ++j) { body.records[i].record.SpellToolTipFlags[j] = UInt32.Parse(rows[i]["SpellToolTipFlags" + j].ToString()); } break; } default: throw new Exception("ERROR: Unhandled type: " + f.FieldType + " on field: " + f.Name + " TYPE: " + attr.Type); } break; } } goto default; } default: throw new Exception("Unhandled type: " + Type.GetTypeCode(f.FieldType).ToString() + ", field: " + f.Name); } } } SaveDBCFile(); })); }
public Task ImportToSql(IDatabaseAdapter adapter, MainWindow.UpdateProgressFunc UpdateProgress, string IdKey, string bindingName) { return(Task.Run(() => { var binding = BindingManager.GetInstance().FindBinding(bindingName); adapter.Execute(string.Format(adapter.GetTableCreateString(binding), binding.Name)); uint currentRecord = 0; uint count = Header.RecordCount; uint updateRate = count < 100 ? 100 : count / 100; uint index = 0; StringBuilder q = null; foreach (var recordMap in Body.RecordMaps) { // This might be needed? Disabled unless bugs are reported around this //if (r.record.ID == 0) // continue; if (index == 0 || index % 250 == 0) { if (q != null) { q.Remove(q.Length - 2, 2); adapter.Execute(q.ToString()); } q = new StringBuilder(); q.Append(string.Format("INSERT INTO `{0}` VALUES ", bindingName)); } if (++index % updateRate == 0) { // Visual studio says these casts are redundant but it does not work without them double percent = (double)index / (double)count; UpdateProgress(percent); } currentRecord = recordMap.ContainsKey(IdKey) ? (uint)recordMap[IdKey] : 0; q.Append("("); foreach (var field in binding.Fields) { switch (field.Type) { case BindingType.INT: case BindingType.UINT: { q.Append(string.Format("'{0}', ", recordMap[field.Name])); break; } case BindingType.FLOAT: case BindingType.DOUBLE: { q.Append(string.Format("REPLACE('{0}', ',', '.'), ", recordMap[field.Name])); break; } case BindingType.STRING_OFFSET: { var strOffset = (uint)recordMap[field.Name]; var lookupResult = Reader.LookupStringOffset(strOffset); q.Append(string.Format("\'{0}\', ", adapter.EscapeString(lookupResult))); break; } case BindingType.UNKNOWN: break; default: throw new Exception($"ERROR: Record[{currentRecord}] Unhandled type: {field.Type} on field: {field.Name}"); } } q.Remove(q.Length - 2, 2); q.Append("), "); } if (q.Length > 0) { q.Remove(q.Length - 2, 2); adapter.Execute(q.ToString()); } // We have attempted to import the Spell.dbc so clean up unneeded data // This will be recreated if the import process is started again Reader.CleanStringsMap(); })); }
protected void SaveDbcFile(MainWindow.UpdateProgressFunc updateProgress, DBCBodyToSerialize body, Binding.Binding binding) { string path = $"Export/{binding.Name}.dbc"; Directory.CreateDirectory(Path.GetDirectoryName(path)); if (File.Exists(path)) { File.Delete(path); } using (FileStream fileStream = new FileStream(path, FileMode.Create)) { using (BinaryWriter writer = new BinaryWriter(fileStream)) { // Write the header file int count = Marshal.SizeOf(typeof(DBCHeader)); byte[] buffer = new byte[count]; GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); Marshal.StructureToPtr(Header, handle.AddrOfPinnedObject(), true); writer.Write(buffer, 0, count); handle.Free(); // Write each record for (int i = 0; i < Header.RecordCount; ++i) { if (i % 250 == 0) { // Visual studio says these casts are redundant but it does not work without them double percent = (double)i / (double)Header.RecordCount; updateProgress(percent); } var record = body.Records[i]; foreach (var entry in binding.Fields) { if (!record.Table.Columns.Contains(entry.Name)) { throw new Exception($"Column binding not found {entry.Name} in table, using binding {binding.Name}.txt"); } var data = record[entry.Name].ToString(); if (entry.Type == BindingType.INT) { if (int.TryParse(data, out int value)) { writer.Write(value); } else { writer.Write(0); } } else if (entry.Type == BindingType.UINT) { if (uint.TryParse(data, out uint value)) { writer.Write(value); } else { writer.Write(0u); } } else if (entry.Type == BindingType.FLOAT) { if (float.TryParse(data, out float value)) { writer.Write(value); } else { writer.Write(0f); } } else if (entry.Type == BindingType.DOUBLE) { if (double.TryParse(data, out double value)) { writer.Write(value); } else { writer.Write(0d); } } else if (entry.Type == BindingType.STRING_OFFSET) { writer.Write(data.Length == 0 ? 0 : body.OffsetStorage[data.GetHashCode()]); } else { throw new Exception($"Unknwon type: {entry.Type} on entry {entry.Name} binding {binding.Name}"); } } } // Write string block int[] offsetsStored = body.OffsetStorage.Values.ToArray(); writer.Write(Encoding.UTF8.GetBytes("\0")); for (int i = 0; i < offsetsStored.Length; ++i) { writer.Write(Encoding.UTF8.GetBytes(body.ReverseStorage[offsetsStored[i]] + "\0")); } } } }
protected List <Dictionary <string, object> > LoadRecords(IDatabaseAdapter adapter, string bindingName, string orderClause, MainWindow.UpdateProgressFunc updateProgress) { const int pageSize = 1000; int totalCount; using (var queryData = adapter.Query($"SELECT COUNT(*) FROM `{bindingName}`")) { totalCount = int.Parse(queryData.Rows[0][0].ToString()); } var lowerBounds = 0; var results = LoadRecordPage(lowerBounds, pageSize, adapter, bindingName, orderClause); var loadCount = results.Count; while (loadCount > 0) { lowerBounds += pageSize; // Visual studio says these casts are redundant but it does not work without them double percent = (double)Math.Min(totalCount, lowerBounds) / (double)totalCount; updateProgress(percent); var page = LoadRecordPage(lowerBounds, pageSize, adapter, bindingName, orderClause); loadCount = page.Count; page.ForEach(results.Add); } return(results); }
public Task Export(IDatabaseAdapter adapter, MainWindow.UpdateProgressFunc updateProgress) { return(ExportToDbc(adapter, updateProgress, "ID", "Spell")); }
public Task ImportToSql(IDatabaseAdapter adapter, MainWindow.UpdateProgressFunc UpdateProgress, string bindingName) { return(ImportToSql(adapter, UpdateProgress, "ID", bindingName)); }