Example #1
0
        public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags)
        {
            string output = flags.Positionals[2];

            List <string> maps = new List <string>();

            if (flags.Positionals.Length > 3)
            {
                maps.AddRange(flags.Positionals.Skip(2).Select((it) => it.ToLower()));
            }
            bool wildcard = maps.Count == 0 || maps.Contains("*");

            List <ulong> masters = track[0x9F];
            Dictionary <ulong, ulong> replace = new Dictionary <ulong, ulong>();

            foreach (ulong masterKey in masters)
            {
                if (!map.ContainsKey(masterKey))
                {
                    continue;
                }
                STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler));
                if (masterStud.Instances == null || masterStud.Instances[0] == null)
                {
                    continue;
                }
                MapMaster master = (MapMaster)masterStud.Instances[0];
                if (master == null)
                {
                    continue;
                }
                string name = Util.GetString(master.Header.name.key, map, handler);
                if (string.IsNullOrWhiteSpace(name))
                {
                    name = $"Unknown{GUID.Index(master.Header.data.key):X}";
                }
                if (!maps.Contains(name.ToLowerInvariant()) && !wildcard)
                {
                    continue;
                }
                if (!map.ContainsKey(master.DataKey(0xB)))
                {
                    continue;
                }
                if (!map.ContainsKey(master.DataKey(0x11)))
                {
                    continue;
                }
                Console.Out.WriteLine("Dumping audio for map {0}", name);
                Dictionary <ulong, List <ulong> > soundData = new Dictionary <ulong, List <ulong> >();
                string          path      = string.Format("{0}{1}{2}{1}{3}{1}{4}{1}", output, Path.DirectorySeparatorChar, Util.Strip(Util.SanitizePath(name)), "Audio", GUID.Index(master.Header.data.key));
                HashSet <ulong> soundDone = new HashSet <ulong>();
                using (Stream mapBStream = Util.OpenFile(map[master.DataKey(0xB)], handler)) {
                    if (mapBStream != null)
                    {
                        Map mapB = new Map(mapBStream);
                        foreach (STUD stud in mapB.STUDs)
                        {
                            Sound.FindSoundsSTUD(stud, soundDone, soundData, map, handler, replace, masterKey, master.DataKey(0xB));
                        }

                        for (int i = 0; i < mapB.Records.Length; ++i)
                        {
                            if (mapB.Records[i] != null && mapB.Records[i].GetType() != typeof(Map0B))
                            {
                                continue;
                            }
                            Map0B mapprop = (Map0B)mapB.Records[i];
                            if (!map.ContainsKey(mapprop.Header.binding))
                            {
                                continue;
                            }
                            Sound.FindSoundsEx(mapprop.Header.binding, soundDone, soundData, map, handler, replace, master.DataKey(0xB));
                        }
                    }
                }
                using (Stream map11Stream = Util.OpenFile(map[master.DataKey(0x11)], handler)) {
                    if (map11Stream != null)
                    {
                        Map11 map11 = new Map11(map11Stream);
                        Sound.FindSoundsSTUD(map11.main, soundDone, soundData, map, handler, replace, masterKey, master.DataKey(0x11));
                        Sound.FindSoundsSTUD(map11.secondary, soundDone, soundData, map, handler, replace, masterKey, master.DataKey(0x11));
                    }
                }
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                DumpVoice.Save(path, soundData, map, handler, quiet);
            }
        }
