Пример #1
0
        /// <returns>A <b>new</b> <see cref="Map"/> object containing <b>only</b> the decompiled map files, or <see langword="null"/> if cancelled.</returns>
        public static Map?DecompileMap(Map map, MapFiles filesToDecompile, BackgroundWorker?worker)
        {
            if (!filesToDecompile.IsDefined(allowNoFlags: false))
            {
                throw new InvalidEnumArgumentException(nameof(filesToDecompile), (int)filesToDecompile, typeof(MapFiles));
            }

            if (filesToDecompile.HasFlag(MapFiles.Environment))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.PathingMap))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.PreviewIcons))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.ShadowMap))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.ImportedFiles))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.Info))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.AbilityObjectData))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.BuffObjectData))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.DestructableObjectData))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.DoodadObjectData))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.ItemObjectData))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.UnitObjectData))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.UpgradeObjectData))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.CustomTextTriggers))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.Script))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.TriggerStrings))
            {
                throw new NotImplementedException();
            }
            if (filesToDecompile.HasFlag(MapFiles.Doodads))
            {
                throw new NotImplementedException();
            }

            var decompiler    = new JassScriptDecompiler(map);
            var decompiledMap = new Map();

            var decompiledCount  = 0;
            var toDecompileCount = 0;
            var progress         = 0;

            if (filesToDecompile.HasFlag(MapFiles.Sounds))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.Cameras))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.Environment))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.PathingMap))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.PreviewIcons))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.Regions))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.ShadowMap))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.ImportedFiles))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.Info))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.AbilityObjectData))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.BuffObjectData))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.DestructableObjectData))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.DoodadObjectData))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.ItemObjectData))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.UnitObjectData))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.UpgradeObjectData))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.CustomTextTriggers))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.Script))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.Triggers))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.TriggerStrings))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.Doodads))
            {
                toDecompileCount++;
            }
            if (filesToDecompile.HasFlag(MapFiles.Units))
            {
                toDecompileCount++;
            }

            var gameVersion = map.Info?.GameVersion;
            var gamePatch   = gameVersion is null ? GamePatch.v1_26a : GamePatchVersionProvider.GetGamePatch(gameVersion);

            var progressState = new ProgressState();

            bool StartDecompilingFile(MapFiles mapFile)
            {
                if (filesToDecompile.HasFlag(mapFile))
                {
                    progressState.MapFile = mapFile;
                    worker?.ReportProgress(progress, progressState);

                    decompiledCount++;
                    progress = (100 * decompiledCount) / toDecompileCount;

                    return(true);
                }

                return(false);
            }

            bool WaitForCancel()
            {
                if (worker is not null)
                {
                    progressState.Error = true;
                    worker.ReportProgress(progress, progressState);

                    while (progressState.Error)
                    {
                        Thread.Sleep(500);
                    }

                    return(worker.CancellationPending);
                }

                return(false);
            }

            if (StartDecompilingFile(MapFiles.Sounds))
            {
                var formatVersion = gamePatch >= GamePatch.v1_32_6
                    ? MapSoundsFormatVersion.ReforgedV3
                    : gamePatch >= GamePatch.v1_32_0
                        ? MapSoundsFormatVersion.Reforged
                        : MapSoundsFormatVersion.Normal;

                if (decompiler.TryDecompileMapSounds(formatVersion, out var decompiledMapSounds))
                {
                    decompiledMap.Sounds = decompiledMapSounds;
                }
                else if (WaitForCancel())
                {
                    return(null);
                }
            }

            if (StartDecompilingFile(MapFiles.Cameras))
            {
                var formatVersion = MapCamerasFormatVersion.Normal;
                var useNewFormat  = gamePatch >= GamePatch.v1_31_0;

                if (decompiler.TryDecompileMapCameras(formatVersion, useNewFormat, out var decompiledMapCameras))
                {
                    decompiledMap.Cameras = decompiledMapCameras;
                }
                else if (WaitForCancel())
                {
                    return(null);
                }
            }

            if (StartDecompilingFile(MapFiles.Regions))
            {
                var formatVersion = MapRegionsFormatVersion.Normal;

                if (decompiler.TryDecompileMapRegions(formatVersion, out var decompiledMapRegions))
                {
                    decompiledMap.Regions = decompiledMapRegions;
                }
                else if (WaitForCancel())
                {
                    return(null);
                }
            }

            if (StartDecompilingFile(MapFiles.Triggers))
            {
                var formatVersion = gamePatch >= GamePatch.v1_07 ? MapTriggersFormatVersion.Tft : MapTriggersFormatVersion.RoC;
                var subVersion    = gamePatch >= GamePatch.v1_31_0 ? (MapTriggersSubVersion?)MapTriggersSubVersion.New : null;

                if (decompiler.TryDecompileMapTriggers(formatVersion, subVersion, out var decompiledMapTriggers))
                {
                    decompiledMap.Triggers = decompiledMapTriggers;
                }
                else if (WaitForCancel())
                {
                    return(null);
                }
            }

            if (StartDecompilingFile(MapFiles.Units))
            {
                var formatVersion = gamePatch >= GamePatch.v1_07 ? MapWidgetsFormatVersion.TFT : MapWidgetsFormatVersion.RoC;
                var subVersion    = gamePatch >= GamePatch.v1_07 ? MapWidgetsSubVersion.V11 : MapWidgetsSubVersion.V9;
                var useNewFormat  = gamePatch >= GamePatch.v1_32_0;

                if (decompiler.TryDecompileMapUnits(formatVersion, subVersion, useNewFormat, out var decompiledMapUnits))
                {
                    decompiledMap.Units = decompiledMapUnits;
                }
                else if (WaitForCancel())
                {
                    return(null);
                }
            }

            progressState.MapFile = null;
            worker?.ReportProgress(progress, progressState);

            return(decompiledMap);
        }
