示例#1
0
        /// <summary>
        /// Converts a W2RC stream to text
        /// </summary>
        /// <param name="format"></param>
        /// <param name="instream"></param>
        /// <returns></returns>
        /// <exception cref="InvalidParsingException"></exception>
        /// <exception cref="SerializationException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public string ConvertToText(ETextConvertFormat format, string infile)
        {
            using var instream = new FileStream(infile, FileMode.Open, FileAccess.Read);

            if (!_wolvenkitFileService.TryReadRed4File(instream, out var cr2w))
            {
                throw new InvalidParsingException("ConvertToText");
            }

            cr2w.MetaData.FileName = infile;

            var dto  = new RedFileDto(cr2w);
            var json = RedJsonSerializer.Serialize(dto);

            if (string.IsNullOrEmpty(json))
            {
                throw new SerializationException();
            }

            switch (format)
            {
            case ETextConvertFormat.json:
                return(json);

            case ETextConvertFormat.xml:
                throw new NotSupportedException(nameof(format));

            default:
                throw new ArgumentOutOfRangeException(nameof(format), format, null);
            }
        }
示例#2
0
        private bool DumpAppPackage(CR2WFile cr2w, Stream appStream, string outfile)
        {
            var blob = cr2w.RootChunk as appearanceAppearanceResource;

            var datas = new List <RedFileDto>();

            foreach (var appearance in blob.Appearances)
            {
                if (appearance.Chunk.CompiledData.Buffer.MemSize > 0)
                {
                    var packageStream = new MemoryStream();
                    packageStream.Write(appearance.Chunk.CompiledData.Buffer.GetBytes());

                    var package = new CompiledPackage(_hashService);
                    packageStream.Seek(0, SeekOrigin.Begin);
                    package.Read(new BinaryReader(packageStream));
                    datas.Add(new RedFileDto(cr2w));
                }
            }
            if (datas.Count > 1)
            {
                var data = RedJsonSerializer.Serialize(datas);
                File.WriteAllText(outfile, data);
                return(true);
            }
            return(false);
        }
