Exemple #1
0
            public void Write(Stream output, STULib.Types.Map.Map map, STULib.Types.Map.Map detail1, STULib.Types.Map.Map detail2, STULib.Types.Map.Map entities, STULib.Types.Map.Map lights, string name, IDataWriter modelFormat, FindLogic.Combo.ComboInfo info)
            {
                if (modelFormat == null)
                {
                    modelFormat = new OWMDLWriter();
                }
                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;
                    foreach (IMapFormat t in map.Records)
                    {
                        if (t != null && t.GetType() != typeof(Map01))
                        {
                            continue;
                        }
                        size++;
                    }
                    writer.Write(size); // nr objects

                    size = 1;
                    foreach (IMapFormat t in detail1.Records)
                    {
                        if (t != null && t.GetType() != typeof(Map02))
                        {
                            continue;
                        }
                        size++;
                    }
                    foreach (IMapFormat t in detail2.Records)
                    {
                        if (t != null && t.GetType() != typeof(Map08))
                        {
                            continue;
                        }
                        size++;
                    }
                    foreach (IMapFormat t in entities.Records)
                    {
                        if (t != null && t.GetType() != typeof(MapEntity))
                        {
                            continue;
                        }
                        if (((MapEntity)t).Model == 0)
                        {
                            continue;
                        }
                        size++;
                    }
                    writer.Write(size); // nr details

                    // Extension 1.1 - Lights
                    size = 0;
                    foreach (IMapFormat t in lights.Records)
                    {
                        if (t != null && t.GetType() != typeof(Map09))
                        {
                            continue;
                        }
                        size++;
                    }
                    writer.Write(size); // nr Lights

                    foreach (IMapFormat t in map.Records)
                    {
                        if (t != null && t.GetType() != typeof(Map01))
                        {
                            continue;
                        }
                        Map01 obj = (Map01)t;
                        FindLogic.Combo.Find(info, obj.Header.Model);
                        FindLogic.Combo.ModelInfoNew modelInfo = info.Models[obj.Header.Model];
                        string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}{modelFormat.Format}";
                        writer.Write(modelFn);
                        writer.Write(obj.Header.groupCount);
                        for (int j = 0; j < obj.Header.groupCount; ++j)
                        {
                            Map01.Map01Group group = obj.Groups[j];
                            FindLogic.Combo.Find(info, group.ModelLook, null, new FindLogic.Combo.ComboContext {
                                Model = obj.Header.Model
                            });
                            string materialFn;
                            if (!info.ModelLooks.ContainsKey(group.ModelLook))
                            {
                                materialFn = ""; // encrypted
                            }
                            else
                            {
                                FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[group.ModelLook];
                                materialFn = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.owmat";
                            }

                            writer.Write(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);
                            }
                        }
                    }

                    // todo: broken?
                    writer.Write($"Models\\physics\\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);

                    foreach (IMapFormat t in detail1.Records)
                    {
                        if (t != null && t.GetType() != typeof(Map02))
                        {
                            continue;
                        }
                        Map02 obj = (Map02)t;

                        FindLogic.Combo.Find(info, obj.Header.Model);
                        FindLogic.Combo.Find(info, obj.Header.ModelLook, null, new FindLogic.Combo.ComboContext {
                            Model = obj.Header.Model
                        });

                        FindLogic.Combo.ModelInfoNew  modelInfo     = info.Models[obj.Header.Model];
                        FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[obj.Header.ModelLook];
                        string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}{modelFormat.Format}";
                        string matFn   = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.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);
                    }

                    foreach (IMapFormat t in detail2.Records)
                    {
                        if (t != null && t.GetType() != typeof(Map08))
                        {
                            continue;
                        }
                        Map08 obj = (Map08)t;

                        FindLogic.Combo.Find(info, obj.Header.Model);
                        FindLogic.Combo.Find(info, obj.Header.ModelLook, null, new FindLogic.Combo.ComboContext {
                            Model = obj.Header.Model
                        });

                        FindLogic.Combo.ModelInfoNew  modelInfo     = info.Models[obj.Header.Model];
                        FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[obj.Header.ModelLook];
                        string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}{modelFormat.Format}";
                        string matFn   = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.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);
                    }

                    foreach (IMapFormat t in entities.Records)
                    {
                        if (t != null && t.GetType() != typeof(MapEntity))
                        {
                            continue;
                        }
                        MapEntity mapEntity = (MapEntity)t;
                        if (mapEntity.Model == 0)
                        {
                            continue;
                        }

                        ulong modelLook = mapEntity.ModelLook;

                        foreach (object container in mapEntity.STUContainers)
                        {
                            ISTU realContainer = (ISTU)container;

                            foreach (Common.STUInstance instance in realContainer.Instances)
                            {
                                if (instance is STUModelComponentInstanceData modelComponentInstanceData)
                                {
                                    if (modelComponentInstanceData.Look != 0)
                                    {
                                        modelLook = modelComponentInstanceData.Look;
                                    }
                                }
                            }
                        }

                        FindLogic.Combo.Find(info, mapEntity.Model);
                        FindLogic.Combo.Find(info, modelLook, null, new FindLogic.Combo.ComboContext {
                            Model = mapEntity.Model
                        });

                        FindLogic.Combo.ModelInfoNew modelInfo = info.Models[mapEntity.Model];
                        string matFn = "";
                        if (info.ModelLooks.ContainsKey(modelLook))
                        {
                            FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[modelLook];
                            matFn = $"Models\\{modelInfo.GetName()}\\ModelLooks\\{modelLookInfo.GetNameIndex()}.owmat";
                        }
                        string modelFn = $"Models\\{modelInfo.GetName()}\\{modelInfo.GetNameIndex()}{modelFormat.Format}";

                        writer.Write(modelFn);
                        writer.Write(matFn);
                        writer.Write(mapEntity.Header.Position.x);
                        writer.Write(mapEntity.Header.Position.y);
                        writer.Write(mapEntity.Header.Position.z);
                        writer.Write(mapEntity.Header.Scale.x);
                        writer.Write(mapEntity.Header.Scale.y);
                        writer.Write(mapEntity.Header.Scale.z);
                        writer.Write(mapEntity.Header.Rotation.x);
                        writer.Write(mapEntity.Header.Rotation.y);
                        writer.Write(mapEntity.Header.Rotation.z);
                        writer.Write(mapEntity.Header.Rotation.w);
                    }

                    // Extension 1.1 - Lights
                    foreach (IMapFormat t in lights.Records)
                    {
                        if (t != null && t.GetType() != typeof(Map09))
                        {
                            continue;
                        }
                        Map09 obj = (Map09)t;
                        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);
                    }
                }
            }
