Ejemplo n.º 1
0
        private void parseMapChunkSubChunks(ref MCNK mapChunk, FileStream ms, long lastpos)
        {
            BinaryReader bin = new BinaryReader(ms);

            BlizChunkHeader tempHeader;
            long pos = ms.Position;

            // Read bytes from the stream until we run out
            while (pos < lastpos)
            {
                // Advance to the next Chunk
                ms.Position = pos;

                // Read in Chunk Header Name
                tempHeader = new BlizChunkHeader(bin.ReadChars(4), bin.ReadUInt32());
                tempHeader.Flip();

                // Set pos to the location of the next Chunk
                pos = ms.Position + tempHeader.Size;

                if (tempHeader.Is("MCVT"))  // These are the actual height values for the 9x9+8x8 vertices.
                {
                    mapChunk.VerticesOuter = new float[9][];
                    mapChunk.VerticesInner = new float[8][];

                    for (int i = 0; i < 9; i++)
                    {
                        mapChunk.VerticesOuter[i] = new float[9];

                        for (int j = 0; j < 9; j++)
                        {
                            mapChunk.VerticesOuter[i][j] = bin.ReadSingle();
                        }

                        if (i == 8) continue;

                        mapChunk.VerticesInner[i] = new float[8];

                        for (int j = 0; j < 8; j++)
                        {
                            mapChunk.VerticesInner[i][j] = bin.ReadSingle();
                        }
                    }

                    continue;
                }

                if (tempHeader.Is("MCNR"))  // Normal vectors for each vertex.
                {
                    pos = ms.Position + 0x1C0; // sizefix?
                    // Not needed.
                    continue;
                }

                if (tempHeader.Is("MCLY"))  // Texture layer definitions for this map chunk.
                {
                    // Not needed.
                    continue;
                }

                if (tempHeader.Is("MCRF"))  // Unknown. List of integers.
                {
                    // Not needed.
                    continue;
                }

                if (tempHeader.Is("MCSH"))  // Shadow map for static shadows on the terrain.
                {
                    // Not needed.
                    continue;
                }

                if (tempHeader.Is("MCAL"))  // Alpha maps for additional texture layers.
                {
                    // Not needed.
                    continue;
                }

                if (tempHeader.Is("MCLQ"))  // Water levels for this map chunk.
                {
                    mapChunk.Liquid = new MCLQ();

                    // I dunno. MCLQ header size lies. If MCSE is immidiately following, there's no water.
                    tempHeader = new BlizChunkHeader(bin.ReadChars(4), 0);
                    tempHeader.Flip();

                    if (tempHeader.Is("MCSE"))
                    {
                        mapChunk.Liquid.waterLevel = float.NaN;
                    }
                    else
                    {
                        // After reading water, we stop. I do NOT like this solution, but
                        // 1) We don't know much about MCLQ chunks.
                        // 2) The size field lies, saying its always 0. (no idea why)
                        // 3) I can't kludge this with a size fix, BECAUSE THE LENGTH VARIES?! Its in the area of 0x320, or 0x31F or 0x31E.
                        // 4) So stopping after this chunk is the best we can do; this is what wowmapview does in any case.
                        pos = lastpos;
                        ms.Seek(-4, SeekOrigin.Current); // Go back! Re-read the last 4 bytes as its actually a float not char[4].
                        mapChunk.Liquid.waterLevel = bin.ReadSingle();
                    }

                    continue;
                }

                if (tempHeader.Is("MCSE"))  // Sound emitters.
                {
                    // Not needed.
                    continue;
                }

                // If we're still down here, we got a problem
                throw new Exception(String.Format("ADTFile: Woah. Got a header of Sub-{0}. Don't know how to deal with this, bailing out.", tempHeader.ToString()));
            }
        }
