public static ADTChunk Process(BinaryReader fileReader, uint mcnkOffset, ADT parent) { var chunk = new ADTChunk(); fileReader.BaseStream.Position = mcnkOffset; // Read the header ReadMCNK(fileReader, chunk); if (chunk.Header.offsColorValues != 0) { fileReader.BaseStream.Position = mcnkOffset + chunk.Header.offsColorValues; ReadMCCV(fileReader, chunk); } if (chunk.Header.ofsHeight != 0) { fileReader.BaseStream.Position = mcnkOffset + chunk.Header.ofsHeight; ReadMCVT(fileReader, chunk); } if (chunk.Header.ofsNormal != 0) { fileReader.BaseStream.Position = mcnkOffset + chunk.Header.ofsNormal; ReadMCNR(fileReader, chunk); } if (chunk.Header.ofsLayer != 0) { fileReader.BaseStream.Position = mcnkOffset + chunk.Header.ofsLayer; ReadMCLY(fileReader, chunk); } if (chunk.Header.ofsRefs != 0) { fileReader.BaseStream.Position = mcnkOffset + chunk.Header.ofsRefs; ReadMCRF(fileReader, chunk); } if (chunk.Header.ofsShadow != 0) { fileReader.BaseStream.Position = mcnkOffset + chunk.Header.ofsShadow; ReadMCSH(fileReader, chunk); } if (chunk.Header.ofsAlpha != 0) { fileReader.BaseStream.Position = mcnkOffset + chunk.Header.ofsAlpha; ReadMCAL(fileReader, chunk); } if (chunk.Header.ofsSndEmitters != 0) { fileReader.BaseStream.Position = mcnkOffset + chunk.Header.ofsSndEmitters; ReadMCSE(fileReader, chunk); } return chunk; }
public static ADT[,] ExtractMapTiles(WDTFile wdt) { var mapTiles = new ADT[TerrainConstants.TilesPerMapSide, TerrainConstants.TilesPerMapSide]; for (var x = 0; x < TerrainConstants.TilesPerMapSide; x++) { for (var y = 0; y < TerrainConstants.TilesPerMapSide; y++) { if (!wdt.TileProfile[y, x]) continue; var adt = ADTParser.Process(WDTParser.MpqManager, wdt.Entry, x, y); if (adt == null) continue; adt.IsWMOOnly = false; // Load in the WMORoots and their DoodadDefinitions // Load in the ADTs referenced M2Models PrepareChunkInfo(wdt.Manager, adt); mapTiles[y, x] = adt; } } return mapTiles; }
static void ReadMVER(BinaryReader fileReader, ADT adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); adt.Version = fileReader.ReadInt32(); }
static void ReadMH2O(BinaryReader fileReader, ADT adt) { var sig = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); var ofsMH2O = fileReader.BaseStream.Position; var mh20Header = new MH20Header[256]; for (var i = 0; i < 256; i++) { mh20Header[i].ofsInfo = fileReader.ReadUInt32(); mh20Header[i].LayerCount = fileReader.ReadUInt32(); //if (mh20Header[i].LayerCount > 0) //{ // Console.WriteLine(); //} mh20Header[i].ofsRenderMask = fileReader.ReadUInt32(); } // Rows for (var x = 0; x < 16; x++) { // Columns for (var y = 0; y < 16; y++) { // Indexing is [col, row] adt.LiquidInfo[y, x] = ProcessMH2O(fileReader, mh20Header[x*16 + y], ofsMH2O); } } }
static void ReadMCNK(BinaryReader br, ADT adt) { for (var i = 0; i < 256; i++) { var chunk = ADTChunkParser.Process(br, adt.MapChunkInfo[i].Offset, adt); adt.MapChunks[chunk.Header.IndexY, chunk.Header.IndexX] = chunk; } }
static void ReadMFBO(BinaryReader fileReader, ADT adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); }
static void ReadMHDR(BinaryReader fileReader, ADT adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); adt.Header.Base = (uint) fileReader.BaseStream.Position; var pad = fileReader.ReadUInt32(); adt.Header.offsInfo = fileReader.ReadUInt32(); adt.Header.offsTex = fileReader.ReadUInt32(); adt.Header.offsModels = fileReader.ReadUInt32(); adt.Header.offsModelIds = fileReader.ReadUInt32(); adt.Header.offsMapObjects = fileReader.ReadUInt32(); adt.Header.offsMapObjectIds = fileReader.ReadUInt32(); adt.Header.offsDoodadDefinitions = fileReader.ReadUInt32(); adt.Header.offsObjectDefinitions = fileReader.ReadUInt32(); adt.Header.offsFlightBoundary = fileReader.ReadUInt32(); adt.Header.offsMH2O = fileReader.ReadUInt32(); var pad3 = fileReader.ReadUInt32(); var pad4 = fileReader.ReadUInt32(); var pad5 = fileReader.ReadUInt32(); var pad6 = fileReader.ReadUInt32(); var pad7 = fileReader.ReadUInt32(); }
public static void WriteTileInfo(FileStream file, ADT adt) { var writer = new BinaryWriter(file); writer.Write(FileTypeId); writer.Write(adt.IsWMOOnly); WriteWMODefs(writer, adt.ObjectDefinitions); if (adt.IsWMOOnly) return; WriteM2Defs(writer, adt.DoodadDefinitions); for (var x = 0; x < TerrainConstants.ChunksPerTileSide; x++) { for (var y = 0; y < TerrainConstants.ChunksPerTileSide; y++) { var chunk = adt.MapChunks[y, x]; // Whether this chunk has a height map WriteChunkInfo(writer, chunk); } } }
static void ReadMWID(BinaryReader fileReader, ADT adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); uint count = size / 4; for (int i = 0; i < count; i++) { adt.ObjectFileOffsets.Add(fileReader.ReadInt32()); } }
public static ADT Process(MpqManager mpqManager, DBCMapEntry mapId, int tileX, int tileY) { var fileName = string.Format("{0}\\{0}_{1}_{2}{3}", mapId.MapDirName, tileY, tileX, Extension); var filePath = Path.Combine(baseDir, fileName); var adt = new ADT(fileName); if (!mpqManager.FileExists(filePath)) { log.Error("ADT file does not exist: ", filePath); } var fileReader = new BinaryReader(mpqManager.OpenFile(filePath)); ReadMVER(fileReader, adt); ReadMHDR(fileReader, adt); if (adt.Header.offsInfo != 0) { fileReader.BaseStream.Position = adt.Header.Base + adt.Header.offsInfo; ReadMCIN(fileReader, adt); } if (adt.Header.offsTex != 0) { fileReader.BaseStream.Position = adt.Header.Base + adt.Header.offsTex; ReadMTEX(fileReader, adt); } if (adt.Header.offsModels != 0) { fileReader.BaseStream.Position = adt.Header.Base + adt.Header.offsModels; ReadMMDX(fileReader, adt); } if (adt.Header.offsModelIds != 0) { fileReader.BaseStream.Position = adt.Header.Base + adt.Header.offsModelIds; ReadMMID(fileReader, adt); } if (adt.Header.offsMapObjects != 0) { fileReader.BaseStream.Position = adt.Header.Base + adt.Header.offsMapObjects; ReadMWMO(fileReader, adt); } if (adt.Header.offsMapObjectIds != 0) { fileReader.BaseStream.Position = adt.Header.Base + adt.Header.offsMapObjectIds; ReadMWID(fileReader, adt); } if (adt.Header.offsDoodadDefinitions != 0) { fileReader.BaseStream.Position = adt.Header.Base + adt.Header.offsDoodadDefinitions; ReadMDDF(fileReader, adt); } if (adt.Header.offsObjectDefinitions != 0) { fileReader.BaseStream.Position = adt.Header.Base + adt.Header.offsObjectDefinitions; ReadMODF(fileReader, adt); } if (adt.Header.offsFlightBoundary != 0) { fileReader.BaseStream.Position = adt.Header.Base + adt.Header.offsFlightBoundary; ReadMFBO(fileReader, adt); } if (adt.Header.offsMH2O != 0) { fileReader.BaseStream.Position = adt.Header.Base + adt.Header.offsMH2O; ReadMH2O(fileReader, adt); } ReadMCNK(fileReader, adt); fileReader.Close(); return adt; }
static void ReadMWMO(BinaryReader fileReader, ADT adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); var endPos = fileReader.BaseStream.Position + size; while (fileReader.BaseStream.Position < endPos) { if (fileReader.PeekByte() == 0) { fileReader.BaseStream.Position++; } else { adt.ObjectFiles.Add(fileReader.ReadCString()); } } }
static void ReadMMID(BinaryReader fileReader, ADT adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); var count = size/4; for (var i=0;i<count;i++) { adt.ModelNameOffsets.Add(fileReader.ReadInt32()); } }
static void ReadMTEX(BinaryReader br, ADT adt) { }
static void ReadMCIN(BinaryReader fileReader, ADT adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); adt.MapChunkInfo = new MapChunkInfo[256]; for (var i = 0; i < 256; i++) { var mcin = new MapChunkInfo { Offset = fileReader.ReadUInt32(), Size = fileReader.ReadUInt32(), Flags = fileReader.ReadUInt32(), AsyncId = fileReader.ReadUInt32() }; if (mcin.Flags != 0) { Console.WriteLine(); } adt.MapChunkInfo[i] = mcin; } }
private static void PrepareChunkInfo(MpqManager manager, ADT adt) { for (var chunkX = 0; chunkX < TerrainConstants.ChunksPerTileSide; chunkX++) { for (var chunkY = 0; chunkY < TerrainConstants.ChunksPerTileSide; chunkY++) { var chunk = adt.MapChunks[chunkY, chunkX]; foreach (var dRefId in chunk.DoodadRefs) { var dRef = adt.DoodadDefinitions[dRefId]; if (dRef == null) continue; if (ModelsToIgnore.Contains(dRef.FilePath)) continue; if (LoadedM2Ids.Contains(dRef.UniqueId)) continue; M2Model model; if (!WorldObjectExtractor.LoadedM2Models.TryGetValue(dRef.FilePath, out model)) { model = M2ModelParser.Process(manager, dRef.FilePath); WorldObjectExtractor.LoadedM2Models.Add(dRef.FilePath, model); } // This model may have no collision information. If so there is no point saving the data. if (model.BoundingVertices.IsNullOrEmpty()) { // This model has no collision information. We'll ignore it. ModelsToIgnore.Add(dRef.FilePath); WorldObjectExtractor.LoadedM2Models.Remove(dRef.FilePath); } // At this point, we're using the model for collision stuff PrepareM2Info(dRef, model); LoadedM2Ids.Add(dRef.UniqueId); } foreach (var oRefId in chunk.ObjectRefs) { var oRef = adt.ObjectDefinitions[oRefId]; if (oRef == null) continue; LoadWMO(manager, oRef); } PrepareChunk(adt, chunkX, chunkY); } } }
private static void PrepareChunk(ADT adt, int chunkX, int chunkY) { var chunk = adt.MapChunks[chunkY, chunkX]; if (chunk == null) return; var min = float.MaxValue; var max = float.MinValue; foreach (var height in chunk.Heights.Heights) { min = Math.Min(height, min); max = Math.Max(height, max); } chunk.IsFlat = (Math.Abs(max - min) < TerrainConstants.MinAllowedHeightDiff); chunk.WaterInfo = adt.LiquidInfo[chunkY, chunkX]; PrepareWaterInfo(chunk.WaterInfo); // Replace the model and wmo refs with their respective UniqueIds for (var i = 0; i < chunk.DoodadRefs.Count; i++) { var doodadRef = chunk.DoodadRefs[i]; var def = adt.DoodadDefinitions[doodadRef]; if (def == null || ModelsToIgnore.Contains(def.FilePath)) { chunk.DoodadRefs[i] = int.MinValue; continue; } var uniqueId = def.UniqueId; chunk.DoodadRefs[i] = (int)uniqueId; } for (var i = 0; i < chunk.ObjectRefs.Count; i++) { var objectRef = chunk.ObjectRefs[i]; var def = adt.ObjectDefinitions[objectRef]; if (def == null) { chunk.ObjectRefs[i] = int.MinValue; continue; } var uniqueId = def.UniqueId; chunk.ObjectRefs[i] = (int)uniqueId; } }
static void ReadMDDF(BinaryReader fileReader, ADT adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); long endPos = fileReader.BaseStream.Position + size; while (fileReader.BaseStream.Position < endPos) { var doodadDefinition = new MapDoodadDefinition(); var nameIndex = fileReader.ReadInt32(); doodadDefinition.FilePath = adt.ModelFiles[nameIndex]; // 4 bytes doodadDefinition.UniqueId = fileReader.ReadUInt32(); // 4 bytes var Y = fileReader.ReadSingle(); var Z = fileReader.ReadSingle(); var X = fileReader.ReadSingle(); doodadDefinition.Position = new Vector3(X, Y, Z); // 12 bytes doodadDefinition.OrientationA = fileReader.ReadSingle(); // 4 Bytes doodadDefinition.OrientationB = fileReader.ReadSingle(); // 4 Bytes doodadDefinition.OrientationC = fileReader.ReadSingle(); // 4 Bytes doodadDefinition.Scale = fileReader.ReadUInt16() / 1024f; // 2 bytes doodadDefinition.Flags = fileReader.ReadUInt16(); // 2 bytes adt.DoodadDefinitions.Add(doodadDefinition); } }
public static ADT ExtractWMOOnly(WDTFile wdt) { var adt = new ADT(""); adt.ObjectDefinitions.Capacity = wdt.WmoDefinitions.Count; foreach (var wmoDefinition in wdt.WmoDefinitions) { adt.ObjectDefinitions.Add(wmoDefinition); } adt.ObjectFiles.Capacity = wdt.WmoFiles.Count; foreach (var wmoFile in wdt.WmoFiles) { adt.ObjectFiles.Add(wmoFile); } foreach (var def in adt.ObjectDefinitions) { LoadWMO(wdt.Manager, def); } return adt; }
static void ReadMODF(BinaryReader fileReader, ADT adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); var endPos = fileReader.BaseStream.Position + size; while (fileReader.BaseStream.Position < endPos) { var objectDef = new MapObjectDefinition(); var nameIndex = fileReader.ReadInt32(); // 4 bytes objectDef.FilePath = adt.ObjectFiles[nameIndex]; objectDef.UniqueId = fileReader.ReadUInt32(); // 4 bytes // This Position appears to be in the wrong order. // To get WoW coords, read it as: {Y, Z, X} var Y = fileReader.ReadSingle(); var Z = fileReader.ReadSingle(); var X = fileReader.ReadSingle(); objectDef.Position = new Vector3(X, Y, Z); // 12 bytes objectDef.OrientationA = fileReader.ReadSingle(); // 4 Bytes objectDef.OrientationB = fileReader.ReadSingle(); // 4 Bytes objectDef.OrientationC = fileReader.ReadSingle(); // 4 Bytes var min = new Vector3 { Y = fileReader.ReadSingle(), Z = fileReader.ReadSingle(), X = fileReader.ReadSingle() }; var max = new Vector3 { Y = fileReader.ReadSingle(), Z = fileReader.ReadSingle(), X = fileReader.ReadSingle() }; objectDef.Extents = new BoundingBox(min, max); // 12*2 bytes objectDef.Flags = fileReader.ReadUInt16(); // 2 bytes objectDef.DoodadSetId = fileReader.ReadUInt16(); // 2 bytes objectDef.NameSet = fileReader.ReadUInt16(); // 2 bytes fileReader.ReadUInt16(); // padding adt.ObjectDefinitions.Add(objectDef); } }