示例#3
0
        private bool DumpEntPackage(CR2WFile cr2w, Stream entStream, string outfile)
        {
            var blob = cr2w.RootChunk as entEntityTemplate;

            if (blob.CompiledData.Buffer.MemSize > 0)
            {
                var packageStream = new MemoryStream();
                packageStream.Write(blob.CompiledData.Buffer.GetBytes());

                var package = new CompiledPackage(_hashService);
                packageStream.Seek(0, SeekOrigin.Begin);
                package.Read(new BinaryReader(packageStream));
                var data = RedJsonSerializer.Serialize(new RedFileDto(cr2w));
                File.WriteAllText(outfile, data);
                return(true);
            }
            return(false);
        }
        private static void Test_Extension(string extension)
        {
            var parsers = _host.Services.GetRequiredService <Red4ParserService>();

            var resultDir = Path.Combine(Environment.CurrentDirectory, s_testResultsDirectory);

            Directory.CreateDirectory(resultDir);
            foreach (var file in Directory.GetFiles(resultDir))
            {
                File.Delete(file);
            }

            var results = new ConcurrentBag <ArchiveTestResult>();
            var files   = s_groupedFiles[extension].ToList();

#if IS_PARALLEL
            Parallel.ForEach(files, file =>
#else
            foreach (var file in files)
#endif
            {
                var hash    = file.Key;
                var archive = file.Archive as Archive;
                ArgumentNullException.ThrowIfNull(archive);

                try
                {
                    #region convert to json
                    using var originalMemoryStream = new MemoryStream();
                    ModTools.ExtractSingleToStream(archive, hash, originalMemoryStream);
                    if (!parsers.TryReadRed4File(originalMemoryStream, out var originalFile))
                    {
#if IS_PARALLEL
                        return;
#else
                        continue;
#endif
                    }

                    var dto  = new RedFileDto(originalFile);
                    var json = RedJsonSerializer.Serialize(dto);
                    if (string.IsNullOrEmpty(json))
                    {
                        throw new SerializationException();
                    }

                    #endregion

                    #region convert back from json

                    var newdto = RedJsonSerializer.Deserialize <RedFileDto>(json);
                    if (newdto == null)
                    {
                        throw new SerializationException();
                    }

                    var newFile = newdto.Data;

                    #endregion

                    #region compare

                    // old file
                    var header        = originalFile.MetaData;
                    var objectsend    = (int)header.ObjectsEnd;
                    var originalBytes = originalMemoryStream.ToByteArray().Take(objectsend);

                    // write the new file
                    using var newMemoryStream = new MemoryStream();
                    using var writer          = new CR2WWriter(newMemoryStream);
                    writer.WriteFile(newFile);

                    // hack to compare buffers
                    var newBytes = newMemoryStream.ToByteArray();

                    newMemoryStream.Seek(0, SeekOrigin.Begin);
                    var dbg = parsers.ReadRed4File(newMemoryStream);
                    //var newExportStartOffset = (int)dbg.Chunks.FirstOrDefault().GetOffset();



                    //                    var originalExportStartOffset = (int)originalFile.Chunks.FirstOrDefault().GetOffset();
                    //                    if (!originalBytes.Skip(160).SequenceEqual(newBytes.Skip(160)))
                    //                    {
                    //                        // check again skipping the tables
                    //                        if (originalExportStartOffset == newExportStartOffset)
                    //                        {
                    //                            if (!originalBytes.Skip(originalExportStartOffset).SequenceEqual(newBytes.Skip(newExportStartOffset)))
                    //                            {
                    //#if WRITE
                    //                                File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.o.bin"), originalBytes.ToArray());
                    //                                File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.bin"), newBytes.ToArray());
                    //#endif
                    //                                throw new SerializationException("Exports not equal");
                    //                            }
                    //                            else
                    //                            {

                    //                            }
                    //                        }
                    //                        else
                    //                        {
                    //#if WRITE
                    //                            File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.o.bin"), originalBytes.ToArray());
                    //                            File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.bin"), newBytes.ToArray());
                    //#endif
                    //                            throw new SerializationException("Header not equal");
                    //                        }



                    //                    }
                    //                    else
                    //                    {

                    //                    }

                    #endregion

                    results.Add(new ArchiveTestResult()
                    {
                        ArchiveName = archive.Name,
                        Hash        = hash.ToString(),
                        Success     = true
                    });
                }
                catch (Exception e)
                {
                    Console.WriteLine($"{hash} - {e.Message} - {e.StackTrace}");
                    results.Add(new ArchiveTestResult()
                    {
                        ArchiveName   = archive.Name,
                        Hash          = hash.ToString(),
                        Success       = false,
                        ExceptionType = e.GetType(),
                        Message       = $"{e.Message}"
                    });
                }
#if IS_PARALLEL
            });
示例#5
0
        private void ParseMaterials(CR2WFile cr2w, Stream meshStream, FileInfo outfile, List <Archive> archives, string matRepo, EUncookExtension eUncookExtension = EUncookExtension.dds)
        {
            var primaryDependencies = new List <string>();

            var materialEntryNames = new List <string>();
            var materialEntries    = new List <CMaterialInstance>();

            GetMateriaEntries(cr2w, meshStream, ref primaryDependencies, ref materialEntryNames, ref materialEntries, archives);

            var mlSetupNames = new List <string>();

            var mlTemplateNames = new List <string>();

            var HairProfileNames = new List <string>();

            var TexturesList = new List <string>();

            var exportArgs =
                new GlobalExportArgs().Register(
                    new XbmExportArgs()
            {
                UncookExtension = eUncookExtension
            },
                    new MlmaskExportArgs()
            {
                UncookExtension = eUncookExtension.ToMlmaskUncookExtension()
            }
                    );

            for (var i = 0; i < primaryDependencies.Count; i++)
            {
                if (Path.GetExtension(primaryDependencies[i]) == ".xbm")
                {
                    if (!TexturesList.Contains(primaryDependencies[i]))
                    {
                        TexturesList.Add(primaryDependencies[i]);
                    }

                    var hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]);
                    foreach (var ar in archives)
                    {
                        if (ar.Files.ContainsKey(hash))
                        {
                            if (!File.Exists(Path.Combine(matRepo, Path.ChangeExtension(primaryDependencies[i], "." + exportArgs.Get <XbmExportArgs>().UncookExtension.ToString()))))
                            {
                                if (Directory.Exists(matRepo))
                                {
                                    UncookSingle(ar, hash, new DirectoryInfo(matRepo), exportArgs);
                                }
                            }
                            break;
                        }
                    }
                }
                if (Path.GetExtension(primaryDependencies[i]) == ".mlmask")
                {
                    if (!TexturesList.Contains(primaryDependencies[i]))
                    {
                        TexturesList.Add(primaryDependencies[i]);
                    }

                    var hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]);
                    foreach (var ar in archives)
                    {
                        if (ar.Files.ContainsKey(hash))
                        {
                            if (!File.Exists(Path.Combine(matRepo, primaryDependencies[i].Replace(".mlmask", $"_0.{exportArgs.Get<XbmExportArgs>().UncookExtension.ToString()}"))))
                            {
                                if (Directory.Exists(matRepo))
                                {
                                    UncookSingle(ar, hash, new DirectoryInfo(matRepo), exportArgs);
                                }
                            }
                            break;
                        }
                    }
                }

                if (Path.GetExtension(primaryDependencies[i]) == ".hp")
                {
                    if (!HairProfileNames.Contains(primaryDependencies[i]))
                    {
                        var hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]);
                        foreach (var ar in archives)
                        {
                            if (ar.Files.ContainsKey(hash))
                            {
                                var ms = new MemoryStream();
                                ExtractSingleToStream(ar, hash, ms);
                                ms.Seek(0, SeekOrigin.Begin);

                                HairProfileNames.Add(primaryDependencies[i]);
                                var path = Path.Combine(matRepo, Path.ChangeExtension(primaryDependencies[i], ".hp.json"));
                                if (!File.Exists(path))
                                {
                                    if (!new FileInfo(path).Directory.Exists)
                                    {
                                        Directory.CreateDirectory(new FileInfo(path).Directory.FullName);
                                    }
                                    var hp = _wolvenkitFileService.ReadRed4File(ms);
                                    //hp.FileName = primaryDependencies[i];
                                    var dto = new RedFileDto(hp);
                                    var doc = RedJsonSerializer.Serialize(dto);
                                    File.WriteAllText(path, doc);
                                }
                                break;
                            }
                        }
                    }
                }

                if (Path.GetExtension(primaryDependencies[i]) == ".mlsetup")
                {
                    if (!mlSetupNames.Contains(primaryDependencies[i]))
                    {
                        var hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]);
                        foreach (var ar in archives)
                        {
                            if (ar.Files.ContainsKey(hash))
                            {
                                var ms = new MemoryStream();
                                ExtractSingleToStream(ar, hash, ms);
                                ms.Seek(0, SeekOrigin.Begin);

                                var isResource = _wolvenkitFileService.IsCR2WFile(ms);
                                if (!isResource)
                                {
                                    throw new InvalidParsingException("not a cr2w file");
                                }
                                using var reader = new CR2WReader(ms);
                                _ = reader.ReadFile(out var mls, false);

                                mlSetupNames.Add(primaryDependencies[i]);

                                var path = Path.Combine(matRepo, Path.ChangeExtension(primaryDependencies[i], ".mlsetup.json"));
                                if (!File.Exists(path))
                                {
                                    if (!new FileInfo(path).Directory.Exists)
                                    {
                                        Directory.CreateDirectory(new FileInfo(path).Directory.FullName);
                                    }
                                    //mls.FileName = primaryDependencies[i];
                                    var dto = new RedFileDto(mls);
                                    var doc = RedJsonSerializer.Serialize(dto);
                                    File.WriteAllText(path, doc);
                                }

                                for (var e = 0; e < reader.ImportsList.Count; e++)
                                {
                                    if (Path.GetExtension(reader.ImportsList[e].DepotPath) == ".xbm")
                                    {
                                        if (!TexturesList.Contains(reader.ImportsList[e].DepotPath))
                                        {
                                            TexturesList.Add(reader.ImportsList[e].DepotPath);
                                        }

                                        var hash1 = FNV1A64HashAlgorithm.HashString(reader.ImportsList[e].DepotPath);
                                        foreach (var arr in archives)
                                        {
                                            if (arr.Files.ContainsKey(hash1))
                                            {
                                                if (!File.Exists(Path.Combine(matRepo, Path.ChangeExtension(reader.ImportsList[e].DepotPath, "." + exportArgs.Get <XbmExportArgs>().UncookExtension.ToString()))))
                                                {
                                                    if (Directory.Exists(matRepo))
                                                    {
                                                        UncookSingle(arr, hash1, new DirectoryInfo(matRepo), exportArgs);
                                                    }
                                                }
                                                break;
                                            }
                                        }
                                    }
                                    if (Path.GetExtension(reader.ImportsList[e].DepotPath) == ".mltemplate")
                                    {
                                        if (!mlTemplateNames.Contains(reader.ImportsList[e].DepotPath))
                                        {
                                            var hash2 = FNV1A64HashAlgorithm.HashString(reader.ImportsList[e].DepotPath);
                                            foreach (var arr in archives)
                                            {
                                                if (arr.Files.ContainsKey(hash2))
                                                {
                                                    var mss = new MemoryStream();
                                                    ExtractSingleToStream(arr, hash2, mss);
                                                    mss.Seek(0, SeekOrigin.Begin);

                                                    var mlt = _wolvenkitFileService.ReadRed4File(mss);
                                                    mlTemplateNames.Add(reader.ImportsList[e].DepotPath);

                                                    var path1 = Path.Combine(matRepo, Path.ChangeExtension(reader.ImportsList[e].DepotPath, ".mltemplate.json"));
                                                    if (!File.Exists(path1))
                                                    {
                                                        if (!new FileInfo(path1).Directory.Exists)
                                                        {
                                                            Directory.CreateDirectory(new FileInfo(path1).Directory.FullName);
                                                        }
                                                        //mlt.FileName = mls.Imports[e].DepotPath;
                                                        var dto1 = new RedFileDto(mlt);
                                                        var doc1 = RedJsonSerializer.Serialize(dto1);
                                                        File.WriteAllText(path1, doc1);
                                                    }

                                                    for (var eye = 0; eye < reader.ImportsList.Count; eye++)
                                                    {
                                                        if (!TexturesList.Contains(reader.ImportsList[eye].DepotPath))
                                                        {
                                                            TexturesList.Add(reader.ImportsList[eye].DepotPath);
                                                        }

                                                        var hash3 = FNV1A64HashAlgorithm.HashString(reader.ImportsList[eye].DepotPath);
                                                        foreach (var arrr in archives)
                                                        {
                                                            if (arrr.Files.ContainsKey(hash3))
                                                            {
                                                                if (!File.Exists(Path.Combine(matRepo, Path.ChangeExtension(reader.ImportsList[eye].DepotPath, "." + exportArgs.Get <XbmExportArgs>().UncookExtension.ToString()))))
                                                                {
                                                                    if (Directory.Exists(matRepo))
                                                                    {
                                                                        UncookSingle(arrr, hash3, new DirectoryInfo(matRepo), exportArgs);
                                                                    }
                                                                }
                                                                break;
                                                            }
                                                        }
                                                    }
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
            }



            var RawMaterials = new List <RawMaterial>();
            var usedMts      = new Dictionary <string, CMaterialTemplate>();

            for (var i = 0; i < materialEntries.Count; i++)
            {
                RawMaterials.Add(ContainRawMaterial(materialEntries[i], materialEntryNames[i], archives, ref usedMts));
            }

            var matTemplates = new List <RawMaterial>();
            {
                var keys = usedMts.Keys.ToList();
                for (var i = 0; i < keys.Count; i++)
                {
                    var rawMat = new RawMaterial
                    {
                        Name = keys[i],
                        Data = new Dictionary <string, object>()
                    };

                    foreach (var item in usedMts[keys[i]].Parameters[2])
                    {
                        rawMat.Data.Add(item.Chunk.ParameterName, GetSerializableValue(item.Chunk));
                    }

                    matTemplates.Add(rawMat);
                }
            }

            var matData = new MatData
            {
                MaterialRepo      = matRepo,
                Materials         = RawMaterials,
                TexturesList      = TexturesList,
                MaterialTemplates = matTemplates
            };

            var str = RedJsonSerializer.Serialize(matData);

            File.WriteAllText(Path.ChangeExtension(outfile.FullName, ".Material.json"), str);
        }
示例#6
0
        public bool WriteMatToMesh(ref CR2WFile cr2w, string _matData, List <Archive> archives)
        {
            if (cr2w == null || cr2w.RootChunk is not CMesh cMesh || cMesh.RenderResourceBlob.Chunk is not rendRenderMeshBlob)
            {
                return(false);
            }

            var matData = RedJsonSerializer.Deserialize <MatData>(_matData);

            var materialbuffer = new MemoryStream();
            var offsets        = new List <uint>();
            var sizes          = new List <uint>();
            var names          = new List <string>();

            if (matData.Materials.Count < 1)
            {
                return(false);
            }

            var mts = new Dictionary <string, CMaterialTemplate>();

            for (var i = 0; i < matData.Materials.Count; i++)
            {
                var mat = matData.Materials[i];
                names.Add(mat.Name);
                var mi = new CR2WFile();
                {
                    var chunk = RedTypeManager.Create <CMaterialInstance>();
                    chunk.CookingPlatform = Enums.ECookingPlatform.PLATFORM_PC;
                    chunk.EnableMask      = true;
                    chunk.ResourceVersion = 4;
                    chunk.BaseMaterial    = new CResourceReference <IMaterial>()
                    {
                        DepotPath = mat.BaseMaterial
                    };
                    chunk.Values = new CArray <CKeyValuePair>();

                    CMaterialTemplate mt = null;
                    if (mts.ContainsKey(mat.MaterialTemplate))
                    {
                        mt = mts[mat.MaterialTemplate];
                    }
                    else
                    {
                        var hash = FNV1A64HashAlgorithm.HashString(mat.MaterialTemplate);
                        foreach (var ar in archives)
                        {
                            if (ar.Files.ContainsKey(hash))
                            {
                                var ms = new MemoryStream();
                                ExtractSingleToStream(ar, hash, ms);
                                ms.Seek(0, SeekOrigin.Begin);

                                mt = (CMaterialTemplate)_wolvenkitFileService.ReadRed4File(ms).RootChunk;
                                mts.Add(mat.MaterialTemplate, mt);
                                break;
                            }
                        }
                    }

                    var fakeMaterialInstance = new CMaterialInstance()
                    {
                        BaseMaterial = new CResourceReference <IMaterial> {
                            DepotPath = mat.BaseMaterial
                        },
                        Values = new CArray <CKeyValuePair>()
                    };
                    var orgChain = GetMaterialChain(fakeMaterialInstance, archives, ref mts);

                    if (mt != null)
                    {
                        foreach (var(key, value) in matData.Materials[i].Data)
                        {
                            var found = false;

                            for (var k = 0; k < mt.Parameters[2].Count; k++)
                            {
                                var refer = mt.Parameters[2][k].Chunk;

                                if (refer.ParameterName == key)
                                {
                                    found = true;

                                    object convValue = GetMaterialParameterValue(refer.GetType(), value);
                                    if (orgChain.valueDict.ContainsKey(refer.ParameterName) && !Equals(orgChain.valueDict[refer.ParameterName], convValue))
                                    {
                                        chunk.Values.Add(new CKeyValuePair(refer.ParameterName, (IRedType)convValue));
                                    }
                                }
                            }

                            if (!found)
                            {
                                var wrapper = ((JsonElement)value).Deserialize <MaterialValueWrapper>();
                                var(type, _) = RedReflection.GetCSTypeFromRedType(wrapper.Type);

                                var nValue = ((JsonElement)wrapper.Value).Deserialize(type, RedJsonSerializer.Options);
                                chunk.Values.Add(new CKeyValuePair(key, (IRedType)nValue));
                            }
                        }
                    }

                    mi.RootChunk = chunk;
                }

                offsets.Add((uint)materialbuffer.Position);

                using var m      = new MemoryStream();
                using var writer = new CR2WWriter(m);
                writer.WriteFile(mi);

                materialbuffer.Write(m.ToArray(), 0, (int)m.Length);
                sizes.Add((uint)m.Length);
            }

            var blob = (CMesh)cr2w.RootChunk;

            // remove existing data
            while (blob.MaterialEntries.Count != 0)
            {
                blob.MaterialEntries.Remove(blob.MaterialEntries[^ 1]);
示例#7
0
        /// <summary>
        /// Converts a json string to W2RC file
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        /// <exception cref="InvalidParsingException"></exception>
        public static CR2WFile ConvertFromJson(string json)
        {
            var dto = RedJsonSerializer.Deserialize <RedFileDto>(json);

            return(dto.Data);
        }