Пример #2
0
 public static Version ToVersion(this GamePatch gamePatch)
 {
     return(GamePatchVersionProvider.GetGameVersion(gamePatch));
 }
Пример #3
0
        public void TranspileAndSaveTest(string inputFile, string outputFile, ScriptLanguage targetLanguage)
        {
            var targetFileName = targetLanguage switch
            {
                ScriptLanguage.Jass => "war3map.j",
                ScriptLanguage.Lua => "war3map.lua",
                _ => throw new InvalidEnumArgumentException(nameof(targetLanguage), (int)targetLanguage, typeof(ScriptLanguage)),
            };

            using var mapArchive = MpqArchive.Open(inputFile, true);

            var map               = Map.Open(mapArchive);
            var sourceLanguage    = map.Info.ScriptLanguage;
            var mpqArchiveBuilder = new MpqArchiveBuilder(mapArchive);

            using var mapInfoStream = new MemoryStream();
            using var mapInfoWriter = new BinaryWriter(mapInfoStream);

            var mapInfo = map.Info;

            mapInfo.ScriptLanguage = targetLanguage;
            if (mapInfo.FormatVersion < MapInfoFormatVersion.Lua)
            {
                mapInfo.FormatVersion = MapInfoFormatVersion.Lua;
                if (mapInfo.GameVersion is null)
                {
                    mapInfo.GameVersion = GamePatchVersionProvider.GetGameVersion(War3Net.Build.Common.GamePatch.v1_31_1);
                }
            }

            mapInfoWriter.Write(mapInfo);
            mapInfoStream.Position = 0;
            mpqArchiveBuilder.AddFile(MpqFile.New(mapInfoStream, MapInfo.FileName));

            if (sourceLanguage == ScriptLanguage.Jass)
            {
                if (targetLanguage != ScriptLanguage.Lua)
                {
                    throw new NotSupportedException($"Unable to transpile from {sourceLanguage} to {targetLanguage}.");
                }

                mpqArchiveBuilder.RemoveFile("war3map.j");
                mpqArchiveBuilder.RemoveFile(@"Scripts\war3map.j");

                using var reader = new StreamReader(@"C:\Users\Stan\Google Drive\PHP Projects\Files\common.j");
                var commonJ = JassSyntaxFactory.ParseCompilationUnit(reader.ReadToEnd());

                using var reader2 = new StreamReader(@"C:\Users\Stan\Google Drive\PHP Projects\Files\blizzard.j");
                var blizzardJ = JassSyntaxFactory.ParseCompilationUnit(reader2.ReadToEnd());

                var transpiler = new JassToLuaTranspiler();
                transpiler.RegisterJassFile(commonJ);
                transpiler.RegisterJassFile(blizzardJ);

                var script = mapArchive.OpenFile("war3map.j");

                using var reader3 = new StreamReader(script);
                var luaCompilationUnit = transpiler.Transpile(JassSyntaxFactory.ParseCompilationUnit(reader3.ReadToEnd()));
                script.Close();

                var tempFileName = Path.GetTempFileName();
                try
                {
                    using (var writer = new StreamWriter(tempFileName))
                    {
                        var luaRenderOptions = new LuaSyntaxGenerator.SettingInfo
                        {
                            // Indent = 4,
                            // IsCommentsDisabled = true,
                        };

                        var luaRenderer = new LuaRenderer(luaRenderOptions, writer);
                        luaRenderer.RenderCompilationUnit(luaCompilationUnit);
                    }

                    using var fileStream = File.OpenRead(tempFileName);
                    mpqArchiveBuilder.AddFile(MpqFile.New(fileStream, targetFileName));

                    var mpqArchiveCreateOptions = new MpqArchiveCreateOptions
                    {
                        AttributesCreateMode = MpqFileCreateMode.Prune,
                    };

                    mpqArchiveBuilder.SaveTo(outputFile, mpqArchiveCreateOptions);
                }
                finally
                {
                    File.Delete(tempFileName);
                }
            }
            else if (sourceLanguage == ScriptLanguage.Lua)
            {
                throw new NotSupportedException($"Unable to transpile from {sourceLanguage} to {targetLanguage}.");
            }
            else
            {
                throw new NotSupportedException($"Unable to transpile from {sourceLanguage} to {targetLanguage}.");
            }
        }