Ejemplo n.º 2
0
        private void parseFile()
        {
            FileStream ms = adtStream;
            if (ms == null)
            {
                throw new Exception("Stream null!");
            }
            BinaryReader bin = new BinaryReader(ms);

            BlizChunkHeader tempHeader;
            long pos = 0;

            // Read bytes from the stream until we run out
            while (pos < ms.Length)
            {
                // Advance to the next Chunk
                ms.Position = pos;

                // Read in Chunk Header Name
                tempHeader = new BlizChunkHeader(bin.ReadChars(4), bin.ReadUInt32());
                tempHeader.Flip();

                // Set pos to the location of the next Chunk
                pos = ms.Position + tempHeader.Size;

                if (tempHeader.Is("MVER"))   // ADT File Version
                {
                    mver = new MVER();
                    mver.version = bin.ReadUInt32();

                    continue;
                }

                if (tempHeader.Is("MHDR"))  // ADT File Header
                {
                    mhdr = new MHDR();
                    mhdr.pad = bin.ReadUInt32();
                    mhdr.offsInfo = bin.ReadUInt32();
                    mhdr.offsTex = bin.ReadUInt32();
                    mhdr.offsModels = bin.ReadUInt32();
                    mhdr.offsModelsIds = bin.ReadUInt32();
                    mhdr.offsMapObejcts = bin.ReadUInt32();
                    mhdr.offsMapObejctsIds = bin.ReadUInt32();
                    mhdr.offsDoodsDef = bin.ReadUInt32();
                    mhdr.offsObjectsDef = bin.ReadUInt32();
                    mhdr.pad1 = bin.ReadUInt32();
                    mhdr.pad2 = bin.ReadUInt32();
                    mhdr.pad3 = bin.ReadUInt32();
                    mhdr.pad4 = bin.ReadUInt32();
                    mhdr.pad5 = bin.ReadUInt32();
                    mhdr.pad6 = bin.ReadUInt32();
                    mhdr.pad7 = bin.ReadUInt32();

                    continue;
                }

                if (tempHeader.Is("MCIN"))  // Index for MCNK chunks.
                {
                    if (tempHeader.Size != 256 * 16)
                        throw new Exception("MCIN Chunk is short??");

                    mcin_array = new MCIN[256];

                    // Read in the 256 records
                    for (int i = 0; i < 256; i++)
                    {
                        mcin_array[i].MCNK_offset = bin.ReadUInt32();
                        mcin_array[i].MCNK_size = bin.ReadUInt32();
                        mcin_array[i].flags = bin.ReadUInt32();
                        mcin_array[i].asyncID = bin.ReadUInt32();
                    }

                    continue;
                }

                if (tempHeader.Is("MTEX"))  // List of texture filenames used by the terrain in this map tile.
                {
                    // Not needed.
                    continue;
                }

                if (tempHeader.Is("MMDX")) // List of filenames for M2 models that appear in this map tile.
                {
                    // Not needed.
                    continue;
                }

                if (tempHeader.Is("MMID"))  // Lists the relative offsets of string beginnings in the above MMDX chunk.
                {
                    // Not needed.
                    continue;
                }

                if (tempHeader.Is("MWMO"))  // List of filenames for WMOs (world map objects) that appear in this map tile.
                {
                    byte[] wmoFilesChunk = bin.ReadBytes((int)tempHeader.Size);

                    wmoFiles = new List<String>();

                    StringBuilder str = new StringBuilder();

                    // Convert szString's to a List<String>.
                    for (int i = 0; i < wmoFilesChunk.Length; i++)
                    {
                        if (wmoFilesChunk[i] == '\0')
                        {
                            if (str.Length > 1)
                                wmoFiles.Add(str.ToString());
                            str = new StringBuilder();
                        }
                        else
                            str.Append((char)wmoFilesChunk[i]);
                    }

                    continue;
                }

                if (tempHeader.Is("MWID"))  // Lists the relative offsets of string beginnings in the above MWWO chunk.
                {
                    // Not needed.
                    continue;
                }

                if (tempHeader.Is("MDDF"))  // Placement information for doodads (M2 models).
                {
                    uint num = tempHeader.Size / 32;

                    doodadLocations = new MDDF[num];

                    for (int i = 0; i < num; i++)
                    {
                        doodadLocations[i].nameId = bin.ReadUInt32();
                        doodadLocations[i].uniqueId = bin.ReadUInt32();
                        doodadLocations[i].coord = new Coordinate(bin.ReadSingle(), bin.ReadSingle(), bin.ReadSingle());
                    }

                    continue;
                }

                if (tempHeader.Is("MODF"))  // Placement information for WMOs.
                {
                    uint num = tempHeader.Size / 64;

                    wmoLocations = new MODF[num];

                    for (int i = 0; i < num; i++)
                    {
                        wmoLocations[i].nameId = bin.ReadUInt32();
                        wmoLocations[i].uniqueId = bin.ReadUInt32();
                        wmoLocations[i].coord = new Coordinate(bin.ReadSingle(), bin.ReadSingle(), bin.ReadSingle());
                        wmoLocations[i].orientation = new Vect3D(bin.ReadSingle(), bin.ReadSingle(), bin.ReadSingle());
                        wmoLocations[i].coord2 = new Coordinate(bin.ReadSingle(), bin.ReadSingle(), bin.ReadSingle());
                        wmoLocations[i].coord3 = new Coordinate(bin.ReadSingle(), bin.ReadSingle(), bin.ReadSingle());
                        wmoLocations[i].flags = bin.ReadUInt32();
                        wmoLocations[i].doodadSet = bin.ReadUInt16();
                        wmoLocations[i].nameSet = bin.ReadUInt16();
                    }

                    continue;
                }

                if (tempHeader.Is("MCNK")) // || tempHeader.Is("MCVT") || tempHeader.Is("MCNR") || tempHeader.Is("MCLY") || tempHeader.Is("MCRF") || tempHeader.Is("MCSH") || tempHeader.Is("MCAL") || tempHeader.Is("MCLQ") || tempHeader.Is("MCSE"))
                {
                    // Skip these. They are read in afterwards.
                    continue;
                }

                // If we're still down here, we got a problem
                throw new Exception(String.Format("ADTFile: Woah. Got a header of {0}. Don't know how to deal with this, bailing out.", tempHeader.ToString()));
            }

            // Read in Map Chunks
            mapChunkTable = new MCNK[16][];

            for (int i = 0; i < 16; i++)
            {
                mapChunkTable[i] = new MCNK[16];

                for (int j = 0; j < 16; j++)
                {
                    int index = i * 16 + j;
                    Log.WriteLine(LogType.Terrain,  "Parsing MCNK Chunk #{0} [{1}, {2}]", index, i, j);
                    mapChunkTable[i][j] = parseMapChunk(ms, mcin_array[index].MCNK_offset, mcin_array[index].MCNK_size);
                }
            }
        }