Exemple #2
0
        public static Asset Excavate(ushort type, ulong guid)
        {
            Asset asset = new Asset {
                GUID = IO.GetFileName(guid),
                SerializationType = SerializationType.Unknown
            };

            using (Stream file = IO.OpenFile(guid)) {
                if (file == null)
                {
                    return(asset);
                }
                using (BinaryReader reader = new BinaryReader(file)) {
                    if (Version1.IsValidVersion(reader))
                    {
                        reader.BaseStream.Position = 0;
                        asset.SerializationType    = SerializationType.STUv1;
                        asset.STUInstances         = new HashSet <string>();
                        asset.GUIDs = new HashSet <string>();

                        reader.BaseStream.Position = 0;

                        // try and auto detect padding that is before a guid
                        int maxCount = 0;
                        for (int i = 0; i < reader.BaseStream.Length; i++)
                        {
                            byte b = reader.ReadByte();
                            if (b == 255)
                            {
                                maxCount++;
                            }
                            if (maxCount >= 8 && b != 255)
                            {
                                if (reader.BaseStream.Length - reader.BaseStream.Position > 8)
                                {
                                    reader.BaseStream.Position -= 1; // before b
                                    Common.STUGUID rawGUID = new Common.STUGUID(reader.ReadUInt64());
                                    reader.BaseStream.Position -= 7; // back to after b
                                    if (GUID.Type(rawGUID) > 1)
                                    {
                                        asset.GUIDs.Add(rawGUID.ToString());
                                    }
                                }
                            }
                            if (b != 255 && maxCount > 0)
                            {
                                maxCount = 0;
                            }
                        }
                    }
                    else if (type == 0xBC)
                    {
                        asset.SerializationType    = SerializationType.MapData;
                        asset.GUIDs                = new HashSet <string>();
                        asset.STUInstances         = new HashSet <string>();
                        reader.BaseStream.Position = 0;
                        Map map = new Map(file, uint.MaxValue);
                        foreach (ISTU stu in map.STUs)
                        {
                            asset.GUIDs = new HashSet <string>(asset.GUIDs.Concat(GetGUIDs(stu)).ToList());
                            foreach (Common.STUInstance stuInstance in stu.Instances)
                            {
                                STUAttribute attr = stuInstance?.GetType().GetCustomAttributes <STUAttribute>().FirstOrDefault();
                                if (attr == null)
                                {
                                    continue;
                                }
                                asset.STUInstances.Add(attr.Checksum.ToString("X8"));
                            }
                        }
                    }
                    else if (type == 0x6)
                    {
                        asset.SerializationType = SerializationType.Raw;

                        reader.BaseStream.Position = 0x18L;
                        ulong effectKey = reader.ReadUInt64();

                        reader.BaseStream.Position = 0;
                        Animation        animation = new Animation(reader.BaseStream);
                        HashSet <string> guids     = new HashSet <string>();
                        if (animation.Header.F08Key != 0)
                        {
                            guids.Add(IO.GetFileName(animation.Header.F08Key));
                        }
                        if (effectKey != 0)
                        {
                            guids.Add(IO.GetFileName(effectKey));
                        }

                        asset.GUIDs = guids;
                    }
                    else
                    {
                        if (Version2.IsValidVersion(reader))     // why is there no magic, blizz pls
                        {
                            reader.BaseStream.Position = 0;
                            Version2 stuVersion2 = null;
                            try {
                                stuVersion2             = new Version2(file, uint.MaxValue);
                                asset.SerializationType = SerializationType.STUv2;
                                asset.GUIDs             = new HashSet <string>();
                                asset.STUInstances      = new HashSet <string>();
                            } catch (Exception) {
                                asset.SerializationType = SerializationType.Unknown;
                            }
                            if (stuVersion2 != null)
                            {
                                asset.GUIDs = GetGUIDs(stuVersion2);
                                // broken: todo
                                // foreach (uint typeHash in stuVersion2.TypeHashes) {
                                //     asset.STUInstances.Add(typeHash.ToString("X8"));
                                // }
                                asset.JSONDump = "";
                                StringBuilder sb = new StringBuilder();

                                int i = 0;
                                foreach (Common.STUInstance stuInstance in stuVersion2.Instances.Concat(stuVersion2.HiddenInstances))
                                {
                                    STUAttribute attr = stuInstance?.GetType().GetCustomAttributes <STUAttribute>().FirstOrDefault();
                                    if (attr == null)
                                    {
                                        continue;
                                    }
                                    asset.STUInstances.Add($"{attr.Checksum:X8}");

                                    if (stuInstance.Usage != Common.InstanceUsage.Root)
                                    {
                                        continue;
                                    }
                                    if (i != 0)
                                    {
                                        sb.AppendLine();
                                    }
                                    sb.AppendLine($"{attr.Checksum:X8}:");
                                    sb.AppendLine(JsonConvert.SerializeObject(stuInstance, Formatting.Indented));
                                    i++;
                                }
                                asset.JSONDump = sb.ToString();
                            }
                        }
                    }
                }
            }
            return(asset);
        }
