예제 #1
0
        public Edge(string gamePath)
        {
            var versionInfo = FileVersionInfo.GetVersionInfo(GamePath = gamePath);

            EngineVersion = new Version(versionInfo.FileMajorPart, versionInfo.FileMinorPart,
                                        versionInfo.FileBuildPart, versionInfo.FilePrivatePart);
            GameDirectory = Path.GetDirectoryName(GamePath);
            Directory.CreateDirectory(ModsDirectory = Path.Combine(GameDirectory, "mods"));
            AudioDirectory    = Path.Combine(GameDirectory, "audio");
            LevelsDirectory   = Path.Combine(GameDirectory, "levels");
            ModelsDirectory   = Path.Combine(GameDirectory, "models");
            TexturesDirectory = Path.Combine(GameDirectory, "textures");
            disabledEdgeMods  = new StringSetFile(Path.Combine(ModsDirectory, "disabledEdgeMods.txt"));
            ModifiedFiles     = new StringSetFile(Path.Combine(ModsDirectory, "modifiedFiles.txt"));
            if (IsCracked)
            {
                SteamOtl = new SteamOtl(Path.Combine(GameDirectory, "steam_otl.ini"));
            }
            RefreshEdgeMods();
            foreach (var file in Directory.EnumerateFiles(TexturesDirectory, "*.etx"))
            {
                try
                {
                    ExFormat = ETX.FromFile(file) is ETX1804;
                    break;
                }
                catch { }
            }
        }
예제 #2
0
        public void Draw(string path, Matrix3D?parentMatrix = null)
        {
            ESO eso;

            do
            {
                var matrix = GetMatrix(eso = ESO.FromFile(path));
                if (parentMatrix.HasValue)
                {
                    matrix *= parentMatrix.Value;
                }
                foreach (var model in eso.Models)
                {
                    BitmapImage image;
                    var         material = new DiffuseMaterial(Brushes.White);
                    var         geom     = new MeshGeometry3D
                    {
                        Positions = new Point3DCollection(model.Vertices.Select(AssetHelper.ConvertVertex)),
                        Normals   = new Vector3DCollection(model.Normals.Select(AssetHelper.ConvertVector))
                    };
                    var ema = EMA.FromFile(Path.Combine(MainWindow.Edge.ModelsDirectory,
                                                        model.MaterialAsset + ".ema"));
                    if (ema.Textures.Length > 0 && model.HasTexCoords)
                    {
                        geom.TextureCoordinates = new PointCollection(model.TexCoords.Select(ConvertTexCoord));
                        var etx = ETX.FromFile(Path.Combine(MainWindow.Edge.TexturesDirectory,
                                                            ema.Textures[0].Asset + ".etx"));
                        image = etx.GetBitmap().GetBitmapImage();
                        Viewport2DVisual3D.SetIsVisualHostMaterial(material, true);
                    }
                    else
                    {
                        image = new BitmapImage();
                    }
                    if (!parentMatrix.HasValue && model.HasColors)
                    {
                        TaskDialog.Show(this, Localization.Warning, Localization.ModelColorWarning,
                                        Localization.ModelColorWarningDetails, TaskDialogType.Warning);
                    }
                    for (var i = model.Vertices.Count - 1; i >= 0; i--)
                    {
                        geom.TriangleIndices.Add(i);
                    }
                    var transform = new MatrixTransform3D(matrix);
                    Model.Children.Add(new Viewport2DVisual3D
                    {
                        Geometry = geom, Material = material,
                        Visual   = new Image {
                            Source = image
                        }, Transform = transform
                    });
                    if (!DebugMode)
                    {
                        continue;
                    }
                    var lines = new ScreenSpaceLines3D {
                        Color = Colors.Red, Transform = transform
                    };
                    Model.Children.Add(lines);
                    var k = 0;
                    while (k < model.Vertices.Count)
                    {
                        lines.Points.Add(AssetHelper.ConvertVertex(model.Vertices[k]));
                        lines.Points.Add(AssetHelper.ConvertVertex(model.Vertices[k + 1]));
                        lines.Points.Add(AssetHelper.ConvertVertex(model.Vertices[k + 1]));
                        lines.Points.Add(AssetHelper.ConvertVertex(model.Vertices[k + 2]));
                        lines.Points.Add(AssetHelper.ConvertVertex(model.Vertices[k + 2]));
                        lines.Points.Add(AssetHelper.ConvertVertex(model.Vertices[k]));
                        k += 3;
                    }
                }
                if (!DrawChildModels)
                {
                    return;
                }
                if (!eso.Header.NodeChild.IsZero())
                {
                    Draw(Path.Combine(Path.GetDirectoryName(path), eso.Header.NodeChild + ".eso"), matrix);
                }
                path = Path.Combine(Path.GetDirectoryName(path), eso.Header.NodeSibling + ".eso");
            }while (!eso.Header.NodeSibling.IsZero());
        }