Example #2
0
        public Dictionary <ulong, List <string> >[] Write(Stream output, Map map, Map detail1, Map detail2, Map props, Map lights, string name, IDataWriter modelFormat)
        {
            if (modelFormat == null)
            {
                modelFormat = new OWMDLWriter();
            }
            //Console.Out.WriteLine("Writing OWMAP");
            using (BinaryWriter writer = new BinaryWriter(output)) {
                writer.Write((ushort)1); // version major
                writer.Write((ushort)1); // version minor

                if (name.Length == 0)
                {
                    writer.Write((byte)0);
                }
                else
                {
                    writer.Write(name);
                }

                uint size = 0;
                for (int i = 0; i < map.Records.Length; ++i)
                {
                    if (map.Records[i] != null && map.Records[i].GetType() != typeof(Map01))
                    {
                        continue;
                    }
                    size++;
                }
                writer.Write(size); // nr objects

                size = 1;
                for (int i = 0; i < detail1.Records.Length; ++i)
                {
                    if (detail1.Records[i] != null && detail1.Records[i].GetType() != typeof(Map02))
                    {
                        continue;
                    }
                    size++;
                }
                for (int i = 0; i < detail2.Records.Length; ++i)
                {
                    if (detail2.Records[i] != null && detail2.Records[i].GetType() != typeof(Map08))
                    {
                        continue;
                    }
                    size++;
                }
                for (int i = 0; i < props.Records.Length; ++i)
                {
                    if (props.Records[i] != null && props.Records[i].GetType() != typeof(Map0B))
                    {
                        continue;
                    }
                    if (((Map0B)props.Records[i]).ModelKey == 0)
                    {
                        continue;
                    }
                    size++;
                }
                writer.Write(size); // nr details

                // Extension 1.1 - Lights
                size = 0;
                for (int i = 0; i < lights.Records.Length; ++i)
                {
                    if (lights.Records[i] != null && lights.Records[i].GetType() != typeof(Map09))
                    {
                        continue;
                    }
                    size++;
                }
                writer.Write(size); // nr Lights


                Dictionary <ulong, List <string> >[] ret = new Dictionary <ulong, List <string> > [2];
                ret[0] = new Dictionary <ulong, List <string> >();
                ret[1] = new Dictionary <ulong, List <string> >();

                for (int i = 0; i < map.Records.Length; ++i)
                {
                    if (map.Records[i] != null && map.Records[i].GetType() != typeof(Map01))
                    {
                        continue;
                    }
                    Map01  obj     = (Map01)map.Records[i];
                    string modelFn = $"{GUID.Index(obj.Header.model):X12}{modelFormat.Format}";
                    writer.Write(modelFn);
                    if (!ret[0].ContainsKey(obj.Header.model))
                    {
                        ret[0].Add(obj.Header.model, new List <string>());
                    }
                    ret[0][obj.Header.model].Add(modelFn);
                    writer.Write(obj.Header.groupCount);
                    for (int j = 0; j < obj.Header.groupCount; ++j)
                    {
                        Map01.Map01Group group      = obj.Groups[j];
                        string           materialFn =
                            $"{GUID.Index(obj.Header.model):X12}_{GUID.Index(@group.material):X12}.owmat";
                        writer.Write(materialFn);
                        if (!ret[1].ContainsKey(group.material))
                        {
                            ret[1].Add(group.material, new List <string>());
                        }
                        ret[1][group.material].Add(materialFn);
                        writer.Write(group.recordCount);
                        for (int k = 0; k < group.recordCount; ++k)
                        {
                            Map01.Map01GroupRecord record = obj.Records[j][k];
                            writer.Write(record.position.x);
                            writer.Write(record.position.y);
                            writer.Write(record.position.z);
                            writer.Write(record.scale.x);
                            writer.Write(record.scale.y);
                            writer.Write(record.scale.z);
                            writer.Write(record.rotation.x);
                            writer.Write(record.rotation.y);
                            writer.Write(record.rotation.z);
                            writer.Write(record.rotation.w);
                        }
                    }
                }

                writer.Write($"physics.{modelFormat.Format}");
                writer.Write((byte)0);
                writer.Write(0.0f);
                writer.Write(0.0f);
                writer.Write(0.0f);
                writer.Write(1.0f);
                writer.Write(1.0f);
                writer.Write(1.0f);
                writer.Write(0.0f);
                writer.Write(0.0f);
                writer.Write(0.0f);
                writer.Write(1.0f);

                for (int i = 0; i < detail1.Records.Length; ++i)
                {
                    if (detail1.Records[i] != null && detail1.Records[i].GetType() != typeof(Map02))
                    {
                        continue;
                    }
                    Map02  obj     = (Map02)detail1.Records[i];
                    string modelFn = $"{GUID.LongKey(obj.Header.model):X12}{modelFormat.Format}";
                    string matFn   = $"{GUID.LongKey(obj.Header.model):X12}.owmat";
                    writer.Write(modelFn);
                    writer.Write(matFn);
                    writer.Write(obj.Header.position.x);
                    writer.Write(obj.Header.position.y);
                    writer.Write(obj.Header.position.z);
                    writer.Write(obj.Header.scale.x);
                    writer.Write(obj.Header.scale.y);
                    writer.Write(obj.Header.scale.z);
                    writer.Write(obj.Header.rotation.x);
                    writer.Write(obj.Header.rotation.y);
                    writer.Write(obj.Header.rotation.z);
                    writer.Write(obj.Header.rotation.w);

                    if (!ret[0].ContainsKey(obj.Header.model))
                    {
                        ret[0].Add(obj.Header.model, new List <string>());
                    }
                    ret[0][obj.Header.model].Add(modelFn);


                    if (!ret[1].ContainsKey(obj.Header.material))
                    {
                        ret[1].Add(obj.Header.material, new List <string>());
                    }
                    ret[1][obj.Header.material].Add(matFn);
                }

                for (int i = 0; i < detail2.Records.Length; ++i)
                {
                    if (detail2.Records[i] != null && detail2.Records[i].GetType() != typeof(Map08))
                    {
                        continue;
                    }
                    Map08  obj     = (Map08)detail2.Records[i];
                    string modelFn = $"{GUID.LongKey(obj.Header.model):X12}{modelFormat.Format}";
                    string matFn   = $"{GUID.LongKey(obj.Header.model):X12}.owmat";
                    writer.Write(modelFn);
                    writer.Write(matFn);
                    writer.Write(obj.Header.position.x);
                    writer.Write(obj.Header.position.y);
                    writer.Write(obj.Header.position.z);
                    writer.Write(obj.Header.scale.x);
                    writer.Write(obj.Header.scale.y);
                    writer.Write(obj.Header.scale.z);
                    writer.Write(obj.Header.rotation.x);
                    writer.Write(obj.Header.rotation.y);
                    writer.Write(obj.Header.rotation.z);
                    writer.Write(obj.Header.rotation.w);

                    if (!ret[0].ContainsKey(obj.Header.model))
                    {
                        ret[0].Add(obj.Header.model, new List <string>());
                    }
                    ret[0][obj.Header.model].Add(modelFn);


                    if (!ret[1].ContainsKey(obj.Header.material))
                    {
                        ret[1].Add(obj.Header.material, new List <string>());
                    }
                    ret[1][obj.Header.material].Add(matFn);
                }

                for (int i = 0; i < props.Records.Length; ++i)
                {
                    if (props.Records[i] != null && props.Records[i].GetType() != typeof(Map0B))
                    {
                        continue;
                    }
                    Map0B obj = (Map0B)props.Records[i];
                    if (obj.ModelKey == 0)
                    {
                        continue;
                    }
                    string modelFn = $"{GUID.LongKey(obj.ModelKey):X12}{modelFormat.Format}";
                    string matFn   = $"{GUID.LongKey(obj.MaterialKey):X12}.owmat";
                    writer.Write(modelFn);
                    writer.Write(matFn);
                    writer.Write(obj.Header.position.x);
                    writer.Write(obj.Header.position.y);
                    writer.Write(obj.Header.position.z);
                    writer.Write(obj.Header.scale.x);
                    writer.Write(obj.Header.scale.y);
                    writer.Write(obj.Header.scale.z);
                    writer.Write(obj.Header.rotation.x);
                    writer.Write(obj.Header.rotation.y);
                    writer.Write(obj.Header.rotation.z);
                    writer.Write(obj.Header.rotation.w);

                    if (!ret[0].ContainsKey(obj.ModelKey))
                    {
                        ret[0].Add(obj.ModelKey, new List <string>());
                    }
                    ret[0][obj.ModelKey].Add(modelFn);


                    if (!ret[1].ContainsKey(obj.MaterialKey))
                    {
                        ret[1].Add(obj.MaterialKey, new List <string>());
                    }
                    ret[1][obj.MaterialKey].Add(matFn);
                }

                // Extension 1.1 - Lights
                for (int i = 0; i < lights.Records.Length; ++i)
                {
                    if (lights.Records[i] != null && lights.Records[i].GetType() != typeof(Map09))
                    {
                        continue;
                    }
                    Map09 obj = (Map09)lights.Records[i];
                    writer.Write(obj.Header.position.x);
                    writer.Write(obj.Header.position.y);
                    writer.Write(obj.Header.position.z);
                    writer.Write(obj.Header.rotation.x);
                    writer.Write(obj.Header.rotation.y);
                    writer.Write(obj.Header.rotation.z);
                    writer.Write(obj.Header.rotation.w);
                    writer.Write(obj.Header.LightType);
                    writer.Write(obj.Header.LightFOV);
                    writer.Write(obj.Header.Color.x);
                    writer.Write(obj.Header.Color.y);
                    writer.Write(obj.Header.Color.z);
                    writer.Write(obj.Header.unknown1A);
                    writer.Write(obj.Header.unknown1B);
                    writer.Write(obj.Header.unknown2A);
                    writer.Write(obj.Header.unknown2B);
                    writer.Write(obj.Header.unknown2C);
                    writer.Write(obj.Header.unknown2D);
                    writer.Write(obj.Header.unknown3A);
                    writer.Write(obj.Header.unknown3B);

                    writer.Write(obj.Header.unknownPos1.x);
                    writer.Write(obj.Header.unknownPos1.y);
                    writer.Write(obj.Header.unknownPos1.z);
                    writer.Write(obj.Header.unknownQuat1.x);
                    writer.Write(obj.Header.unknownQuat1.y);
                    writer.Write(obj.Header.unknownQuat1.z);
                    writer.Write(obj.Header.unknownQuat1.w);
                    writer.Write(obj.Header.unknownPos2.x);
                    writer.Write(obj.Header.unknownPos2.y);
                    writer.Write(obj.Header.unknownPos2.z);
                    writer.Write(obj.Header.unknownQuat2.x);
                    writer.Write(obj.Header.unknownQuat2.y);
                    writer.Write(obj.Header.unknownQuat2.z);
                    writer.Write(obj.Header.unknownQuat2.w);
                    writer.Write(obj.Header.unknownPos3.x);
                    writer.Write(obj.Header.unknownPos3.y);
                    writer.Write(obj.Header.unknownPos3.z);
                    writer.Write(obj.Header.unknownQuat3.x);
                    writer.Write(obj.Header.unknownQuat3.y);
                    writer.Write(obj.Header.unknownQuat3.z);
                    writer.Write(obj.Header.unknownQuat3.w);

                    writer.Write(obj.Header.unknown4A);
                    writer.Write(obj.Header.unknown4B);
                    writer.Write(obj.Header.unknown5);
                    writer.Write(obj.Header.unknown6A);
                    writer.Write(obj.Header.unknown6B);
                    writer.Write(obj.Header.unknown7A);
                    writer.Write(obj.Header.unknown7B);
                }

                return(ret);
            }
        }