Exemple #3
0
        public static void Save(ICLIFlags flags, STUMap map, ulong key, string basePath)
        {
            string name = GetValidFilename(GetString(map.DisplayName)) ?? "Title Screen";

            if (GetString(map.VariantName) != null)
            {
                name = GetValidFilename(GetString(map.VariantName));
            }

            LoudLog($"Extracting map {name}\\{GUID.Index(key):X}");

            // if (map.Gamemodes != null) {
            //     foreach (Common.STUGUID gamemodeGUID in map.Gamemodes) {
            //         STUGamemode gamemode = GetInstance<STUGamemode>(gamemodeGUID);
            //     }
            // }

            // TODO: MAP11 HAS CHANGED
            // TODO: MAP10 TOO?

            string mapPath = Path.Combine(basePath, "Maps", name, GUID.Index(key).ToString("X")) + Path.DirectorySeparatorChar;

            CreateDirectoryFromFile(mapPath);

            // if (map.UnknownArray != null) {
            //     Dictionary<ulong, List<TextureInfo>> textures = new Dictionary<ulong, List<TextureInfo>>();
            //     foreach (STUMap.STU_7D6D8405 stu_7D6D8405 in map?.UnknownArray) {
            //         ISTU overrideStu = OpenSTUSafe(stu_7D6D8405.Override);
            //         STUSkinOverride @override = GetInstance<STUSkinOverride>(stu_7D6D8405.Override);
            //         textures = FindLogic.Texture.FindTextures(textures, @override.SkinImage);
            //     }
            //     SaveLogic.Texture.Save(flags, Path.Combine(mapPath, "override"), textures);
            // }

            OWMDLWriter   modelWriter = new OWMDLWriter();
            OWMap14Writer owmap       = new OWMap14Writer();

            FindLogic.Combo.ComboInfo info = new FindLogic.Combo.ComboInfo();
            LoudLog("\tFinding");
            FindLogic.Combo.Find(info, map.MapDataResource1);

            MapEnvironment?env = null;

            using (Stream data = OpenFile(map.MapDataResource1)) {
                if (data != null)
                {
                    using (BinaryReader dataReader = new BinaryReader(data)) {
                        env = dataReader.Read <MapEnvironment>();
                    }
                }
            }

            using (Stream mapStream = OpenFile(map.GetDataKey(1))) {
                STULib.Types.Map.Map mapData = new STULib.Types.Map.Map(mapStream, BuildVersion);

                using (Stream map2Stream = OpenFile(map.GetDataKey(2))) {
                    if (map2Stream == null)
                    {
                        return;
                    }
                    STULib.Types.Map.Map map2Data = new STULib.Types.Map.Map(map2Stream, BuildVersion);
                    using (Stream map8Stream = OpenFile(map.GetDataKey(8))) {
                        STULib.Types.Map.Map map8Data = new STULib.Types.Map.Map(map8Stream, BuildVersion);
                        using (Stream mapEntitiesStream = OpenFile(map.GetDataKey(0xB))) {
                            STULib.Types.Map.Map mapEntities =
                                new STULib.Types.Map.Map(mapEntitiesStream, BuildVersion, true);

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

                            for (int i = 0; i < mapEntities.Records.Length; ++i)
                            {
                                if (mapEntities.Records[i] != null && mapEntities.Records[i].GetType() != typeof(MapEntity))
                                {
                                    continue;
                                }
                                MapEntity mapEntity = (MapEntity)mapEntities.Records[i];

                                if (mapEntity == null)
                                {
                                    continue;
                                }
                                FindLogic.Combo.Find(info, mapEntity.Header.Entity);
                                STUModelComponent component =
                                    GetInstance <STUModelComponent>(mapEntity.Header.Entity);

                                if (component == null)
                                {
                                    continue;
                                }
                                mapEntity.ModelLook    = component.Look;
                                mapEntity.Model        = component.Model;
                                mapEntities.Records[i] = mapEntity;
                            }

                            using (Stream mapLStream = OpenFile(map.GetDataKey(9))) {
                                STULib.Types.Map.Map mapLData = new STULib.Types.Map.Map(mapLStream, BuildVersion);
                                using (Stream outputStream = File.Open(Path.Combine(mapPath, $"{name}.owmap"),
                                                                       FileMode.Create, FileAccess.Write)) {
                                    owmap.Write(outputStream, mapData, map2Data, map8Data, mapEntities, mapLData, name,
                                                modelWriter, info);
                                }
                            }
                        }
                    }
                }
            }

            FindLogic.Combo.Find(info, map.EffectAnnouncer);
            info.SetEffectName(map.EffectAnnouncer, "LoadAnnouncer");
            FindLogic.Combo.Find(info, map.EffectMusic);
            info.SetEffectName(map.EffectMusic, "LoadMusic");

            if (map.VoiceSet != null)
            {
                FindLogic.Combo.Find(info, map.VoiceSet);
            }

            if (env != null)
            {
                FindLogic.Combo.Find(info, env.Value.EntityDefinition);
                STUVoiceSetComponent voiceSetComponent = GetInstance <STUVoiceSetComponent>(env.Value.EntityDefinition);
                if (voiceSetComponent != null)
                {
                    FindLogic.Combo.Find(info, voiceSetComponent.VoiceSet);
                    info.SetEffectVoiceSet(map.EffectAnnouncer, voiceSetComponent.VoiceSet);
                    info.SetEffectVoiceSet(map.EffectMusic, voiceSetComponent.VoiceSet);
                }
            }

            LoudLog("\tSaving");
            Combo.Save(flags, mapPath, info);

            string soundPath       = Path.Combine(mapPath, "Sound");
            string voiceSetsPath   = Path.Combine(soundPath, "VoiceSets");
            string otherSoundsPath = Path.Combine(soundPath, "SFX");

            Combo.SaveVoiceSets(flags, voiceSetsPath, info);
            foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileInfo> sound in info.SoundFiles)
            {
                Combo.SaveSoundFile(flags, otherSoundsPath, info, sound.Key, false);
            }

            LoudLog("\tDone");
        }