Пример #4
0
        public static void TranspileAndSave(string inputFile, string outputFile, string?commonJPath, string?blizzardJPath, ScriptLanguage targetLanguage, BackgroundWorker?worker)
        {
            var targetFileName = targetLanguage switch
            {
                ScriptLanguage.Jass => "war3map.j",
                ScriptLanguage.Lua => "war3map.lua",
                _ => throw new InvalidEnumArgumentException(nameof(targetLanguage), (int)targetLanguage, typeof(ScriptLanguage)),
            };

            using var mapArchive = MpqArchive.Open(inputFile, true);

            var map               = Map.Open(mapArchive);
            var sourceLanguage    = map.Info.ScriptLanguage;
            var mpqArchiveBuilder = new MpqArchiveBuilder(mapArchive);

            using var mapInfoStream = new MemoryStream();
            using var mapInfoWriter = new BinaryWriter(mapInfoStream);

            var mapInfo = map.Info;

            mapInfo.ScriptLanguage = targetLanguage;
            if (mapInfo.FormatVersion < MapInfoFormatVersion.Lua)
            {
                mapInfo.FormatVersion = MapInfoFormatVersion.Lua;
                if (mapInfo.GameVersion is null)
                {
                    mapInfo.GameVersion = GamePatchVersionProvider.GetGameVersion(GamePatch.v1_31_1);
                }
            }

            mapInfoWriter.Write(mapInfo);
            mapInfoStream.Position = 0;
            mpqArchiveBuilder.AddFile(MpqFile.New(mapInfoStream, MapInfo.FileName));

            if (sourceLanguage == ScriptLanguage.Jass)
            {
                if (targetLanguage != ScriptLanguage.Lua)
                {
                    throw new NotSupportedException($"Unable to transpile from {sourceLanguage} to {targetLanguage}.");
                }

                mpqArchiveBuilder.RemoveFile("war3map.j");
                mpqArchiveBuilder.RemoveFile(@"Scripts\war3map.j");

                var jassHelperFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Warcraft III", "JassHelper");
                if (string.IsNullOrEmpty(commonJPath))
                {
                    if (Directory.Exists(jassHelperFolder))
                    {
                        commonJPath = Path.Combine(jassHelperFolder, "common.j");
                        if (string.IsNullOrEmpty(blizzardJPath))
                        {
                            blizzardJPath = Path.Combine(jassHelperFolder, "Blizzard.j");
                        }
                    }
                    else
                    {
                        throw new DirectoryNotFoundException("Unable to automatically find common.j and Blizzard.j folder.");
                    }
                }

                var mapHasCustomBlizzardJ = mapArchive.FileExists(@"Scripts\Blizzard.j");
                if (string.IsNullOrEmpty(blizzardJPath) && !mapHasCustomBlizzardJ)
                {
                    if (Directory.Exists(jassHelperFolder))
                    {
                        blizzardJPath = Path.Combine(jassHelperFolder, "Blizzard.j");
                    }
                    else
                    {
                        throw new DirectoryNotFoundException("Unable to automatically find common.j and Blizzard.j folder.");
                    }
                }

                var estimatedWorkToTranspile = map.Script.Length + 700000;
                var estimatedWorkToRegisterCommonAndBlizzard = 35000000 / estimatedWorkToTranspile;
                if (estimatedWorkToRegisterCommonAndBlizzard == 0)
                {
                    estimatedWorkToRegisterCommonAndBlizzard = 1;
                }

                var transpiler = new JassToLuaTranspiler();
                transpiler.RegisterJassFile(JassSyntaxFactory.ParseCompilationUnit(File.ReadAllText(commonJPath)));

                worker?.ReportProgress(estimatedWorkToRegisterCommonAndBlizzard);

                if (mapHasCustomBlizzardJ)
                {
                    throw new NotImplementedException("Custom Blizzard.j files are currently not supported.");
                }
                else
                {
                    transpiler.RegisterJassFile(JassSyntaxFactory.ParseCompilationUnit(File.ReadAllText(blizzardJPath)));

                    worker?.ReportProgress(estimatedWorkToRegisterCommonAndBlizzard * 2);
                }

                var luaCompilationUnit = transpiler.Transpile(JassSyntaxFactory.ParseCompilationUnit(map.Script));

                using var stream = new MemoryStream();
                using (var writer = new StreamWriter(stream, leaveOpen: true))
                {
                    var luaRenderOptions = new LuaSyntaxGenerator.SettingInfo
                    {
                        // Indent = 4,
                        // IsCommentsDisabled = true,
                    };

                    var luaRenderer = new LuaRenderer(luaRenderOptions, writer);
                    luaRenderer.RenderCompilationUnit(luaCompilationUnit);
                    writer.Flush();
                }

                stream.Position = 0;
                mpqArchiveBuilder.AddFile(MpqFile.New(stream, targetFileName));

                worker?.ReportProgress(100);

                var mpqArchiveCreateOptions = new MpqArchiveCreateOptions
                {
                };

                mpqArchiveBuilder.SaveTo(outputFile, mpqArchiveCreateOptions);
            }
            else if (sourceLanguage == ScriptLanguage.Lua)
            {
                mpqArchiveBuilder.RemoveFile("war3map.lua");
                mpqArchiveBuilder.RemoveFile(@"Scripts\war3map.lua");

                throw new NotSupportedException($"Unable to transpile from {sourceLanguage} to {targetLanguage}.");
            }
            else
            {
                throw new NotSupportedException($"Unable to transpile from {sourceLanguage} to {targetLanguage}.");
            }
        }