Example #3
0
        public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags)
        {
            string        output = flags.Positionals[2];
            List <string> maps   = flags.Positionals.Skip(3).ToList();

            bool skipCmodel = !flags.ExportCollision;

            for (int i = 0; i < maps.Count; ++i)
            {
                maps[i] = maps[i].ToUpperInvariant().TrimStart('0');
            }
            bool mapWildcard = maps.Count == 0;

            if (maps.Count > 0 && maps.Contains("*"))
            {
                mapWildcard = true;
            }

            char animEncoding = flags.AnimFormat;

            if (flags.Raw)
            {
                animEncoding = '+';
            }
            bool suppressAnimations = flags.SkipAnimations;

            if (animEncoding == '+' && !flags.RawAnimation)
            {
                suppressAnimations = true;
            }

            char modelEncoding = flags.ModelFormat;

            if (flags.Raw)
            {
                modelEncoding = '+';
            }
            bool suppressModels = flags.SkipModels;

            if (modelEncoding == '+' && !flags.RawModel)
            {
                suppressModels = true;
            }

            IDataWriter animWriter = null;

            if (animEncoding != 0 && animEncoding != '+')
            {
                Assembly    asm   = typeof(IDataWriter).Assembly;
                Type        t     = typeof(IDataWriter);
                List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList();
                foreach (Type tt in types)
                {
                    if (animWriter != null)
                    {
                        break;
                    }
                    if (tt.IsInterface)
                    {
                        continue;
                    }

                    IDataWriter tmp = (IDataWriter)Activator.CreateInstance(tt);
                    for (int i = 0; i < tmp.Identifier.Length; ++i)
                    {
                        if (tmp.Identifier[i] == animEncoding)
                        {
                            animWriter = tmp;
                            break;
                        }
                    }
                }
            }

            IDataWriter modelWriter = null;

            if (modelEncoding != 0 && modelEncoding != '+')
            {
                Assembly    asm   = typeof(IDataWriter).Assembly;
                Type        t     = typeof(IDataWriter);
                List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList();
                foreach (Type tt in types)
                {
                    if (modelWriter != null)
                    {
                        break;
                    }
                    if (tt.IsInterface)
                    {
                        continue;
                    }

                    IDataWriter tmp = (IDataWriter)Activator.CreateInstance(tt);
                    for (int i = 0; i < tmp.Identifier.Length; ++i)
                    {
                        if (tmp.Identifier[i] == modelEncoding)
                        {
                            modelWriter = tmp;
                            break;
                        }
                    }
                }
            }

            List <ulong> masters = track[0x9F];
            List <byte>  LODs    = new List <byte>(new byte[5] {
                0, 1, 128, 254, 255
            });
            Dictionary <ulong, ulong> replace = new Dictionary <ulong, ulong>();

            foreach (ulong masterKey in masters)
            {
                if (!map.ContainsKey(masterKey))
                {
                    continue;
                }
                STUD masterStud = new STUD(Util.OpenFile(map[masterKey], handler));
                if (masterStud.Instances == null)
                {
                    continue;
                }
                MapMaster master = (MapMaster)masterStud.Instances[0];
                if (master == null)
                {
                    continue;
                }

                string name = Util.GetString(master.Header.name.key, map, handler);
                if (string.IsNullOrWhiteSpace(name))
                {
                    name = $"Unknown{GUID.Index(master.Header.data.key):X}";
                }
                if (!mapWildcard && !(maps.Contains(name.ToUpperInvariant()) || maps.Contains($"{GUID.Index(masterKey):X}")))
                {
                    continue;
                }
                string outputPath = string.Format("{0}{1}{2}{1}{3:X}{1}", output, Path.DirectorySeparatorChar, Util.SanitizePath(name), GUID.Index(master.Header.data.key));

                if (!map.ContainsKey(master.Header.data.key))
                {
                    continue;
                }

                HashSet <ulong>                   parsed    = new HashSet <ulong>();
                Dictionary <ulong, ulong>         animList  = new Dictionary <ulong, ulong>();
                Dictionary <ulong, List <ulong> > soundData = new Dictionary <ulong, List <ulong> >();
                if (!map.ContainsKey(master.DataKey(1)))
                {
                    continue;
                }
                if (!map.ContainsKey(master.DataKey(2)))
                {
                    continue;
                }
                if (!map.ContainsKey(master.DataKey(8)))
                {
                    continue;
                }
                if (!map.ContainsKey(master.DataKey(0xB)))
                {
                    continue;
                }
                if (!map.ContainsKey(master.DataKey(0x11)))
                {
                    continue;
                }
                if (!map.ContainsKey(master.DataKey(0x10)))
                {
                    continue;
                }
                using (Stream mapStream = Util.OpenFile(map[master.DataKey(1)], handler)) {
                    Console.Out.WriteLine("Extracting map {0} with ID {1:X8}", name, GUID.Index(master.Header.data.key));
                    Map         mapData = new Map(mapStream);
                    IDataWriter owmap   = new OWMAPWriter();
                    Dictionary <ulong, List <string> >[] used = null;
                    if (!Directory.Exists(outputPath))
                    {
                        Directory.CreateDirectory(outputPath);
                    }
                    HashSet <ulong> soundDone = new HashSet <ulong>();
                    Sound.FindSoundsEx(master.Header.audio.key, soundDone, soundData, map, handler, replace, master.Header.data.key);
                    using (Stream map2Stream = Util.OpenFile(map[master.DataKey(2)], handler)) {
                        if (map2Stream != null)
                        {
                            Map map2Data = new Map(map2Stream);
                            using (Stream map8Stream = Util.OpenFile(map[master.DataKey(8)], handler)) {
                                if (map8Stream != null)
                                {
                                    Map map8Data = new Map(map8Stream);
                                    using (Stream mapBStream = Util.OpenFile(map[master.DataKey(0xB)], handler)) {
                                        if (mapBStream != null)
                                        {
                                            Map mapBData = new Map(mapBStream, true);
                                            using (Stream map11Stream = Util.OpenFile(map[master.DataKey(0x11)], handler)) {
                                                if (map11Stream != null)
                                                {
                                                    Map11 map11 = new Map11(map11Stream);
                                                    Sound.FindSoundsSTUD(map11.main, soundDone, soundData, map, handler, replace, masterKey, master.DataKey(0x11));
                                                    Sound.FindSoundsSTUD(map11.secondary, soundDone, soundData, map, handler, replace, masterKey, master.DataKey(0x11));
                                                }
                                            }

                                            mapBStream.Position = (long)(Math.Ceiling((float)mapBStream.Position / 16.0f) * 16); // Future proofing

                                            for (int i = 0; i < mapBData.STUDs.Count; ++i)
                                            {
                                                STUD stud = mapBData.STUDs[i];
                                                Sound.FindSoundsSTUD(stud, soundDone, soundData, map, handler, replace, master.DataKey(0xB), master.DataKey(0xB));
                                            }

                                            for (int i = 0; i < mapBData.Records.Length; ++i)
                                            {
                                                if (mapBData.Records[i] != null && mapBData.Records[i].GetType() != typeof(Map0B))
                                                {
                                                    continue;
                                                }
                                                Map0B mapprop = (Map0B)mapBData.Records[i];
                                                if (!map.ContainsKey(mapprop.Header.binding))
                                                {
                                                    continue;
                                                }
                                                Sound.FindSoundsEx(mapprop.Header.binding, soundDone, soundData, map, handler, replace, master.DataKey(0xB));
                                                HashSet <ulong> bindingModels = new HashSet <ulong>();
                                                Dictionary <ulong, List <ImageLayer> > bindingTextures = new Dictionary <ulong, List <ImageLayer> >();

                                                using (Stream bindingFile = Util.OpenFile(map[mapprop.Header.binding], handler)) {
                                                    STUD binding = new STUD(bindingFile, true, STUDManager.Instance, false, true);
                                                    foreach (ISTUDInstance instance in binding.Instances)
                                                    {
                                                        if (instance == null)
                                                        {
                                                            continue;
                                                        }
                                                        if (instance.Name != binding.Manager.GetName(typeof(ComplexModelRecord)))
                                                        {
                                                            continue;
                                                        }
                                                        ComplexModelRecord cmr = (ComplexModelRecord)instance;
                                                        mapprop.MaterialKey = cmr.Data.material.key;
                                                        mapprop.ModelKey    = cmr.Data.model.key;
                                                        Skin.FindAnimations(cmr.Data.animationList.key, soundData, animList, replace, parsed, map, handler, bindingModels, bindingTextures, mapprop.ModelKey);
                                                        Skin.FindAnimations(cmr.Data.secondaryAnimationList.key, soundData, animList, replace, parsed, map, handler, bindingModels, bindingTextures, mapprop.ModelKey);
                                                        break;
                                                    }
                                                }
                                                mapBData.Records[i] = mapprop;
                                            }

                                            using (Stream mapLStream = Util.OpenFile(map[master.DataKey(9)], handler)) {
                                                Map mapLData = new Map(mapLStream);
                                                using (Stream outputStream = File.Open($"{outputPath}{Util.SanitizePath(name)}{owmap.Format}", FileMode.Create, FileAccess.Write)) {
                                                    used = owmap.Write(outputStream, mapData, map2Data, map8Data, mapBData, mapLData, name, modelWriter);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    IDataWriter owmat = new OWMATWriter();
                    using (Stream map10Stream = Util.OpenFile(map[master.DataKey(0x10)], handler)) {
                        Map10 physics = new Map10(map10Stream);
                        using (Stream outputStream = File.Open($"{outputPath}physics{modelWriter.Format}", FileMode.Create, FileAccess.Write)) {
                            modelWriter.Write(physics, outputStream, new object[0]);
                        }
                    }
                    if (used != null)
                    {
                        Dictionary <ulong, List <string> > models    = used[0];
                        Dictionary <ulong, List <string> > materials = used[1];
                        Dictionary <ulong, Dictionary <ulong, List <ImageLayer> > > cache = new Dictionary <ulong, Dictionary <ulong, List <ImageLayer> > >();

                        if (!suppressModels)
                        {
                            foreach (KeyValuePair <ulong, List <string> > modelpair in models)
                            {
                                if (!map.ContainsKey(modelpair.Key))
                                {
                                    continue;
                                }
                                if (!parsed.Add(modelpair.Key))
                                {
                                    continue;
                                }
                                HashSet <string> extracted = new HashSet <string>();
                                using (Stream modelStream = Util.OpenFile(map[modelpair.Key], handler)) {
                                    Chunked mdl = new Chunked(modelStream, true);
                                    modelStream.Position = 0;
                                    if (modelEncoding != '+' && modelWriter != null)
                                    {
                                        foreach (string modelOutput in modelpair.Value)
                                        {
                                            if (!extracted.Add(modelOutput))
                                            {
                                                continue;
                                            }
                                            using (Stream outputStream = File.Open($"{outputPath}{modelOutput}", FileMode.Create, FileAccess.Write)) {
                                                if (modelWriter.Write(mdl, outputStream, LODs, new Dictionary <ulong, List <ImageLayer> >(), new object[5] {
                                                    null, null, null, null, skipCmodel
                                                }))
                                                {
                                                    if (!quiet)
                                                    {
                                                        Console.Out.WriteLine("Wrote model {0}", modelOutput);
                                                    }
                                                }
                                                else
                                                {
                                                    if (!quiet)
                                                    {
                                                        Console.Out.WriteLine("Failed to write model");
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    if (flags.RawModel)
                                    {
                                        using (Stream outputStream = File.Open($"{outputPath}{GUID.LongKey(modelpair.Key):X12}.{GUID.Type(modelpair.Key):X3}", FileMode.Create, FileAccess.Write)) {
                                            if (modelWriter.Write(mdl, outputStream, LODs, new Dictionary <ulong, List <ImageLayer> >(), new object[5] {
                                                null, null, null, null, skipCmodel
                                            }))
                                            {
                                                if (!quiet)
                                                {
                                                    Console.Out.WriteLine("Wrote raw model {0:X12}.{1:X3}", GUID.LongKey(modelpair.Key), GUID.Type(modelpair.Key));
                                                }
                                            }
                                            else
                                            {
                                                if (!quiet)
                                                {
                                                    Console.Out.WriteLine("Failed to write model");
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if (!suppressAnimations)
                        {
                            foreach (KeyValuePair <ulong, ulong> kv in animList)
                            {
                                ulong  parent     = kv.Value;
                                ulong  key        = kv.Key;
                                Stream animStream = Util.OpenFile(map[key], handler);
                                if (animStream == null)
                                {
                                    continue;
                                }

                                Animation anim = new Animation(animStream);
                                animStream.Position = 0;

                                string outpath = string.Format("{0}Animations{1}{2:X12}{1}{5}{1}{3:X12}.{4:X3}", outputPath, Path.DirectorySeparatorChar, GUID.Index(parent), GUID.LongKey(key), GUID.Type(key), anim.Header.priority);
                                if (!Directory.Exists(Path.GetDirectoryName(outpath)))
                                {
                                    Directory.CreateDirectory(Path.GetDirectoryName(outpath));
                                }
                                if (flags.RawAnimation)
                                {
                                    using (Stream outp = File.Open(outpath, FileMode.Create, FileAccess.Write)) {
                                        animStream.CopyTo(outp);
                                        if (!quiet)
                                        {
                                            Console.Out.WriteLine("Wrote raw animation {0}", outpath);
                                        }
                                    }
                                }
                                if (animEncoding != '+' && animWriter != null)
                                {
                                    outpath = string.Format("{0}Animations{1}{2:X12}{1}{5}{1}{3:X12}.{4}", outputPath, Path.DirectorySeparatorChar, GUID.Index(parent), GUID.LongKey(key), animWriter.Format, anim.Header.priority);
                                    using (Stream outp = File.Open(outpath, FileMode.Create, FileAccess.Write)) {
                                        animWriter.Write(anim, outp);
                                        if (!quiet)
                                        {
                                            Console.Out.WriteLine("Wrote animation {0}", outpath);
                                        }
                                    }
                                }
                            }
                        }

                        if (!flags.SkipSound)
                        {
                            Console.Out.WriteLine("Dumping sounds...");
                            string soundPath = $"{outputPath}Sounds{Path.DirectorySeparatorChar}";
                            if (!Directory.Exists(soundPath))
                            {
                                Directory.CreateDirectory(soundPath);
                            }

                            DumpVoice.Save(soundPath, soundData, map, handler, quiet);
                        }

                        if (!flags.SkipTextures)
                        {
                            foreach (KeyValuePair <ulong, List <string> > matpair in materials)
                            {
                                Dictionary <ulong, List <ImageLayer> > tmp = new Dictionary <ulong, List <ImageLayer> >();
                                if (cache.ContainsKey(matpair.Key))
                                {
                                    tmp = cache[matpair.Key];
                                }
                                else
                                {
                                    Skin.FindTextures(matpair.Key, tmp, new Dictionary <ulong, ulong>(), new HashSet <ulong>(), map, handler);
                                    cache.Add(matpair.Key, tmp);
                                }
                                Dictionary <string, TextureType> types = new Dictionary <string, TextureType>();
                                foreach (KeyValuePair <ulong, List <ImageLayer> > kv in tmp)
                                {
                                    ulong             materialId     = kv.Key;
                                    List <ImageLayer> sublayers      = kv.Value;
                                    HashSet <ulong>   materialParsed = new HashSet <ulong>();
                                    foreach (ImageLayer layer in sublayers)
                                    {
                                        if (!materialParsed.Add(layer.key))
                                        {
                                            continue;
                                        }
                                        KeyValuePair <string, TextureType> pair = Skin.SaveTexture(layer.key, materialId, map, handler, outputPath, quiet);
                                        if (pair.Key == null)
                                        {
                                            continue;
                                        }
                                        types.Add(pair.Key, pair.Value);
                                    }
                                }

                                foreach (string matOutput in matpair.Value)
                                {
                                    if (File.Exists($"{outputPath}{matOutput}"))
                                    {
                                        continue;
                                    }
                                    using (Stream outputStream = File.Open($"{outputPath}{matOutput}", FileMode.Create, FileAccess.Write)) {
                                        if (owmat.Write(null, outputStream, null, tmp, new object[1] {
                                            types
                                        }))
                                        {
                                            if (!quiet)
                                            {
                                                Console.Out.WriteLine("Wrote material {0}", matOutput);
                                            }
                                        }
                                        else
                                        {
                                            if (!quiet)
                                            {
                                                Console.Out.WriteLine("Failed to write material");
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }