private static void Load() { liquidObjectToLVFDict = new Dictionary <uint, ushort>(); var dbcd = new DBCD.DBCD(new CASCDBCProvider(), new DBCD.Providers.GithubDBDProvider()); var loStorage = dbcd.Load("LiquidObject", CASC.BuildName); var ltStorage = dbcd.Load("LiquidType", CASC.BuildName); var lmStorage = dbcd.Load("LiquidMaterial", CASC.BuildName); foreach (dynamic loEntry in loStorage.Values) { foreach (dynamic ltEntry in ltStorage.Values) { if (loEntry.LiquidTypeID == ltEntry.ID) { foreach (dynamic lmEntry in lmStorage.Values) { if (ltEntry.MaterialID == lmEntry.ID) { liquidObjectToLVFDict.Add((uint)loEntry.ID, (ushort)lmEntry.LVF); } } } } } loaded = true; }
static DBCD.IDBCDStorage LoadMaps() { var dbdProvider = new GithubDBDProvider(); var dbcProvider = new MirrorDBCProvider(BuildConfig); var dbcd = new DBCD.DBCD(dbcProvider, dbdProvider); var maps = dbcd.Load("Map"); return(maps); }
static void Main(string[] args) { var dbcd = new DBCD.DBCD(new ItemSparseProvider(), new GithubDBDProvider()); var ItemSparse = dbcd.Load("ItemSparse", "8.2.5.31921"); foreach (dynamic row in ItemSparse.Values) { Console.WriteLine(row.ID + " " + row.Display_lang); } }
static void Main(string[] args) { var dbcProvider = new DBCProvider(); var dbdProvider = new DBDProvider(); if (args.Length > 0) { foreach (var file in Directory.GetFiles(Path.Combine(SettingManager.dbcDir, args[0], "dbfilesclient"), "*.*", SearchOption.AllDirectories)) { var db = Path.GetFileNameWithoutExtension(file); try { Console.WriteLine(); Console.WriteLine(file.Replace(SettingManager.dbcDir + "\\", "")); DBCD.DBCD storage = new DBCD.DBCD(dbcProvider, dbdProvider); storage.Load(db, args[0]); } catch (Exception e) { Console.WriteLine(e.Message + " " + e.StackTrace); } } } else { foreach (var dir in Directory.GetDirectories(SettingManager.dbcDir)) { var build = dir.Replace(SettingManager.dbcDir + "\\", ""); foreach (var file in Directory.GetFiles(Path.Combine(dir, "dbfilesclient"), "*.*", SearchOption.AllDirectories)) { var db = Path.GetFileNameWithoutExtension(file); try { Console.WriteLine(); Console.WriteLine(file.Replace(SettingManager.dbcDir + "\\", "")); DBCD.DBCD storage = new DBCD.DBCD(dbcProvider, dbdProvider); storage.Load(db, build); } catch (Exception e) { Console.WriteLine(e.Message + " " + e.StackTrace); } } } } }
public static void ExportADT(uint wdtFileDataID, byte tileX, byte tileY, BackgroundWorker exportworker = null) { if (exportworker == null) { exportworker = new BackgroundWorker(); exportworker.WorkerReportsProgress = true; } var outdir = ConfigurationManager.AppSettings["outdir"]; var customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone(); customCulture.NumberFormat.NumberDecimalSeparator = "."; System.Threading.Thread.CurrentThread.CurrentCulture = customCulture; var MaxSize = 51200 / 3.0; var TileSize = MaxSize / 32.0; var ChunkSize = TileSize / 16.0; var UnitSize = ChunkSize / 8.0; var UnitSizeHalf = UnitSize / 2.0; if (!Listfile.TryGetFilename(wdtFileDataID, out string wdtFilename)) { Logger.WriteLine("ADT OBJ Exporter: WDT {0} has no known filename, skipping export!", wdtFileDataID); return; } var mapName = Path.GetFileNameWithoutExtension(wdtFilename); var file = "world/maps/" + mapName + "/" + mapName + "_" + tileX.ToString() + "_" + tileY.ToString() + ".adt"; var reader = new ADTReader(); reader.LoadADT(wdtFileDataID, tileX, tileY, true, wdtFilename); var adt = reader.adtfile; if (adt.chunks == null) { Logger.WriteLine("ADT OBJ Exporter: File {0} has no chunks, skipping export!", file); return; } Logger.WriteLine("ADT OBJ Exporter: Starting export of {0}..", file); Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file))); exportworker.ReportProgress(0, "Loading ADT " + file); var renderBatches = new List <Structs.RenderBatch>(); var verticelist = new List <Structs.Vertex>(); var indicelist = new List <int>(); var materials = new Dictionary <int, string>(); ConfigurationManager.RefreshSection("appSettings"); var bakeQuality = ConfigurationManager.AppSettings["bakeQuality"]; // Calculate ADT offset in world coordinates var adtStartX = ((adt.x - 32) * TileSize) * -1; var adtStartY = ((adt.y - 32) * TileSize) * -1; // Calculate first chunk offset in world coordinates var initialChunkX = adtStartY + (adt.chunks[0].header.indexX * ChunkSize) * -1; var initialChunkY = adtStartX + (adt.chunks[0].header.indexY * ChunkSize) * -1; uint ci = 0; for (var x = 0; x < 16; x++) { double xOfs = x / 16d; for (var y = 0; y < 16; y++) { double yOfs = y / 16d; var genx = (initialChunkX + (ChunkSize * x) * -1); var geny = (initialChunkY + (ChunkSize * y) * -1); var chunk = adt.chunks[ci]; var off = verticelist.Count(); var batch = new Structs.RenderBatch(); for (int i = 0, idx = 0; i < 17; i++) { bool isSmallRow = (i % 2) != 0; int rowLength = isSmallRow ? 8 : 9; for (var j = 0; j < rowLength; j++) { var v = new Structs.Vertex(); v.Normal = new Structs.Vector3D { X = (double)chunk.normals.normal_0[idx] / 127, Y = (double)chunk.normals.normal_2[idx] / 127, Z = (double)chunk.normals.normal_1[idx] / 127 }; var px = geny - (j * UnitSize); var py = chunk.vertices.vertices[idx++] + chunk.header.position.Z; var pz = genx - (i * UnitSizeHalf); v.Position = new Structs.Vector3D { X = px, Y = py, Z = pz }; if ((i % 2) != 0) { v.Position.X = (px - UnitSizeHalf); } double ofs = j; if (isSmallRow) { ofs += 0.5; } if (bakeQuality == "none") { v.TexCoord = new Structs.Vector2D { X = (j + (((i % 2) != 0) ? 0.5f : 0f)) / 8f, Y = (i * 0.5f) / 8f }; } else if (bakeQuality == "high") { double tx = ofs / 8d; double ty = 1 - (i / 16d); v.TexCoord = new Structs.Vector2D { X = tx, Y = ty }; } else { double tx = -(v.Position.X - initialChunkY) / TileSize; double ty = (v.Position.Z - initialChunkX) / TileSize; v.TexCoord = new Structs.Vector2D { X = tx, Y = ty }; } verticelist.Add(v); } } batch.firstFace = (uint)indicelist.Count(); // Stupid C# and its structs var holesHighRes = new byte[8]; holesHighRes[0] = chunk.header.holesHighRes_0; holesHighRes[1] = chunk.header.holesHighRes_1; holesHighRes[2] = chunk.header.holesHighRes_2; holesHighRes[3] = chunk.header.holesHighRes_3; holesHighRes[4] = chunk.header.holesHighRes_4; holesHighRes[5] = chunk.header.holesHighRes_5; holesHighRes[6] = chunk.header.holesHighRes_6; holesHighRes[7] = chunk.header.holesHighRes_7; for (int j = 9, xx = 0, yy = 0; j < 145; j++, xx++) { if (xx >= 8) { xx = 0; ++yy; } var isHole = true; // Check if chunk is using low-res holes if ((chunk.header.flags & 0x10000) == 0) { // Calculate current hole number var currentHole = (int)Math.Pow(2, Math.Floor(xx / 2f) * 1f + Math.Floor(yy / 2f) * 4f); // Check if current hole number should be a hole if ((chunk.header.holesLowRes & currentHole) == 0) { isHole = false; } } else { // Check if current section is a hole if (((holesHighRes[yy] >> xx) & 1) == 0) { isHole = false; } } if (!isHole) { indicelist.AddRange(new int[] { off + j + 8, off + j - 9, off + j }); indicelist.AddRange(new int[] { off + j - 9, off + j - 8, off + j }); indicelist.AddRange(new int[] { off + j - 8, off + j + 9, off + j }); indicelist.AddRange(new int[] { off + j + 9, off + j + 8, off + j }); // Generates quads instead of 4x triangles //indicelist.AddRange(new int[] { off + j + 8, off + j - 9, off + j - 8 }); //indicelist.AddRange(new int[] { off + j - 8, off + j + 9, off + j + 8 }); } if ((j + 1) % (9 + 8) == 0) { j += 9; } } if (bakeQuality == "high") { materials.Add((int)ci + 1, Path.GetFileNameWithoutExtension(file).Replace(" ", "") + "_" + ci); batch.materialID = ci + 1; } else { if (!materials.ContainsKey(1)) { materials.Add(1, Path.GetFileNameWithoutExtension(file).Replace(" ", "")); } batch.materialID = (uint)materials.Count(); } batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace; if (bakeQuality == "none") { // Build alpha textures, export raw and height textures var rawMaterials = new List <Renderer.Structs.Material>(); if (adt.textures.filenames == null) { for (var ti = 0; ti < adt.diffuseTextureFileDataIDs.Count(); ti++) { var material = new Renderer.Structs.Material(); material.filename = adt.diffuseTextureFileDataIDs[ti].ToString(); material.textureID = (int)adt.diffuseTextureFileDataIDs[ti]; if (adt.texParams != null && adt.texParams.Count() >= ti) { material.scale = (float)Math.Pow(2, (adt.texParams[ti].flags & 0xF0) >> 4); if (adt.texParams[ti].height != 0.0 || adt.texParams[ti].offset != 1.0) { material.heightScale = adt.texParams[ti].height; material.heightOffset = adt.texParams[ti].offset; if (!WoWFormatLib.Utils.CASC.FileExists(adt.heightTextureFileDataIDs[ti])) { Console.WriteLine("Height texture: " + adt.heightTextureFileDataIDs[ti] + " does not exist! Falling back to original texture (hack).."); material.heightTexture = (int)adt.diffuseTextureFileDataIDs[ti]; } else { material.heightTexture = (int)adt.heightTextureFileDataIDs[ti]; } } else { material.heightScale = 0.0f; material.heightOffset = 1.0f; } } else { material.heightScale = 0.0f; material.heightOffset = 1.0f; material.scale = 1.0f; } rawMaterials.Add(material); } } else { for (var ti = 0; ti < adt.textures.filenames.Count(); ti++) { var material = new Renderer.Structs.Material(); material.filename = adt.textures.filenames[ti]; material.textureID = (int)WoWFormatLib.Utils.CASC.getFileDataIdByName(adt.textures.filenames[ti]); if (adt.texParams != null && adt.texParams.Count() >= ti) { material.scale = (float)Math.Pow(2, (adt.texParams[ti].flags & 0xF0) >> 4); if (adt.texParams[ti].height != 0.0 || adt.texParams[ti].offset != 1.0) { material.heightScale = adt.texParams[ti].height; material.heightOffset = adt.texParams[ti].offset; var heightName = adt.textures.filenames[ti].Replace(".blp", "_h.blp"); if (!WoWFormatLib.Utils.CASC.FileExists(heightName)) { Console.WriteLine("Height texture: " + heightName + " does not exist! Falling back to original texture (hack).."); material.heightTexture = (int)WoWFormatLib.Utils.CASC.getFileDataIdByName(adt.textures.filenames[ti]); } else { material.heightTexture = (int)WoWFormatLib.Utils.CASC.getFileDataIdByName(heightName); } } else { material.heightScale = 0.0f; material.heightOffset = 1.0f; } } else { material.heightScale = 0.0f; material.heightOffset = 1.0f; material.scale = 1.0f; } rawMaterials.Add(material); } } var layerMaterials = new List <uint>(); var alphalayermats = new List <int>(); var layerscales = new List <float>(); var layerheights = new List <int>(); //batch.heightScales = new Vector4(); //batch.heightOffsets = new Vector4(); exportworker.ReportProgress(10, "Exporting alpha layers " + file); var baseTextureName = Path.Combine(outdir, Path.GetDirectoryName(file), "terraindiffuse", Path.GetFileNameWithoutExtension(file).Replace(" ", "")); var baseAlphaTextureName = Path.Combine(outdir, Path.GetDirectoryName(file), "terrainalpha", Path.GetFileNameWithoutExtension(file).Replace(" ", "")); Directory.CreateDirectory(Path.GetDirectoryName(baseAlphaTextureName)); var pixels = new byte[4, 4096]; for (var li = 0; li < adt.texChunks[ci].layers.Count(); li++) { if (adt.texChunks[ci].alphaLayer != null) { var values = adt.texChunks[ci].alphaLayer[li].layer; for (var tx = 0; tx < 64; tx++) { for (var ty = 0; ty < 64; ty++) { pixels[li, tx * 64 + ty] = values[tx * 64 + ty]; } } } Renderer.Structs.Material curMat; if (adt.diffuseTextureFileDataIDs == null) { if (adt.textures.filenames == null) { throw new Exception("ADT has no textures?"); } var texFileDataID = WoWFormatLib.Utils.CASC.getFileDataIdByName(adt.textures.filenames[adt.texChunks[ci].layers[li].textureId]); //layerMaterials.Add((uint)BLPLoader.LoadTexture(texFileDataID)); curMat = rawMaterials.Where(material => material.filename == adt.textures.filenames[adt.texChunks[ci].layers[li].textureId]).Single(); } else { //layerMaterials.Add((uint)BLPLoader.LoadTexture(adt.diffuseTextureFileDataIDs[adt.texChunks[ci].layers[li].textureId])); curMat = rawMaterials.Where(material => material.filename == adt.diffuseTextureFileDataIDs[adt.texChunks[ci].layers[li].textureId].ToString()).Single(); //Console.WriteLine(ci + " " + li + " " + curMat.filename); } //layerscales.Add(curMat.scale); //layerheights.Add(curMat.heightTexture); //batch.heightScales[li] = curMat.heightScale; //batch.heightOffsets[li] = curMat.heightOffset; } //batch.materialID = layerMaterials.ToArray(); //batch.alphaMaterialID = alphalayermats.ToArray(); //batch.scales = layerscales.ToArray(); //batch.heightMaterialIDs = layerheights.ToArray(); using (var bmp = new System.Drawing.Bitmap(64, 64)) { for (var tx = 0; tx < 64; tx++) { for (var ty = 0; ty < 64; ty++) { var color = System.Drawing.Color.FromArgb(pixels[0, tx * 64 + ty], pixels[1, tx * 64 + ty], pixels[2, tx * 64 + ty], pixels[3, tx * 64 + ty]); bmp.SetPixel(ty, tx, color); } } bmp.Save(baseAlphaTextureName + "_" + ci + ".png", System.Drawing.Imaging.ImageFormat.Png); } } renderBatches.Add(batch); ci++; } } ConfigurationManager.RefreshSection("appSettings"); bool exportWMO = ConfigurationManager.AppSettings["exportWMO"] == "True"; bool exportM2 = ConfigurationManager.AppSettings["exportM2"] == "True"; bool exportFoliage = ConfigurationManager.AppSettings["exportFoliage"] == "True"; if (exportFoliage) { exportworker.ReportProgress(65, "Exporting ADT foliage"); try { var build = WoWFormatLib.Utils.CASC.BuildName; var dbcd = new DBCD.DBCD(new DBC.CASCDBCProvider(), new GithubDBDProvider()); var groundEffectTextureDB = dbcd.Load("GroundEffectTexture"); var groundEffectDoodadDB = dbcd.Load("GroundEffectDoodad"); for (var c = 0; c < reader.adtfile.texChunks.Length; c++) { for (var l = 0; l < reader.adtfile.texChunks[c].layers.Length; l++) { var effectID = reader.adtfile.texChunks[c].layers[l].effectId; if (effectID == 0) { continue; } if (!groundEffectTextureDB.ContainsKey(effectID)) { continue; } dynamic textureEntry = groundEffectTextureDB[effectID]; foreach (int doodad in textureEntry.DoodadID) { if (!groundEffectDoodadDB.ContainsKey(doodad)) { continue; } dynamic doodadEntry = groundEffectDoodadDB[doodad]; var filedataid = (uint)doodadEntry.ModelFileID; if (!Listfile.TryGetFilename(filedataid, out var filename)) { Logger.WriteLine("Could not find filename for " + filedataid + ", setting filename to filedataid.."); filename = filedataid.ToString(); } if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), "foliage"))) { Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file), "foliage")); } if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), "foliage", Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj"))) { M2Exporter.ExportM2(filedataid, null, Path.Combine(outdir, Path.GetDirectoryName(file), "foliage"), filename); } } } } } catch (Exception e) { Logger.WriteLine("Error exporting GroundEffects: " + e.Message); } } if (exportWMO || exportM2) { var doodadSW = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + "_ModelPlacementInformation.csv")); doodadSW.WriteLine("ModelFile;PositionX;PositionY;PositionZ;RotationX;RotationY;RotationZ;ScaleFactor;ModelId;Type"); if (exportWMO) { exportworker.ReportProgress(25, "Exporting ADT worldmodels"); for (var mi = 0; mi < reader.adtfile.objects.worldModels.entries.Count(); mi++) { var wmo = reader.adtfile.objects.worldModels.entries[mi]; var filename = ""; uint filedataid = 0; if (reader.adtfile.objects.wmoNames.filenames == null) { filedataid = wmo.mwidEntry; if (!Listfile.TryGetFilename(filedataid, out filename)) { Logger.WriteLine("Warning! Could not find filename for " + filedataid + ", setting filename to filedataid.."); filename = filedataid.ToString() + ".wmo"; } } else { Logger.WriteLine("Warning!! File " + filename + " ID: " + filedataid + " still has filenames!"); filename = reader.adtfile.objects.wmoNames.filenames[wmo.mwidEntry]; if (!Listfile.TryGetFileDataID(filename, out filedataid)) { Logger.WriteLine("Error! Could not find filedataid for " + filename + "!"); continue; } } short doodadSet = -1; if (ConfigurationManager.AppSettings["exportWMODoodads"] == "True") { doodadSet = (short)wmo.doodadSet; } if (string.IsNullOrEmpty(filename)) { string wmoFile = Path.Combine(outdir, Path.GetDirectoryName(file), filedataid.ToString() + ".obj"); if (!File.Exists(wmoFile)) { WMOExporter.ExportWMO(filedataid, exportworker, Path.Combine(outdir, Path.GetDirectoryName(file)), doodadSet); } if (File.Exists(wmoFile)) { doodadSW.WriteLine(filedataid + ".obj;" + wmo.position.X + ";" + wmo.position.Y + ";" + wmo.position.Z + ";" + wmo.rotation.X + ";" + wmo.rotation.Y + ";" + wmo.rotation.Z + ";" + wmo.scale / 1024f + ";" + wmo.uniqueId + ";wmo"); } } else { string wmoFile = Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj"); if (!File.Exists(wmoFile)) { WMOExporter.ExportWMO(filedataid, exportworker, Path.Combine(outdir, Path.GetDirectoryName(file)), doodadSet, filename); } if (File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj"))) { doodadSW.WriteLine(Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj;" + wmo.position.X + ";" + wmo.position.Y + ";" + wmo.position.Z + ";" + wmo.rotation.X + ";" + wmo.rotation.Y + ";" + wmo.rotation.Z + ";" + wmo.scale / 1024f + ";" + wmo.uniqueId + ";wmo"); } } } } if (exportM2) { exportworker.ReportProgress(50, "Exporting ADT doodads"); for (var mi = 0; mi < reader.adtfile.objects.models.entries.Count(); mi++) { var doodad = reader.adtfile.objects.models.entries[mi]; string filename; uint filedataid; if (reader.adtfile.objects.m2Names.filenames == null) { filedataid = doodad.mmidEntry; if (!Listfile.TryGetFilename(filedataid, out filename)) { Logger.WriteLine("Could not find filename for " + filedataid + ", setting filename to filedataid.."); filename = filedataid.ToString(); } } else { filename = reader.adtfile.objects.m2Names.filenames[doodad.mmidEntry].ToLower(); if (!Listfile.TryGetFileDataID(filename, out filedataid)) { Logger.WriteLine("Error! Could not find filedataid for " + filename + "!"); continue; } } if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(filename) + ".obj"))) { M2Exporter.ExportM2(filedataid, null, Path.Combine(outdir, Path.GetDirectoryName(file)), filename); } if (File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(filename) + ".obj"))) { doodadSW.WriteLine(Path.GetFileNameWithoutExtension(filename) + ".obj;" + doodad.position.X + ";" + doodad.position.Y + ";" + doodad.position.Z + ";" + doodad.rotation.X + ";" + doodad.rotation.Y + ";" + doodad.rotation.Z + ";" + doodad.scale / 1024f + ";" + doodad.uniqueId + ";m2"); } } } doodadSW.Close(); } exportworker.ReportProgress(75, "Exporting terrain textures.."); if (bakeQuality != "none") { var mtlsw = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl")); //No idea how MTL files really work yet. Needs more investigation. foreach (var material in materials) { mtlsw.WriteLine("newmtl " + material.Value.Replace(" ", "")); mtlsw.WriteLine("Ka 1.000000 1.000000 1.000000"); mtlsw.WriteLine("Kd 0.640000 0.640000 0.640000"); mtlsw.WriteLine("map_Ka " + material.Value.Replace(" ", "") + ".png"); mtlsw.WriteLine("map_Kd " + material.Value.Replace(" ", "") + ".png"); } mtlsw.Close(); } exportworker.ReportProgress(85, "Exporting terrain geometry.."); var indices = indicelist.ToArray(); var adtname = Path.GetFileNameWithoutExtension(file); var objsw = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".obj")); objsw.WriteLine("# Written by Marlamin's WoW OBJExporter. Original file: " + file); if (bakeQuality != "none") { objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl"); } var verticeCounter = 1; var chunkCounter = 1; foreach (var vertex in verticelist) { //objsw.WriteLine("# C" + chunkCounter + ".V" + verticeCounter); objsw.WriteLine("v " + vertex.Position.X.ToString("R") + " " + vertex.Position.Y.ToString("R") + " " + vertex.Position.Z.ToString("R")); objsw.WriteLine("vt " + vertex.TexCoord.X + " " + vertex.TexCoord.Y); objsw.WriteLine("vn " + vertex.Normal.X.ToString("R") + " " + vertex.Normal.Y.ToString("R") + " " + vertex.Normal.Z.ToString("R")); verticeCounter++; if (verticeCounter == 146) { chunkCounter++; verticeCounter = 1; } } if (bakeQuality == "minimap" || bakeQuality == "low" || bakeQuality == "medium") { objsw.WriteLine("g " + adtname.Replace(" ", "")); objsw.WriteLine("usemtl " + materials[1]); objsw.WriteLine("s 1"); } for (int rbi = 0; rbi < renderBatches.Count(); rbi++) { var renderBatch = renderBatches[rbi]; var i = renderBatch.firstFace; if (bakeQuality == "high" || bakeQuality == "none") { objsw.WriteLine("g " + adtname.Replace(" ", "") + "_" + rbi); } if (bakeQuality == "high" && materials.ContainsKey((int)renderBatch.materialID)) { objsw.WriteLine("usemtl " + materials[(int)renderBatch.materialID]); } while (i < (renderBatch.firstFace + renderBatch.numFaces)) { objsw.WriteLine("f " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1)); i = i + 3; } } objsw.Close(); Logger.WriteLine("ADT OBJ Exporter: Finished with export of {0}..", file); }
static void Main(string[] args) { if (args.Length < 4) { throw new ArgumentException("Required arguments: cdndir, buildconfig, cdnconfig, outdir"); } var cdndir = args[0]; var bc = args[1]; var cdnc = args[2]; var outdir = args[3]; var mapFilter = ""; if (args.Length == 5) { mapFilter = args[4]; } // Open storage for specific build TACTRepo tactRepo = new TACTRepo(cdndir) { ConfigContainer = new ConfigContainer() }; Console.WriteLine("Loading configs.."); tactRepo.ConfigContainer.OpenLocal(tactRepo.BaseDirectory, bc, cdnc); Console.WriteLine("Loading indices.."); tactRepo.IndexContainer = new TACT.Net.Indices.IndexContainer(); tactRepo.IndexContainer.Open(tactRepo.BaseDirectory, tactRepo.ConfigContainer); Console.WriteLine("Loading encoding.."); tactRepo.EncodingFile = new TACT.Net.Encoding.EncodingFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.EncodingEKey); Console.WriteLine("Looking up root.."); tactRepo.EncodingFile.TryGetCKeyEntry(tactRepo.ConfigContainer.RootCKey, out var rootCEntry); Console.WriteLine("Loading root.."); tactRepo.RootFile = new TACT.Net.Root.RootFile(tactRepo.BaseDirectory, rootCEntry.EKey); Console.WriteLine("Loading TACT keys.."); try { using (var client = new HttpClient()) { var result = client.GetAsync("https://wow.tools/api.php?type=tactkeys").Result; var keys = result.Content.ReadAsStringAsync().Result.Split('\n'); foreach (var key in keys) { var split = key.Split(' '); if (split.Length < 2) { continue; } var keyname = Convert.ToUInt64(split[0], 16); var keybytes = split[1]; if (TACT.Net.Cryptography.KeyService.TryAddKey(keyname, keybytes)) { Console.WriteLine("Added TACT key " + split[0]); } } } } catch (Exception e) { Console.WriteLine("An error occurred retrieving/loading TACT keys: " + e.Message); } // Set up DBCD var dbdProvider = new GithubDBDProvider(); var dbcProvider = new TACTDBCProvider(tactRepo); var dbcd = new DBCD.DBCD(dbcProvider, dbdProvider); // Open Map DBC with local defs Console.WriteLine("Opening Map.db2.."); // This will currently crash on partially encrypted DBs with unknown keys due to https://github.com/wowdev/TACT.Net/issues/12 var mapdb = dbcd.Load("Map"); // Run through map db Console.WriteLine("Extracting tiles.."); foreach (dynamic map in mapdb.Values) { if (!string.IsNullOrEmpty(mapFilter) && map.Directory != mapFilter) { continue; } Console.WriteLine(map.Directory); // Load WDT Stream wdtStream; try { if (map.WdtFileDataID == 0) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Skipping map " + map.Directory + " with no WDT!"); Console.ResetColor(); continue; } wdtStream = tactRepo.RootFile.OpenFile((uint)map.WdtFileDataID, tactRepo); } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException e) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Older build detected: map record has no wdtFileDataID property"); Console.ResetColor(); wdtStream = tactRepo.RootFile.OpenFile("world/maps/" + map.Directory + "/" + map.Directory + ".wdt", tactRepo); } if (wdtStream == null) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Skipping map " + map.Directory + " with unshipped WDT!"); Console.ResetColor(); continue; } var minimapFDIDs = WDT.FileDataIdsFromWDT(wdtStream); if (minimapFDIDs.Count() == 0) { // Pre-MAID build, extract by filename for (var x = 0; x < 64; x++) { for (var y = 0; y < 64; y++) { string tileName = "world/minimaps/" + map.Directory + "/map" + x.ToString().PadLeft(2, '0') + "_" + y.ToString().PadLeft(2, '0') + ".blp"; var minimapStream = tactRepo.RootFile.OpenFile(tileName, tactRepo); if (minimapStream == null) { continue; } var minimapName = "map" + x.ToString().PadLeft(2, '0') + "_" + y.ToString().PadLeft(2, '0') + ".blp"; var minimapPath = Path.Combine(outdir, "world", "minimaps", map.Directory, minimapName); Directory.CreateDirectory(Path.GetDirectoryName(minimapPath)); using (var fileStream = File.Create(minimapPath)) { minimapStream.CopyTo(fileStream); } } } } else { // Extract tiles by FDID minimapFDIDs = minimapFDIDs.Where(chunk => chunk.fileDataId != 0).ToArray(); foreach (var minimap in minimapFDIDs) { var minimapStream = tactRepo.RootFile.OpenFile(minimap.fileDataId, tactRepo); if (minimapStream == null) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Unable to extract minimap " + minimap.fileDataId + " for tile " + minimap.x + "_" + minimap.y); Console.ResetColor(); continue; } var minimapName = "map" + minimap.x.ToString().PadLeft(2, '0') + "_" + minimap.y.ToString().PadLeft(2, '0') + ".blp"; var minimapPath = Path.Combine(outdir, "world", "minimaps", map.Directory, minimapName); Directory.CreateDirectory(Path.GetDirectoryName(minimapPath)); using (var fileStream = File.Create(minimapPath)) { minimapStream.CopyTo(fileStream); } } } } // Append any filenames from listfile for additional non-WDT referenced minimaps? }
public static void exportADT(string file, string outdir, string bakeQuality, BackgroundWorker exportworker = null) { if (exportworker == null) { exportworker = new BackgroundWorker { WorkerReportsProgress = true }; } var customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone(); customCulture.NumberFormat.NumberDecimalSeparator = "."; System.Threading.Thread.CurrentThread.CurrentCulture = customCulture; var MaxSize = 51200 / 3.0; var TileSize = MaxSize / 32.0; var ChunkSize = TileSize / 16.0; var UnitSize = ChunkSize / 8.0; var UnitSizeHalf = UnitSize / 2.0; string mapname = file; mapname = mapname.Substring(mapname.LastIndexOf("\\", mapname.Length - 2) + 1); mapname = mapname.Substring(0, mapname.Length - 4); var reader = new ADTReader(); var ADTfile = file; exportworker.ReportProgress(0, "Loading ADT " + file); if (Managers.ConfigurationManager.Profile <= 3) //WoTLK and below { reader.Load335ADT(ADTfile); } else { reader.LoadADT(ADTfile); } if (reader.adtfile.chunks == null) { throw new Exception("ADT OBJ Exporter: File has no chunks, skipping export!"); } if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file)))) { Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file))); } var renderBatches = new List <Structs.RenderBatch>(); var verticelist = new List <Structs.Vertex>(); var indicelist = new List <int>(); var materials = new Dictionary <int, string>(); // Calculate ADT offset in world coordinates var adtStartX = reader.adtfile.chunks[0].header.position.X; var adtStartY = reader.adtfile.chunks[0].header.position.Y; // Calculate first chunk offset in world coordinates var initialChunkX = adtStartX + (reader.adtfile.chunks[0].header.indexX * ChunkSize) * -1; var initialChunkY = adtStartY + (reader.adtfile.chunks[0].header.indexY * ChunkSize) * -1; uint ci = 0; for (var x = 0; x < 16; x++) { for (var y = 0; y < 16; y++) { var genx = (initialChunkX + (ChunkSize * x) * -1); var geny = (initialChunkY + (ChunkSize * y) * -1); var chunk = reader.adtfile.chunks[ci]; var off = verticelist.Count(); var batch = new Structs.RenderBatch(); for (int row = 0, idx = 0; row < 17; row++) { bool isSmallRow = (row % 2) != 0; int rowLength = isSmallRow ? 8 : 9; for (var col = 0; col < rowLength; col++) { var v = new Structs.Vertex(); v.Normal = new Structs.Vector3D { X = (double)chunk.normals.normal_0[idx] / 127, Y = (double)chunk.normals.normal_2[idx] / 127, Z = (double)chunk.normals.normal_1[idx] / 127 }; var px = geny - (col * UnitSize); var py = chunk.vertices.vertices[idx++] + chunk.header.position.Z; var pz = genx - (row * UnitSizeHalf); v.Position = new Structs.Vector3D { X = px, Y = py, Z = pz }; if ((row % 2) != 0) { v.Position.X = (px - UnitSizeHalf); } double ofs = col; if (isSmallRow) { ofs += 0.5; } if (bakeQuality == "high") { double tx = ofs / 8d; double ty = 1 - (row / 16d); v.TexCoord = new Structs.Vector2D { X = tx, Y = ty }; } else { double tx = -(v.Position.X - initialChunkY) / TileSize; double ty = (v.Position.Z - initialChunkX) / TileSize; v.TexCoord = new Structs.Vector2D { X = tx, Y = ty }; } verticelist.Add(v); } } batch.firstFace = (uint)indicelist.Count(); // Stupid C# and its structs var holesHighRes = new byte[8]; holesHighRes[0] = chunk.header.holesHighRes_0; holesHighRes[1] = chunk.header.holesHighRes_1; holesHighRes[2] = chunk.header.holesHighRes_2; holesHighRes[3] = chunk.header.holesHighRes_3; holesHighRes[4] = chunk.header.holesHighRes_4; holesHighRes[5] = chunk.header.holesHighRes_5; holesHighRes[6] = chunk.header.holesHighRes_6; holesHighRes[7] = chunk.header.holesHighRes_7; for (int j = 9, xx = 0, yy = 0; j < 145; j++, xx++) { if (xx >= 8) { xx = 0; ++yy; } var isHole = true; // Check if chunk is using low-res holes if ((chunk.header.flags & 0x10000) == 0) { // Calculate current hole number var currentHole = (int)Math.Pow(2, Math.Floor(xx / 2f) * 1f + Math.Floor(yy / 2f) * 4f); // Check if current hole number should be a hole if ((chunk.header.holesLowRes & currentHole) == 0) { isHole = false; } } //Sloppy ignore holes: if (Managers.ConfigurationManager.ADTIgnoreHoles) { isHole = false; } else { // Check if current section is a hole if (((holesHighRes[yy] >> xx) & 1) == 0) { isHole = false; } } if (!isHole) { indicelist.AddRange(new int[] { off + j + 8, off + j - 9, off + j }); indicelist.AddRange(new int[] { off + j - 9, off + j - 8, off + j }); indicelist.AddRange(new int[] { off + j - 8, off + j + 9, off + j }); indicelist.AddRange(new int[] { off + j + 9, off + j + 8, off + j }); // Generates quads instead of 4x triangles //indicelist.AddRange(new int[] { off + j + 8, off + j - 9, off + j - 8 }); //indicelist.AddRange(new int[] { off + j - 8, off + j + 9, off + j + 8 }); } if ((j + 1) % (9 + 8) == 0) { j += 9; } } if (bakeQuality == "high") { materials.Add((int)ci + 1, Path.GetFileNameWithoutExtension(file) + "_" + ci); batch.materialID = ci + 1; } else { if (!materials.ContainsKey(1)) { materials.Add(1, Path.GetFileNameWithoutExtension(file)); } batch.materialID = (uint)materials.Count(); } batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace; renderBatches.Add(batch); ci++; } } bool exportWMO = Managers.ConfigurationManager.ADTExportWMO; bool exportM2 = Managers.ConfigurationManager.ADTExportM2; bool exportTextures = Managers.ConfigurationManager.ADTexportTextures; bool exportAlphaMaps = Managers.ConfigurationManager.ADTexportAlphaMaps; bool exportHeightmap = Managers.ConfigurationManager.ADTExportHeightmap; bool exportFoliage = Managers.ConfigurationManager.ADTExportFoliage; //FOLIAGE if (exportFoliage && Managers.ArchiveManager.usingCasc) //ONLY EXPROT IF CASC; PRE CASC NEEDS TO BE IMPLEMEMNTED { exportworker.ReportProgress(65, "Exporting foliage"); try { var build = Managers.ArchiveManager.cascHandler.Config.VersionName; //TODO: IMPLEMENT PRE CASC BUILDS var dbcd = new DBCD.DBCD(new WoWExport.DBC.ArchiveDBCProvider(), new WoWExport.DBC.LocalDBCDProvider()); var groundEffectTextureDB = dbcd.Load("GroundEffectTexture", build); var groundEffectDoodadDB = dbcd.Load("GroundEffectDoodad", build); for (var c = 0; c < reader.adtfile.texChunks.Length; c++) { for (var l = 0; l < reader.adtfile.texChunks[c].layers.Length; l++) { var effectID = reader.adtfile.texChunks[c].layers[l].effectId; if (effectID == 0) { continue; } if (!groundEffectTextureDB.ContainsKey(effectID)) { continue; } dynamic textureEntry = groundEffectTextureDB[effectID]; foreach (int doodad in textureEntry.DoodadID) { if (!groundEffectDoodadDB.ContainsKey(doodad)) { continue; } dynamic doodadEntry = groundEffectDoodadDB[doodad]; var filedataid = (uint)doodadEntry.ModelFileID; if (!WoWExport.Listfile.TryGetFilename(filedataid, out var filename)) { Console.WriteLine("Could not find filename for " + filedataid + ", setting filename to filedataid.."); filename = filedataid.ToString(); } if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), "foliage"))) { Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file), "foliage")); } if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), "foliage", Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj"))) { M2Exporter.ExportM2(filename, Path.Combine(outdir, Path.GetDirectoryName(file), "foliage")); } } } } } catch (Exception e) { Console.WriteLine("Error exporting GroundEffects: " + e.Message); } } if (exportWMO || exportM2) { var doodadSW = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + "_ModelPlacementInformation.csv")); doodadSW.WriteLine("ModelFile;PositionX;PositionY;PositionZ;RotationX;RotationY;RotationZ;ScaleFactor;ModelId;Type"); if (exportWMO) { exportworker.ReportProgress(25, "Exporting WMOs"); for (var mi = 0; mi < reader.adtfile.objects.worldModels.entries.Count(); mi++) { var wmo = reader.adtfile.objects.worldModels.entries[mi]; float wmoScale; if (wmo.scale != 0) { wmoScale = wmo.scale / 1024f; } else { wmoScale = 1; } var filename = reader.adtfile.objects.wmoNames.filenames[wmo.mwidEntry]; if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj"))) { WMOExporter.ExportWMO(filename, Path.Combine(outdir, Path.GetDirectoryName(file)), exportworker, null, wmo.doodadSet); } if (Managers.ConfigurationManager.ADTModelsPlacementGlobalPath) { doodadSW.WriteLine(Path.Combine(Path.GetDirectoryName(filename).ToLower(), Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj") + ";" + wmo.position.X + ";" + wmo.position.Y + ";" + wmo.position.Z + ";" + wmo.rotation.X + ";" + wmo.rotation.Y + ";" + wmo.rotation.Z + ";" + wmoScale + ";" + wmo.uniqueId + ";wmo"); } else { doodadSW.WriteLine(Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj;" + wmo.position.X + ";" + wmo.position.Y + ";" + wmo.position.Z + ";" + wmo.rotation.X + ";" + wmo.rotation.Y + ";" + wmo.rotation.Z + ";" + wmoScale + ";" + wmo.uniqueId + ";wmo"); } } } if (exportM2) { exportworker.ReportProgress(50, "Exporting M2s"); for (var mi = 0; mi < reader.adtfile.objects.models.entries.Count(); mi++) { var doodad = reader.adtfile.objects.models.entries[mi]; string filename; filename = reader.adtfile.objects.m2Names.filenames[doodad.mmidEntry]; if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj"))) { M2Exporter.ExportM2(filename, Path.Combine(outdir, Path.GetDirectoryName(file)), exportworker); } if (Managers.ConfigurationManager.ADTModelsPlacementGlobalPath) { doodadSW.WriteLine(Path.Combine(Path.GetDirectoryName(filename).ToLower(), Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj") + ";" + doodad.position.X + ";" + doodad.position.Y + ";" + doodad.position.Z + ";" + doodad.rotation.X + ";" + doodad.rotation.Y + ";" + doodad.rotation.Z + ";" + doodad.scale / 1024f + ";" + doodad.uniqueId + ";m2"); } else { doodadSW.WriteLine(Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj;" + doodad.position.X + ";" + doodad.position.Y + ";" + doodad.position.Z + ";" + doodad.rotation.X + ";" + doodad.rotation.Y + ";" + doodad.rotation.Z + ";" + doodad.scale / 1024f + ";" + doodad.uniqueId + ";m2"); } } } doodadSW.Close(); } #region Alpha&Tex //---------------------------------------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////////////////////////////////// ///TEXTURE & ALPHA & HEIGHTMAP RELATED START //////////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------- if (exportTextures) //Export ground textures { { if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures"))) { Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures")); } } List <String> GroundTextures = reader.adtfile.textures.filenames.ToList(); var blpreader = new BLPReader(); foreach (string texture in GroundTextures) { if (Managers.ConfigurationManager.ADTPreserveTextureStruct) { if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture) + Path.GetFileNameWithoutExtension(texture) + ".png"))) { if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture)))) { Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture))); } if (Managers.ArchiveManager.FileExists(texture)) { try { blpreader.LoadBLP(Managers.ArchiveManager.ReadThisFile(texture)); blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + ".png")); if (Managers.ConfigurationManager.ADTExportSpecularTextures) { if (Managers.ArchiveManager.FileExists(Path.Combine(Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.blp"))) { if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.png"))) { blpreader.LoadBLP(Managers.ArchiveManager.ReadThisFile(Path.Combine(Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.blp"))); blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.png")); } } } } catch (Exception e) { //Error on file save throw new Exception(e.Message); } } else { //Missing file } } } else { if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures\\", Path.GetFileNameWithoutExtension(texture) + ".png"))) { if (Managers.ArchiveManager.FileExists(texture)) { try { blpreader.LoadBLP(Managers.ArchiveManager.ReadThisFile(texture)); blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures\\", Path.GetFileNameWithoutExtension(texture) + ".png")); if (Managers.ConfigurationManager.ADTExportSpecularTextures) { if (Managers.ArchiveManager.FileExists(Path.Combine(Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.blp"))) { if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures\\", Path.GetFileNameWithoutExtension(texture) + "_s.png"))) { blpreader.LoadBLP(Managers.ArchiveManager.ReadThisFile(Path.Combine(Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.blp"))); blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures\\", Path.GetFileNameWithoutExtension(texture) + "_s.png")); } } } } catch (Exception e) { //Error on file save throw new Exception(e.Message); } } else { //Missing file } } } } } if (exportAlphaMaps) { Generators.ADT_Alpha.ADT_Alpha AlphaMapsGenerator = new Generators.ADT_Alpha.ADT_Alpha(); AlphaMapsGenerator.GenerateAlphaMaps(reader.adtfile, Managers.ConfigurationManager.ADTAlphaMode); List <System.Drawing.Bitmap> AlphaLayers = new List <System.Drawing.Bitmap>(); AlphaLayers = AlphaMapsGenerator.AlphaLayers; if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps"))) { Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps")); } if (AlphaLayers != null) { if (Managers.ConfigurationManager.ADTAlphaMode == 0 || Managers.ConfigurationManager.ADTAlphaMode == 1) { for (int m = 0; m < AlphaLayers.ToArray().Length; m++) { if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_" + m + ".png"))) { try { AlphaLayers[m].Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_" + m + ".png")); } catch { //Error on file save } } } } if (Managers.ConfigurationManager.ADTAlphaMode == 2 || Managers.ConfigurationManager.ADTAlphaMode == 3) { List <String> AlphaLayersNames = new List <String>(AlphaMapsGenerator.AlphaLayersNames); for (int m = 0; m < AlphaLayers.ToArray().Length; m++) { if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_" + AlphaLayersNames[m].Replace(";", "_") + ".png"))) { try { AlphaLayers[m].Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_" + AlphaLayersNames[m].Replace(";", "_") + ".png")); } catch { //Error on file save } } } } if (Managers.ConfigurationManager.ADTAlphaMode == 4) //Splatmaps { //Save the splatmaps for (int m = 0; m < AlphaLayers.ToArray().Length; m++) { if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_splatmap_" + m + ".png"))) { try { AlphaLayers[m].Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_splatmap_" + m + ".png")); } catch { //Error on file save } } } //Save the material info JSON if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_MaterialData.json"))) { try { File.WriteAllText(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_MaterialData.json"), AlphaMapsGenerator.SplatmapJSON); } catch { //Error on file save } } } } //Check if the CSV already exists, if not, create it if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\" + mapname + "_" + "layers.csv"))) { //Generate layer information CSV StreamWriter layerCsvSR = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\" + mapname + "_" + "layers.csv")); //Insert CSV scheme layerCsvSR.WriteLine("chunk;tex0;tex1;tex2;tex3"); for (uint c = 0; c < reader.adtfile.chunks.Count(); c++) { string csvLine = c.ToString(); for (int li = 0; li < reader.adtfile.texChunks[c].layers.Count(); li++) { var AlphaLayerName = reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[li].textureId].ToLower(); if (Managers.ConfigurationManager.ADTPreserveTextureStruct) { csvLine = csvLine + ";" + Path.Combine(Path.GetDirectoryName(AlphaLayerName), Path.GetFileNameWithoutExtension(AlphaLayerName)); } else { csvLine = csvLine + ";" + Path.GetFileNameWithoutExtension(AlphaLayerName); } } layerCsvSR.WriteLine(csvLine); } layerCsvSR.Close(); } } if (exportHeightmap) { Generators.ADT_Height.ADT_Height heightmapGenerator = new Generators.ADT_Height.ADT_Height(); heightmapGenerator.GenerateHeightmap(reader.adtfile); if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\HeightMaps"))) { Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\HeightMaps")); } try { File.WriteAllText(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\HeightMaps\\", mapname + "_HeightData.json"), Newtonsoft.Json.JsonConvert.SerializeObject(heightmapGenerator.heightArray2d)); heightmapGenerator.heightMap.Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\HeightMaps\\", mapname + "_heightmap.png")); } catch { //Error on save } } //---------------------------------------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////////////////////////////////// ///TEXTURE & ALPHA & HEIGHTMAP RELATED END //////////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------- #endregion //VERTEX COLORS -- not implemented /* * //Vertex color data * if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\" + mapname + "_" + "vertex_colors.csv"))) * { * StreamWriter vertesColorCSV = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\" + mapname + "_" + "vertex_colors.csv")); * vertesColorCSV.WriteLine("chunk;vert;a;r;g;b"); //header * for (uint c = 0; c < reader.adtfile.chunks.Count(); c++) * { * if (reader.adtfile.chunks[c].vertexShading.red != null) * { * for (int i = 0; i < 145; i++) * { * //Console.WriteLine(c + "_" + i + "-" + reader.adtfile.chunks[c].vertexShading.alpha[i] + " " + reader.adtfile.chunks[c].vertexShading.red[i] + " " + reader.adtfile.chunks[c].vertexShading.green[i] + " " + reader.adtfile.chunks[c].vertexShading.blue[i]); * vertesColorCSV.WriteLine(c + ";" + i + ";" + reader.adtfile.chunks[c].vertexShading.alpha[i] + ";" + reader.adtfile.chunks[c].vertexShading.red[i] + ";" + reader.adtfile.chunks[c].vertexShading.green[i] + ";" + reader.adtfile.chunks[c].vertexShading.blue[i]); * } * } * else * { * //Console.WriteLine(c + "- null"); * vertesColorCSV.WriteLine(c + ";0;0;0;0;0"); * } * } * vertesColorCSV.Close(); * } */ exportworker.ReportProgress(75, "Exporting terrain textures.."); if (bakeQuality != "none") { var mtlsw = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl")); //No idea how MTL files really work yet. Needs more investigation. foreach (var material in materials) { mtlsw.WriteLine("newmtl " + material.Value.Replace(" ", "")); mtlsw.WriteLine("Ka 1.000000 1.000000 1.000000"); mtlsw.WriteLine("Kd 0.640000 0.640000 0.640000"); mtlsw.WriteLine("map_Ka " + material.Value.Replace(" ", "") + ".png"); mtlsw.WriteLine("map_Kd " + material.Value.Replace(" ", "") + ".png"); } mtlsw.Close(); } exportworker.ReportProgress(85, "Exporting terrain geometry.."); var indices = indicelist.ToArray(); var adtname = Path.GetFileNameWithoutExtension(file); var objsw = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".obj")); objsw.WriteLine("# Written by Marlamin's WoW OBJExporter. Original file: " + file); if (bakeQuality != "none") { objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl"); } objsw.WriteLine("g " + adtname.Replace(" ", "")); var verticeCounter = 1; var chunkCounter = 1; foreach (var vertex in verticelist) { objsw.WriteLine("# C" + chunkCounter + ".V" + verticeCounter); objsw.WriteLine("v " + vertex.Position.X.ToString("R") + " " + vertex.Position.Y.ToString("R") + " " + vertex.Position.Z.ToString("R")); objsw.WriteLine("vt " + vertex.TexCoord.X + " " + vertex.TexCoord.Y); objsw.WriteLine("vn " + vertex.Normal.X.ToString("R") + " " + vertex.Normal.Y.ToString("R") + " " + vertex.Normal.Z.ToString("R")); verticeCounter++; if (verticeCounter == 146) { chunkCounter++; verticeCounter = 1; } } if (bakeQuality != "high") { objsw.WriteLine("usemtl " + materials[1]); objsw.WriteLine("s 1"); } int currentChunk = 0; foreach (var renderBatch in renderBatches) { var i = renderBatch.firstFace; if (bakeQuality == "high" && materials.ContainsKey((int)renderBatch.materialID)) { if (Managers.ConfigurationManager.ADTSplitChunks) { objsw.WriteLine("g " + materials[(int)renderBatch.materialID]); objsw.WriteLine("usemtl " + materials[(int)renderBatch.materialID]); objsw.WriteLine("s 1"); } else { objsw.WriteLine("usemtl " + materials[(int)renderBatch.materialID]); } } while (i < (renderBatch.firstFace + renderBatch.numFaces)) { objsw.WriteLine("f " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1)); i += 3; } currentChunk++; } objsw.Close(); }
private static void Main(string[] args) { var config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("settings.json", true, true).Build(); var saveExplored = bool.Parse(config["saveExploredMaps"]); var saveUnexplored = bool.Parse(config["saveUnexploredMaps"]); var saveLayers = bool.Parse(config["saveMapLayers"]); var saveExploredMapsWithoutUnexplored = bool.Parse(config["saveExploredMapsWithoutUnexplored"]); if (saveExplored && !Directory.Exists("explored")) { Directory.CreateDirectory("explored"); } if (saveUnexplored && !Directory.Exists("unexplored")) { Directory.CreateDirectory("unexplored"); } if (saveLayers && !Directory.Exists("layers")) { Directory.CreateDirectory("layers"); } if (saveExploredMapsWithoutUnexplored && !Directory.Exists("exploredNoUnexplored")) { Directory.CreateDirectory("exploredNoUnexplored"); } var locale = CASCLib.LocaleFlags.enUS; if (config["locale"] != string.Empty) { switch (config["locale"]) { case "deDE": locale = CASCLib.LocaleFlags.deDE; break; case "enUS": locale = CASCLib.LocaleFlags.enUS; break; case "ruRU": locale = CASCLib.LocaleFlags.ruRU; break; case "zhCN": locale = CASCLib.LocaleFlags.zhCN; break; case "zhTW": locale = CASCLib.LocaleFlags.zhTW; break; } } if (config["installDir"] != string.Empty && Directory.Exists(config["installDir"])) { CASC.InitCasc(null, config["installDir"], config["program"], locale); } else { CASC.InitCasc(null, null, config["program"], locale); } var dbcd = new DBCD.DBCD(new CASCDBCProvider(), new DBCD.Providers.GithubDBDProvider()); var UIMap = dbcd.Load("UiMap", CASC.BuildName); var UIMapXArt = dbcd.Load("UiMapXMapArt", CASC.BuildName); var UIMapArtTile = dbcd.Load("UiMapArtTile", CASC.BuildName); var UIMapArt = dbcd.Load("UiMapArt", CASC.BuildName); var UIMapArtStyleLayer = dbcd.Load("UiMapArtStyleLayer", CASC.BuildName); var WorldMapOverlay = dbcd.Load("WorldMapOverlay", CASC.BuildName); var WorldMapOverlayTile = dbcd.Load("WorldMapOverlayTile", CASC.BuildName); Console.WriteLine(); // new line after wdc2 debug output foreach (dynamic mapRow in UIMap.Values) { var mapName = mapRow.Name_lang; Console.WriteLine(mapRow.ID + " = " + mapName); foreach (dynamic mxaRow in UIMapXArt.Values) { var uiMapArtID = mxaRow.UiMapArtID; var uiMapID = mxaRow.UiMapID; if (mxaRow.PhaseID != 0) { continue; // Skip phase stuff for now } if (uiMapID == mapRow.ID) { var maxRows = uint.MinValue; var maxCols = uint.MinValue; var tileDict = new Dictionary <string, int>(); foreach (dynamic matRow in UIMapArtTile.Values) { var matUiMapArtID = matRow.UiMapArtID; if (matUiMapArtID == uiMapArtID) { var fdid = matRow.FileDataID; var rowIndex = matRow.RowIndex; var colIndex = matRow.ColIndex; var layerIndex = matRow.LayerIndex; // Skip other layers for now if (layerIndex != 0) { continue; } if (rowIndex > maxRows) { maxRows = rowIndex; } if (colIndex > maxCols) { maxCols = colIndex; } tileDict.Add(rowIndex + "," + colIndex, fdid); } } uint res_x = 0; uint res_y = 0; foreach (dynamic maRow in UIMapArt.Values) { if (maRow.ID == uiMapArtID) { foreach (dynamic mastRow in UIMapArtStyleLayer.Values) { if (mastRow.ID == maRow.UiMapArtStyleID) { res_x = mastRow.LayerHeight; res_y = mastRow.LayerWidth; continue; } } continue; } } if (res_x == 0) { res_x = (maxRows + 1) * 256; } if (res_y == 0) { res_y = (maxCols + 1) * 256; } var bmp = new Bitmap((int)res_y, (int)res_x); var g = Graphics.FromImage(bmp); var bmp2 = new Bitmap((int)res_y, (int)res_x); var g2 = Graphics.FromImage(bmp2); for (var cur_x = 0; cur_x < maxRows + 1; cur_x++) { for (var cur_y = 0; cur_y < maxCols + 1; cur_y++) { var fdid = tileDict[cur_x + "," + cur_y]; if (CASC.FileExists((uint)fdid)) { using (var stream = CASC.OpenFile((uint)fdid)) { try { var blp = new BlpFile(stream); g.DrawImage(blp.GetBitmap(0), cur_y * 256, cur_x * 256, new Rectangle(0, 0, 256, 256), GraphicsUnit.Pixel); } catch (Exception e) { Console.WriteLine("An error occured opening BLP with filedataid " + fdid); } } } } } if (saveUnexplored) { bmp.Save("unexplored/ " + CleanFileName(mapRow.ID + " - " + mapName + ".png")); } if (!saveLayers && !saveExplored) { continue; } foreach (dynamic wmorow in WorldMapOverlay.Values) { var WMOUIMapArtID = wmorow.UiMapArtID; var offsetX = wmorow.OffsetX; var offsetY = wmorow.OffsetY; uint maxWMORows = 0; uint maxWMOCols = 0; var wmoTileDict = new Dictionary <string, int>(); if (WMOUIMapArtID == uiMapArtID) { foreach (dynamic wmotrow in WorldMapOverlayTile.Values) { var worldMapOverlayID = wmotrow.WorldMapOverlayID; // something wrong in/around this check if (worldMapOverlayID == wmorow.ID) { var fdid = wmotrow.FileDataID; var rowIndex = wmotrow.RowIndex; var colIndex = wmotrow.ColIndex; var layerIndex = wmotrow.LayerIndex; // Skip other layers for now if (layerIndex != 0) { continue; } if (rowIndex > maxWMORows) { maxWMORows = rowIndex; } if (colIndex > maxWMOCols) { maxWMOCols = colIndex; } wmoTileDict.Add(rowIndex + "," + colIndex, fdid); } } } if (wmoTileDict.Count == 0) { continue; } var layerResX = (maxWMORows + 1) * 256; var layerResY = (maxWMOCols + 1) * 256; var layerBitmap = new Bitmap((int)layerResY, (int)layerResX); var layerGraphics = Graphics.FromImage(layerBitmap); for (var cur_x = 0; cur_x < maxWMORows + 1; cur_x++) { for (var cur_y = 0; cur_y < maxWMOCols + 1; cur_y++) { var fdid = wmoTileDict[cur_x + "," + cur_y]; if (CASC.FileExists((uint)fdid)) { using (var stream = CASC.OpenFile((uint)fdid)) { try { var blp = new BlpFile(stream); var posY = cur_y * 256 + offsetX; var posX = cur_x * 256 + offsetY; if (saveLayers) { layerGraphics.DrawImage(blp.GetBitmap(0), cur_y * 256, cur_x * 256, new Rectangle(0, 0, 256, 256), GraphicsUnit.Pixel); } var blpBMP = blp.GetBitmap(0); g.DrawImage(blpBMP, posY, posX, new Rectangle(0, 0, 256, 256), GraphicsUnit.Pixel); if (saveExploredMapsWithoutUnexplored) { g2.DrawImage(blpBMP, posY, posX, new Rectangle(0, 0, 256, 256), GraphicsUnit.Pixel); } } catch (Exception e) { Console.WriteLine("An error occured opening BLP with filedataid " + fdid); } } } } } if (saveLayers) { if (!Directory.Exists("layers/" + CleanFileName(mapRow + " - " + mapName) + "/")) { Directory.CreateDirectory("layers/" + CleanFileName(mapRow.ID + " - " + mapName) + "/"); } layerBitmap.Save("layers/" + CleanFileName(mapRow.ID + " - " + mapName) + "/" + wmorow.ID + ".png"); } } if (saveExplored) { bmp.Save("explored/ " + CleanFileName(mapRow.ID + " - " + mapName + ".png")); } if (saveExploredMapsWithoutUnexplored) { bmp2.Save("exploredNoUnexplored/ " + CleanFileName(mapRow.ID + " - " + mapName + ".png")); } } } } }
public static void Execute(string filter = null) { var dbcd = new DBCD.DBCD(new DBCProvider(dbPath), new DBDProvider(definitionsPath)); var build = "8.3.0.34220"; var connectionString = new SqlConnectionStringBuilder { InitialCatalog = "wow", DataSource = "(local)", IntegratedSecurity = true }.ToString(); using var connection = new SqlConnection(connectionString); connection.Open(); var server = new Server(); var database = server.Databases["wow"]; // The DBCache which stores downloaded / patched database records from the server side Console.WriteLine("Loading in hotfix cache..."); var hotfix = new HotfixReader(Path.Combine(cachePath, "DBCache.bin")); var caches = Directory.EnumerateFiles(cachePath, "DBCache.bin*.tmp").ToList(); hotfix.CombineCaches(caches.ToArray()); Console.WriteLine("Loading tables.."); foreach (var databaseFile in Directory.EnumerateFiles(dbPath, "*.db?", SearchOption.TopDirectoryOnly)) { Console.WriteLine(); var name = Path.GetFileNameWithoutExtension(databaseFile); if (name.StartsWith("UnitTest", StringComparison.OrdinalIgnoreCase)) { continue; } if (!string.IsNullOrWhiteSpace(filter) && !filter.Contains(name, StringComparison.OrdinalIgnoreCase)) { continue; } var storage = dbcd.Load(name, build, Locale.EnUS).ApplyingHotfixes(hotfix); DBCDRow item = storage.Values.FirstOrDefault(); if (item == null) { Console.WriteLine(name + ": **EMPTY**"); continue; } Console.WriteLine(name); Console.WriteLine(string.Join("", Enumerable.Repeat("=", name.Length))); using var table = new DataTable(name); for (var j = 0; j < storage.AvailableColumns.Length; ++j) { string fieldname = storage.AvailableColumns[j]; var field = item[fieldname]; var isEndOfRecord = j == storage.AvailableColumns.Length - 1; if (field is Array a) { for (var i = 0; i < a.Length; i++) { var isEndOfArray = a.Length - 1 == i; Console.Write($"{fieldname}[{i}]"); if (!isEndOfArray) { Console.Write(","); } table.Columns.Add(new DataColumn(fieldname + "_" + i) { DataType = a.GetType().GetElementType() }); } } else { var column = new DataColumn(fieldname) { DataType = field.GetType() }; table.Columns.Add(column); if (fieldname.Equals("id", StringComparison.OrdinalIgnoreCase)) { table.PrimaryKey = new[] { column }; } Console.Write(fieldname); } if (!isEndOfRecord) { Console.Write(","); } } database.CreateTableSchema(table); // Process rows foreach (var row in storage.Values) { var dataRow = table.NewRow(); foreach (var fieldName in storage.AvailableColumns) { var value = row[fieldName]; if (value is Array a) { for (var j = 0; j < a.Length; j++) { var arrayValue = a.GetValue(j).ToString(); // if (searchValues.Contains(arrayValue)) // { // Console.ForegroundColor = ConsoleColor.Yellow; // Console.WriteLine($"Found matching record: {table.TableName}#{row.ID}"); // Console.ResetColor(); // } dataRow[fieldName + "_" + j] = arrayValue; } } else { dataRow[fieldName] = value; } } table.Rows.Add(dataRow); } // Bulk import the data var bulk = new SqlBulkCopy(connection); bulk.DestinationTableName = table.TableName; bulk.WriteToServer(table); Console.WriteLine(); } }