예제 #3
0
        public void Install(HashSet <string> allModifiedFiles, StringBuilder error,
                            Dictionary <string, EdgeMod> conflicts, ProgressCallback callback = null)
        {
            if (MinEngineVersion != null && parent.EngineVersion < MinEngineVersion ||
                MaxEngineVersion != null && parent.EngineVersion > MaxEngineVersion)
            {
                error.AppendLine(string.Format(Localization.EdgeModErrorEngineNotSupported, ID, parent.EngineVersion));
                return;
            }
            if (!Dependency.IsSubsetOf(from edgeMod in parent.EdgeMods where edgeMod.Enabled select edgeMod.ID))
            {
                error.AppendLine(string.Format(Localization.EdgeModErrorEngineDependenciesNotInstalled, ID));
                return;
            }
            if (conflicts.ContainsKey(ID))
            {
                error.AppendLine(string.Format(Localization.EdgeModErrorConflict, conflicts[ID].ID, ID));
                return;
            }
            conflicts.Add(ID, this);    // self conflict
            foreach (var conflict in Conflicts.Where(conflict => !conflicts.ContainsKey(conflict)))
            {
                conflicts.Add(conflict, this);
            }
            using (var extractor = new SevenZipExtractor(FilePath))
            {
                try
                {
                    extractor.ExtractFiles(e =>
                    {
                        if (e.Reason == ExtractFileCallbackReason.Start)
                        {
                            callback?.Invoke(ID + '\\' + e.ArchiveFileInfo.FileName);
                        }
                        var path = Path.Combine(parent.GameDirectory, e.ArchiveFileInfo.FileName);
                        try
                        {
                            if (e.ArchiveFileInfo.IsDirectory)
                            {
                                return;                                         // ignore directories
                            }
                            var lowered = e.ArchiveFileInfo.FileName.ToLower(); // and files that has been processed
                            if (lowered == "mod.xml" || lowered == "description.txt" ||
                                lowered == "levels\\mapping.xsl" || lowered == "config\\settings_readme.txt" ||
                                lowered == "config\\settings_template_do_not_modify.ini" ||
                                lowered.StartsWith("mods\\", true, CultureInfo.InvariantCulture) ||
                                lowered.EndsWith(".bak", true, CultureInfo.InvariantCulture))
                            {
                                return;
                            }
                            var isSfx = lowered.StartsWith("sfx\\", true, CultureInfo.InvariantCulture);
                            if (isSfx)
                            {
                                path = Path.Combine(parent.BeginSfx(), e.ArchiveFileInfo.FileName);
                            }
                            Directory.CreateDirectory(Path.GetDirectoryName(path));
                            var fileInfo = new FileInfo(path);
                            switch (e.Reason)
                            {
                            case ExtractFileCallbackReason.Start:
                                if (isSfx)
                                {
                                    File.Delete(path);
                                    e.ExtractToFile = path;
                                }
                                else
                                {
                                    if (Type == EdgeModType.Level && fileInfo.Exists &&
                                        !allModifiedFiles.Contains(e.ArchiveFileInfo.FileName.ToLower()))
                                    {
                                        throw new IOException(Localization.EdgeModErrorLevelOverwriteForbidden);
                                    }
                                    if (!fileInfo.Exists || (ulong)fileInfo.Length != e.ArchiveFileInfo.Size ||
                                        Math.Abs(fileInfo.LastWriteTime.Ticks
                                                 - e.ArchiveFileInfo.LastWriteTime.Ticks)
                                        > new TimeSpan(0, 0, 1).Ticks)      // fast check
                                    {
                                        parent.CreateCopy(allModifiedFiles, lowered);
                                        File.Delete(path);
                                        e.ExtractToFile = path;
                                    }
                                    parent.ModifiedFiles.Add(lowered);
                                    allModifiedFiles.Add(lowered);
                                }
                                break;

                            case ExtractFileCallbackReason.Done:
                                if (e.ExtractToFile != null)
                                {
                                    fileInfo.LastWriteTime = e.ArchiveFileInfo.LastWriteTime;
                                    if (!e.ExtractToFile.EndsWith(".etx", StringComparison.Ordinal))
                                    {
                                        return;
                                    }
                                    try
                                    {
                                        var etx = ETX.FromFile(e.ExtractToFile);
                                        if (parent.ExFormat && etx is ETX1803)
                                        {
                                            ETX1804.CreateFromImage(etx.GetBitmap(), etx.AssetHeader)
                                            .Save(e.ExtractToFile);
                                        }
                                        else if (!parent.ExFormat && etx is ETX1804)
                                        {
                                            ETX1803.CreateFromImage(etx.GetBitmap(), etx.AssetHeader)
                                            .Save(e.ExtractToFile);
                                        }
                                    }
                                    catch { }
                                }
                                break;

                            case ExtractFileCallbackReason.Failure:
                                throw e.Exception;
                            }
                        }
                        catch (Exception exc)
                        {
                            error.AppendFormat(Localization.EdgeModFileError, ID, path, exc.Message);
                        }
                    });
                }
                catch (Exception exc)
                {
                    error.AppendFormat(Localization.EdgeModError, ID, exc.Message);
                }
            }
            try
            {
                if (Xsl == null)
                {
                    return;
                }
                var mappingPath = Path.Combine(parent.GameDirectory, "levels\\mapping.xml");
                parent.CreateCopy(allModifiedFiles, "levels\\mapping.xml");
                var transform = new XslCompiledTransform(true);
                transform.Load(XmlReader.Create(new StringReader(parent.IsCracked ? XslCracked : Xsl)),
                               new XsltSettings(true, true), new XmlUrlResolver());
                var writer = new StringWriter();
                transform.Transform(XmlReader.Create(new StringReader(File.ReadAllText(
                                                                          File.Exists(mappingPath) ? mappingPath : (mappingPath + ".bak")))), null,
                                    XmlWriter.Create(writer, new XmlWriterSettings {
                    Indent = true
                }), new XmlUrlResolver());
                File.WriteAllText(mappingPath, writer.ToString());
                parent.ModifiedFiles.Add("levels\\mapping.xml");
                allModifiedFiles.Add("levels\\mapping.xml");
            }
            catch (Exception exc)
            {
                error.AppendFormat(Localization.EdgeModErrorXsl, exc.Message);
            }
        }
예제 #4
0
파일: Compiler.cs 프로젝트: bundie1990/EDGE
        public static Tuple <Exception, string, List <FileEntry> > Compile(bool exFormat, string file,
                                                                           string directory = null)
        {
            var list     = new List <FileEntry>();
            var fileName = Path.GetFileNameWithoutExtension(file);

            if (string.IsNullOrWhiteSpace(directory))
            {
                directory = Path.GetDirectoryName(file);
            }
            string inputPath  = Path.Combine(Path.GetDirectoryName(file), fileName),
                   outputPath = Path.Combine(directory, fileName);

            Warning.Start();
            try
            {
                switch ((Path.GetExtension(file) ?? string.Empty).ToLowerInvariant())
                {
                case ".bin":
                    switch (fileName.ToLowerInvariant())
                    {
                    case "cos":
                        var array = new short[181];
                        using (var stream = File.OpenRead(file))
                            using (var reader = new BinaryReader(stream))
                                for (var i = 0; i <= 180; i++)
                                {
                                    array[i] = reader.ReadInt16();
                                }
                        File.WriteAllText(outputPath += ".txt",
                                          string.Join(Environment.NewLine, array.Select(value => value / 256.0)));
                        list.Add(new FileEntry(outputPath, "cos.txt"));
                        break;

                    case "font":
                        DecompileFont(file, ref outputPath);
                        list.Add(new FileEntry(outputPath, "font.xml"));
                        break;

                    default:
                    {
                        var index = 0;
                        foreach (var path in Level.CreateFromCompiled(file).Decompile(outputPath))
                        {
                            list.Add(new FileEntry(path, index == 0 ? "level.xml"
                                        : index == 1 ? "level.png" : "level.z.png"));
                            index++;
                        }
                        break;
                    }
                    }
                    break;

                case ".xml":
                    var root = XHelper.Load(file).Elements().First();
                    switch (root.Name.LocalName.ToLowerInvariant())
                    {
                    case "level":
                    {
                        var index = 0;
                        foreach (var path in Level.CreateFromDecompiled(inputPath)
                                 .Compile(outputPath + ".bin"))
                        {
                            list.Add(new FileEntry(path, index == 0 ? "level.bin" : "model.eso"));
                            index++;
                        }
                        break;
                    }

                    case "animation":
                        AssetHelper.ParseEan(root, fileName).Save(outputPath = Path.Combine(directory,
                                                                                            AssetUtil.CrcFullName(fileName, "models") + ".ean"));
                        list.Add(new FileEntry(outputPath, "animation.ean"));
                        break;

                    case "material":
                    {
                        string name;
                        Helper.AnalyzeFileName(out name, out outputPath, fileName);
                        var ema = AssetHelper.ParseEma(root, name);
                        ema.Save(Path.Combine(directory, outputPath += ".ema"));
                        list.Add(new FileEntry(outputPath, "material.ema"));
                        break;
                    }

                    case "models":
                    {
                        string name;
                        Helper.AnalyzeFileName(out name, out outputPath, fileName);
                        var eso = AssetHelper.ParseEso(root, name);
                        eso.Save(Path.Combine(directory, outputPath += ".eso"));
                        list.Add(new FileEntry(outputPath, "model.eso"));
                        break;
                    }

                    case "font":
                    {
                        CompileFont(inputPath, out outputPath, root);
                        list.Add(new FileEntry(outputPath, "font.bin"));
                        break;
                    }
                    }
                    break;

                case ".loc":
                    LOC.FromFile(file).SaveXls(outputPath += ".xls");
                    list.Add(new FileEntry(outputPath, "text.xls"));
                    break;

                case ".xls":
                    LocHelper.FromXls(file).Save(outputPath += ".loc");
                    list.Add(new FileEntry(outputPath, "text.loc"));
                    break;

                case ".etx":
                    var etx = ETX.FromFile(file);
                    etx.GetBitmap().Save(outputPath = Path.Combine(directory, etx.AssetHeader.Name + ".png"));
                    list.Add(new FileEntry(outputPath, "texture.png"));
                    break;

                case ".png":
                {
                    var name = AssetUtil.CrcFullName(fileName, "textures") + ".etx";
                    (exFormat ? (ETX)ETX1804.CreateFromImage(file) : ETX1803.CreateFromImage(file))
                    .Save(outputPath = Path.Combine(directory, name));
                    list.Add(new FileEntry(outputPath, "texture.etx"));
                    break;
                }

                case ".ean":
                    var ean = EAN.FromFile(file);
                    File.WriteAllText(outputPath = Path.Combine(directory,
                                                                Helper.GetDecompiledFileName(fileName, ean) + ".xml"),
                                      AssetHelper.GetEanElement(ean).ToString());
                    list.Add(new FileEntry(outputPath, "animation.xml"));
                    break;

                case ".ema":
                {
                    var ema = EMA.FromFile(file);
                    File.WriteAllText(outputPath = Path.Combine(directory,
                                                                Helper.GetDecompiledFileName(fileName, ema) + ".xml"),
                                      AssetHelper.GetEmaElement(ema).ToString());
                    list.Add(new FileEntry(outputPath, "material.xml"));
                    break;
                }

                case ".eso":
                {
                    var eso = ESO.FromFile(file);
                    File.WriteAllText(outputPath = Path.Combine(directory,
                                                                Helper.GetDecompiledFileName(fileName, eso) + ".xml"),
                                      AssetHelper.GetEsoElement(eso).ToString());
                    list.Add(new FileEntry(outputPath, "model.xml"));
                    break;
                }

                case ".txt":
                    using (var stream = new FileStream(outputPath += ".bin", FileMode.Create,
                                                       FileAccess.Write, FileShare.Read))
                    {
                        var writer = new BinaryWriter(stream);
                        foreach (var num in File.ReadAllText(file)
                                 .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                                 .Select(double.Parse))
                        {
                            writer.Write((short)Math.Round(num * 256));
                        }
                    }
                    list.Add(new FileEntry(outputPath, "cos.bin"));
                    break;

                default:
                    switch (Path.GetFileName(file))
                    {
                    case "audio":
                        if (Directory.Exists(outputPath = Path.Combine(directory, "sfx")))
                        {
                            Directory.Delete(outputPath, true);
                        }
                        Directory.CreateDirectory(outputPath);
                        string xsb = Path.Combine(file, "sfx.xsb"), xwb = Path.Combine(file, "sfx.xwb");
                        int    offset;
                        using (var stream = new FileStream(xsb, FileMode.Open))
                        {
                            stream.Position = 0x2A;
                            using (var reader = new BinaryReader(stream)) offset = reader.ReadInt32();
                        }
                        var unxwb = new Process {
                            StartInfo = new ProcessStartInfo(
                                Path.Combine(CurrentApp.Directory, "Resources/Libraries/unxwb.exe"),
                                FormattableString.Invariant($"-d \"{outputPath}\" -b \"{xsb}\" {offset} \"{xwb}\""))
                            {
                                UseShellExecute = false, CreateNoWindow = true
                            }
                        };
                        unxwb.Start();
                        unxwb.WaitForExit();
                        list.Add(new FileEntry(outputPath, "sfx"));
                        break;

                    case "sfx":
                        Directory.CreateDirectory(outputPath = Path.Combine(directory, "audio"));
                        string tempPath       = Helper.GetRandomDirectory(),
                               tempInputPath  = Path.Combine(tempPath, "sfx"),
                               tempOutputPath = Path.Combine(tempPath, "audio");

                        /************************************************************************************
                        *     create temp input dir because it's still occupied for unknown reason;        *
                        *     create temp output dir because COMException will be thrown if output dir and *
                        * temp input dir is not under the same drive.                                      *
                        ************************************************************************************/
                        Directory.CreateDirectory(tempInputPath);
                        var projectPath = GenerateXactProject(file, tempInputPath);
                        using (var project = new CXACTMasterProject())
                        {
                            project.Create();
                            project.Load(projectPath, new CXACTMasterProjectCallback(), 0);
                            project.Build(new CXACTMasterProjectCallback(), tempOutputPath, false, false);
                        }
                        foreach (var path in Directory.EnumerateFiles(tempOutputPath))
                        {
                            var target = Path.Combine(outputPath, Path.GetFileName(path));
                            File.Delete(target);
                            File.Move(path, target);
                        }
                        try
                        {
                            Directory.Delete(tempPath, true);
                        }
                        catch
                        {
                            Trace.WriteLine(tempPath, "Delete tempPath failed");
                        }
                        list.Add(new FileEntry(outputPath, "audio"));
                        break;

                    default:
                        throw new NotSupportedException(Localization.DecompileUnrecognizedFile);
                    }
                    break;
                }
                return(new Tuple <Exception, string, List <FileEntry> >(null, Warning.Fetch(), list));
            }
            catch (Exception exc)
            {
                return(new Tuple <Exception, string, List <FileEntry> >(exc, Warning.Fetch(), list));
            }
            finally
            {
                Warning.Clear();
            }
        }