Ejemplo n.º 3
0
        // Read in an MCNK chunk at supplied offset.
        private MCNK parseMapChunk(FileStream ms, uint offset, uint size)
        {
            BinaryReader bin = new BinaryReader(ms);
            ms.Position = offset;

            BlizChunkHeader tempHeader = new BlizChunkHeader(bin.ReadChars(4), bin.ReadUInt32());
            tempHeader.Flip();

            if (!tempHeader.Is("MCNK"))
                throw new Exception("This was supposed to be an MCNK chunk. Wtf?");

            long lastpos = ms.Position + tempHeader.Size;

            MCNK mapChunk = new MCNK();

            mapChunk.flags = bin.ReadUInt32();
            mapChunk.ix = bin.ReadUInt32();
            mapChunk.iy = bin.ReadUInt32();
            mapChunk.nLayers = bin.ReadUInt32();
            mapChunk.nDoodadRefs = bin.ReadUInt32();
            mapChunk.ofsHeight = bin.ReadUInt32();
            mapChunk.ofsNormal = bin.ReadUInt32();
            mapChunk.ofsLayer = bin.ReadUInt32();
            mapChunk.ofsRefs = bin.ReadUInt32();
            mapChunk.ofsAlpha = bin.ReadUInt32();
            mapChunk.sizeAlpha = bin.ReadUInt32();
            mapChunk.ofsShadow = bin.ReadUInt32();
            mapChunk.sizeShadow = bin.ReadUInt32();
            mapChunk.areaid = bin.ReadUInt32();
            mapChunk.nMapObjRefs = bin.ReadUInt32();
            mapChunk.holes = bin.ReadUInt32();
            mapChunk.s1 = bin.ReadUInt16();
            mapChunk.s2 = bin.ReadUInt16();
            mapChunk.d1 = bin.ReadUInt32();
            mapChunk.d2 = bin.ReadUInt32();
            mapChunk.d3 = bin.ReadUInt32();
            mapChunk.predTex = bin.ReadUInt32();
            mapChunk.nEffectDoodad = bin.ReadUInt32();
            mapChunk.ofsSndEmitters = bin.ReadUInt32();
            mapChunk.nSndEmitters = bin.ReadUInt32();
            mapChunk.ofsLiquid = bin.ReadUInt32();
            mapChunk.sizeLiquid = bin.ReadUInt32();
            mapChunk.zpos = bin.ReadSingle();
            mapChunk.xpos = bin.ReadSingle();
            mapChunk.ypos = bin.ReadSingle();
            mapChunk.textureId = bin.ReadUInt32();
            mapChunk.props = bin.ReadUInt32();
            mapChunk.effectId = bin.ReadUInt32();

            // Parse this MapChunk's SubChunks!
            parseMapChunkSubChunks(ref mapChunk, ms, lastpos);

            return mapChunk;
        }