private void RenderToFile(string path, IEnumerable <GlobalDeclarationSyntax?> globals) { using (var fileStream = FileProvider.CreateFileAndFolder(path)) { using (var writer = new StreamWriter(fileStream, new UTF8Encoding(false, true))) { var renderer = new JassRenderer(writer); renderer.Options = _rendererOptions; var globalsArray = globals.Where(global => global != null).ToArray(); var globalsDeclarationList = globalsArray.Length == 0 ? new GlobalsDeclarationListSyntax(new EmptyNode(0)) : new GlobalsDeclarationListSyntax(globalsArray); renderer.Render(JassSyntaxFactory.File( new NewDeclarationSyntax( new DeclarationSyntax(new GlobalsBlockSyntax( new TokenNode(new SyntaxToken(SyntaxTokenType.GlobalsKeyword), 0), new LineDelimiterSyntax(new EndOfLineSyntax(new TokenNode(new SyntaxToken(SyntaxTokenType.NewlineSymbol), 0))), globalsDeclarationList, new TokenNode(new SyntaxToken(SyntaxTokenType.EndglobalsKeyword), 0))), new LineDelimiterSyntax(new EndOfLineSyntax(new TokenNode(new SyntaxToken(SyntaxTokenType.NewlineSymbol), 0)))))); } } }
public static CompileResult CompileScript(this Map map, Compiler compiler, IEnumerable <string> luaSystemLibs, string commonJPath, string blizzardJPath) { if (map is null) { throw new ArgumentNullException(nameof(map)); } if (compiler is null) { throw new ArgumentNullException(nameof(compiler)); } if (map.Info.ScriptLanguage != ScriptLanguage.Lua) { throw new InvalidOperationException($"The map's script language must be set to lua in order to use the C# compiler."); } using var stream = new MemoryStream(); try { compiler.CompileSingleFile(stream, luaSystemLibs); } catch (CompilationErrorException e) { return(new CompileResult(e.EmitResult)); } var transpiler = new JassToLuaTranspiler(); transpiler.IgnoreComments = true; transpiler.IgnoreEmptyDeclarations = true; transpiler.IgnoreEmptyStatements = true; transpiler.KeepFunctionsSeparated = true; transpiler.RegisterJassFile(JassSyntaxFactory.ParseCompilationUnit(File.ReadAllText(commonJPath))); transpiler.RegisterJassFile(JassSyntaxFactory.ParseCompilationUnit(File.ReadAllText(blizzardJPath))); var mapScriptBuilder = new MapScriptBuilder(); mapScriptBuilder.SetDefaultOptionsForCSharpLua(); var luaCompilationUnit = transpiler.Transpile(mapScriptBuilder.Build(map)); using (var writer = new StreamWriter(stream, _defaultEncoding, leaveOpen: true)) { var luaRenderOptions = new LuaSyntaxGenerator.SettingInfo { Indent = 4, }; var luaRenderer = new LuaRenderer(luaRenderOptions, writer); luaRenderer.RenderCompilationUnit(luaCompilationUnit); } stream.Position = 0; map.SetScriptFile(stream); return(new CompileResult(true, null)); }
private void RenderToFile(string path, IEnumerable <FunctionSyntax> functions) { using (var fileStream = FileProvider.CreateFileAndFolder(path)) { using (var writer = new StreamWriter(fileStream, new UTF8Encoding(false, true))) { var renderer = new JassRenderer(writer); renderer.Options = _rendererOptions; renderer.Render(JassSyntaxFactory.File(functions)); } } }
private bool TryAdaptCallStatement(JassMapScriptAdapterContext context, JassCallStatementSyntax callStatement, [NotNullWhen(true)] out IStatementSyntax?adaptedCallStatement) { if (TryAdaptInvocation(context, callStatement, out var adaptedInvocationName, out var adaptedInvocationArguments)) { if (string.IsNullOrEmpty(adaptedInvocationName)) { adaptedCallStatement = new JassCommentSyntax(callStatement.ToString()); } else if (TryAdaptArgumentList(context, adaptedInvocationArguments, out var adaptedArguments)) { adaptedCallStatement = JassSyntaxFactory.CallStatement( adaptedInvocationName, adaptedArguments); } else { adaptedCallStatement = JassSyntaxFactory.CallStatement( adaptedInvocationName, adaptedInvocationArguments); } return(true); }
private bool TryAdaptBlzCreateInvocation <TInvocation>( JassMapScriptAdapterContext context, TInvocation invocation, [NotNullWhen(true)] out string?adaptedInvocationName, [NotNullWhen(true)] out JassArgumentListSyntax?adaptedInvocationArguments, string replacementFunctionName, int expectedArgumentCount, int typeIdArgumentIndex, int skinIdArgumentIndex) where TInvocation : IInvocationSyntax { if (invocation.Arguments.Arguments.Length == expectedArgumentCount && invocation.Arguments.Arguments[typeIdArgumentIndex].TryGetIntegerExpressionValue(out var typeId) && invocation.Arguments.Arguments[skinIdArgumentIndex].TryGetIntegerExpressionValue(out var skinId)) { if (typeId == skinId) { var arguments = new IExpressionSyntax[expectedArgumentCount - 1]; for (var i = 0; i < expectedArgumentCount; i++) { if (i == skinIdArgumentIndex) { continue; } arguments[i > skinIdArgumentIndex ? i - 1 : i] = invocation.Arguments.Arguments[i]; } adaptedInvocationName = replacementFunctionName; adaptedInvocationArguments = JassSyntaxFactory.ArgumentList(arguments); return(true); } else { context.Diagnostics.Add($"Unable to adapt '{invocation.IdentifierName}' to '{replacementFunctionName}', because the skin '{skinId.ToRawcode()}' is not the same as the type '{typeId.ToRawcode()}'."); } }
private bool TryAdaptInvocationExpression(JassMapScriptAdapterContext context, JassInvocationExpressionSyntax invocationExpression, [NotNullWhen(true)] out IExpressionSyntax?adaptedInvocationExpression) { if (TryAdaptInvocation(context, invocationExpression, out var adaptedInvocationName, out var adaptedInvocationArguments)) { if (string.IsNullOrEmpty(adaptedInvocationName)) { context.Diagnostics.Add($"Invocation expression of function '{invocationExpression.IdentifierName}' should be removed."); adaptedInvocationExpression = invocationExpression; } else if (TryAdaptArgumentList(context, adaptedInvocationArguments, out var adaptedArguments)) { adaptedInvocationExpression = JassSyntaxFactory.InvocationExpression( adaptedInvocationName, adaptedArguments); } else { adaptedInvocationExpression = JassSyntaxFactory.InvocationExpression( adaptedInvocationName, adaptedInvocationArguments); } return(true); }
private bool TryAdaptInvocation <TInvocation>(JassMapScriptAdapterContext context, TInvocation invocation, out string?adaptedInvocationName, [NotNullWhen(true)] out JassArgumentListSyntax?adaptedInvocationArguments) where TInvocation : IInvocationSyntax { if (context.KnownFunctions.TryGetValue(invocation.IdentifierName.Name, out var knownFunctionParameters)) { if (knownFunctionParameters.Length != invocation.Arguments.Arguments.Length) { context.Diagnostics.Add($"Invalid function invocation: '{invocation.IdentifierName}' expected {knownFunctionParameters.Length} parameters but got {invocation.Arguments.Arguments.Length}."); } } else { if (string.Equals(invocation.IdentifierName.Name, "BlzCreateItemWithSkin", StringComparison.Ordinal)) { return(TryAdaptBlzCreateInvocation(context, invocation, out adaptedInvocationName, out adaptedInvocationArguments, "CreateItem", 4, 0, 3)); } else if (string.Equals(invocation.IdentifierName.Name, "BlzCreateUnitWithSkin", StringComparison.Ordinal)) { return(TryAdaptBlzCreateInvocation(context, invocation, out adaptedInvocationName, out adaptedInvocationArguments, "CreateUnit", 6, 1, 5)); } else if (string.Equals(invocation.IdentifierName.Name, "BlzCreateDestructableWithSkin", StringComparison.Ordinal)) { return(TryAdaptBlzCreateInvocation(context, invocation, out adaptedInvocationName, out adaptedInvocationArguments, "CreateDestructable", 7, 0, 6)); } else if (string.Equals(invocation.IdentifierName.Name, "BlzCreateDestructableZWithSkin", StringComparison.Ordinal)) { return(TryAdaptBlzCreateInvocation(context, invocation, out adaptedInvocationName, out adaptedInvocationArguments, "CreateDestructableZ", 8, 0, 7)); } else if (string.Equals(invocation.IdentifierName.Name, "BlzCreateDeadDestructableWithSkin", StringComparison.Ordinal)) { return(TryAdaptBlzCreateInvocation(context, invocation, out adaptedInvocationName, out adaptedInvocationArguments, "CreateDeadDestructable", 7, 0, 6)); } else if (string.Equals(invocation.IdentifierName.Name, "BlzCreateDeadDestructableZWithSkin", StringComparison.Ordinal)) { return(TryAdaptBlzCreateInvocation(context, invocation, out adaptedInvocationName, out adaptedInvocationArguments, "CreateDeadDestructableZ", 8, 0, 7)); } else if (string.Equals(invocation.IdentifierName.Name, "SetSoundFacialAnimationLabel", StringComparison.Ordinal)) { adaptedInvocationName = null; adaptedInvocationArguments = invocation.Arguments; return(true); } else if (string.Equals(invocation.IdentifierName.Name, "SetSoundFacialAnimationGroupLabel", StringComparison.Ordinal)) { adaptedInvocationName = null; adaptedInvocationArguments = invocation.Arguments; return(true); } else if (string.Equals(invocation.IdentifierName.Name, "SetSoundFacialAnimationSetFilepath", StringComparison.Ordinal)) { adaptedInvocationName = null; adaptedInvocationArguments = invocation.Arguments; return(true); } else if (string.Equals(invocation.IdentifierName.Name, "SetDialogueSpeakerNameKey", StringComparison.Ordinal)) { if (invocation.Arguments.Arguments.Length == 2 && invocation.Arguments.Arguments[0] is JassVariableReferenceExpressionSyntax variableReferenceExpression && invocation.Arguments.Arguments[1] is JassStringLiteralExpressionSyntax stringLiteralExpression) { if (!context.DialogueTitles.TryAdd(variableReferenceExpression.IdentifierName.Name, stringLiteralExpression.Value)) { context.Diagnostics.Add($"Duplicate dialogue title for sound '{variableReferenceExpression.IdentifierName}'."); } } adaptedInvocationName = null; adaptedInvocationArguments = invocation.Arguments; return(true); } else if (string.Equals(invocation.IdentifierName.Name, "SetDialogueTextKey", StringComparison.Ordinal)) { if (invocation.Arguments.Arguments.Length == 2 && invocation.Arguments.Arguments[0] is JassVariableReferenceExpressionSyntax variableReferenceExpression && invocation.Arguments.Arguments[1] is JassStringLiteralExpressionSyntax stringLiteralExpression) { if (!context.DialogueTexts.TryAdd(variableReferenceExpression.IdentifierName.Name, stringLiteralExpression.Value)) { context.Diagnostics.Add($"Duplicate dialogue text for sound '{variableReferenceExpression.IdentifierName}'."); } } adaptedInvocationName = null; adaptedInvocationArguments = invocation.Arguments; return(true); } else if (string.Equals(invocation.IdentifierName.Name, "PlayDialogueFromSpeakerEx", StringComparison.Ordinal)) { if (invocation.Arguments.Arguments.Length == 7 && invocation.Arguments.Arguments[3] is JassVariableReferenceExpressionSyntax variableReferenceExpression && context.DialogueTitles.TryGetValue(variableReferenceExpression.IdentifierName.Name, out var dialogueTitle) && context.DialogueTexts.TryGetValue(variableReferenceExpression.IdentifierName.Name, out var dialogueText)) { adaptedInvocationName = "TransmissionFromUnitWithNameBJ"; adaptedInvocationArguments = JassSyntaxFactory.ArgumentList( invocation.Arguments.Arguments[0], invocation.Arguments.Arguments[1], JassSyntaxFactory.LiteralExpression(dialogueTitle), invocation.Arguments.Arguments[3], JassSyntaxFactory.LiteralExpression(dialogueText), invocation.Arguments.Arguments[4], invocation.Arguments.Arguments[5], invocation.Arguments.Arguments[6]); return(true); } } else if (string.Equals(invocation.IdentifierName.Name, "PlayDialogueFromSpeakerTypeEx", StringComparison.Ordinal)) { if (invocation.Arguments.Arguments.Length == 8 && invocation.Arguments.Arguments[4] is JassVariableReferenceExpressionSyntax variableReferenceExpression && context.DialogueTitles.TryGetValue(variableReferenceExpression.IdentifierName.Name, out var dialogueTitle) && context.DialogueTexts.TryGetValue(variableReferenceExpression.IdentifierName.Name, out var dialogueText)) { adaptedInvocationName = "TransmissionFromUnitTypeWithNameBJ"; adaptedInvocationArguments = JassSyntaxFactory.ArgumentList( invocation.Arguments.Arguments[0], invocation.Arguments.Arguments[1], invocation.Arguments.Arguments[2], JassSyntaxFactory.LiteralExpression(dialogueTitle), invocation.Arguments.Arguments[3], invocation.Arguments.Arguments[4], JassSyntaxFactory.LiteralExpression(dialogueText), invocation.Arguments.Arguments[5], invocation.Arguments.Arguments[6], invocation.Arguments.Arguments[7]); return(true); } } else if (string.Equals(invocation.IdentifierName.Name, "SetEnemyStartLocPrioCount", StringComparison.Ordinal)) { adaptedInvocationName = null; adaptedInvocationArguments = invocation.Arguments; return(true); } else if (string.Equals(invocation.IdentifierName.Name, "SetEnemyStartLocPrio", StringComparison.Ordinal)) { adaptedInvocationName = null; adaptedInvocationArguments = invocation.Arguments; return(true); } else { context.Diagnostics.Add($"Unknown function '{invocation.IdentifierName}'."); adaptedInvocationName = null; adaptedInvocationArguments = null; return(false); } } adaptedInvocationName = null; adaptedInvocationArguments = null; return(false); }
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}."); } }
private static void Main(string[] args) { #if false var mapRegions = new MapRegions(MapRegionsFormatVersion.Normal); mapRegions.Regions.Add(new Region { Left = -2594f, Right = -2016f, Bottom = 992f, Top = 1568f, Name = "Spawn1Reg", }); #else var mapRegionsPath = ""; // TODO using var mapRegionsFileStream = File.OpenRead(mapRegionsPath); // var mapArchivePath = ""; // TODO // using var mapRegionsFileStream = MpqFile.OpenRead(Path.Combine(mapArchivePath, MapRegions.FileName)); using var mapRegionsReader = new BinaryReader(mapRegionsFileStream); var mapRegions = mapRegionsReader.ReadMapRegions(); #endif var members = new List <MemberDeclarationSyntax>(); var luamembers = new List <MemberDeclarationSyntax>(); foreach (var region in mapRegions.Regions) { if (string.IsNullOrEmpty(region.AmbientSound) && region.WeatherType == 0) { var decl = new GlobalVariableDeclarationSyntax( new War3Net.CodeAnalysis.Jass.Syntax.VariableDeclarationSyntax( new VariableDefinitionSyntax( JassSyntaxFactory.ParseTypeName("rect"), JassSyntaxFactory.Token(SyntaxTokenType.AlphanumericIdentifier, $"gg_rct_{region.Name.Replace(' ', '_')}"), JassSyntaxFactory.EqualsValueClause(JassSyntaxFactory.InvocationExpression( "Rect", JassSyntaxFactory.ConstantExpression(region.Left), JassSyntaxFactory.ConstantExpression(region.Bottom), JassSyntaxFactory.ConstantExpression(region.Right), JassSyntaxFactory.ConstantExpression(region.Top))))), JassSyntaxFactory.Newlines()); members.Add(JassToCSharpTranspiler.Transpile(decl)); } else { var decl = new GlobalVariableDeclarationSyntax( new War3Net.CodeAnalysis.Jass.Syntax.VariableDeclarationSyntax( new VariableDefinitionSyntax( JassSyntaxFactory.ParseTypeName("rect"), JassSyntaxFactory.Token(SyntaxTokenType.AlphanumericIdentifier, $"gg_rct_{region.Name.Replace(' ', '_')}"), JassSyntaxFactory.Empty())), JassSyntaxFactory.Newlines()); luamembers.Add(JassToCSharpTranspiler.Transpile(decl)); } } var class1 = JassTranspilerHelper.GetClassDeclaration("Regions", members, false); var class2 = JassTranspilerHelper.GetClassDeclaration("LuaRegions", luamembers, true); var usingDirectives = new UsingDirectiveSyntax[] { SyntaxFactory.UsingDirective(SyntaxFactory.Token(SyntaxKind.StaticKeyword), null, SyntaxFactory.ParseName("War3Api.Common")), }; var compilationUnit = JassTranspilerHelper.GetCompilationUnit( new SyntaxList <UsingDirectiveSyntax>(usingDirectives), JassTranspilerHelper.GetNamespaceDeclaration("War3Map.Template.Generated", class1.Concat(class2).ToArray())); var path = Path.Combine(GeneratedCodeProjectFolderPath, "Regions.cs"); using var fileStream = File.Create(path); CompilationHelper.SerializeTo(compilationUnit, fileStream); }
public AdaptResult AdaptFile(Stream stream, TargetPatch targetPatch, GamePatch originPatch) { try { var commonJPath = Path.Combine(targetPatch.GameDataPath, PathConstants.CommonJPath); if (!File.Exists(commonJPath)) { return(new AdaptResult { Status = MapFileStatus.ConfigError, Diagnostics = commonJPath.GetFileNotFoundDiagnostics(), }); } var blizzardJPath = Path.Combine(targetPatch.GameDataPath, PathConstants.BlizzardJPath); if (!File.Exists(blizzardJPath)) { return(new AdaptResult { Status = MapFileStatus.ConfigError, Diagnostics = blizzardJPath.GetFileNotFoundDiagnostics(), }); } var commonJText = File.ReadAllText(commonJPath); var commonJCompilationUnit = JassSyntaxFactory.ParseCompilationUnit(commonJText); var blizzardJText = File.ReadAllText(blizzardJPath); var blizzardJCompilationUnit = JassSyntaxFactory.ParseCompilationUnit(blizzardJText); string scriptText; using (var reader = new StreamReader(stream, leaveOpen: true)) { scriptText = reader.ReadToEnd(); } var compilationUnit = JassSyntaxFactory.ParseCompilationUnit(scriptText); try { var context = new JassMapScriptAdapterContext(); foreach (var declaration in commonJCompilationUnit.Declarations) { RegisterDeclaration(declaration, context); } foreach (var declaration in blizzardJCompilationUnit.Declarations) { RegisterDeclaration(declaration, context); } // Common.j and Blizzard.j should not cause any diagnostics. if (context.Diagnostics.Count > 0) { return(new AdaptResult { Status = MapFileStatus.AdapterError, Diagnostics = context.Diagnostics.ToArray(), }); } if (TryAdaptCompilationUnit(context, compilationUnit, out var adaptedCompilationUnit)) { var memoryStream = new MemoryStream(); using var writer = new StreamWriter(memoryStream, new UTF8Encoding(false, true), leaveOpen: true); var renderer = new JassRenderer(writer); renderer.Render(adaptedCompilationUnit); return(new AdaptResult { Status = MapFileStatus.Adapted, Diagnostics = context.Diagnostics.ToArray(), AdaptedFileStream = memoryStream, }); } if (context.Diagnostics.Count == 0) { return(new AdaptResult { Status = MapFileStatus.Compatible, }); } else { return(new AdaptResult { Status = MapFileStatus.Incompatible, Diagnostics = context.Diagnostics.ToArray(), }); } } catch { return(new AdaptResult { Status = MapFileStatus.AdapterError, }); } } catch (Exception e) { return(new AdaptResult { Status = MapFileStatus.ParseError, Diagnostics = new[] { e.Message }, }); } }
private static void Main(string[] args) { _watcher = new FileSystemWatcher(); _watcher.Created += OnWatchedFileEvent; _watcher.Renamed += OnWatchedFileEvent; _watcher.Deleted += OnWatchedFileEvent; var form = new Form(); form.Text = Title; _archiveInput = new TextBox { PlaceholderText = "Input map...", }; _openCloseArchiveButton = new Button { Text = "Open archive", Enabled = false, }; _saveAsButton = new Button { Text = "Save As...", }; _saveAsButton.Size = _saveAsButton.PreferredSize; _saveAsButton.Enabled = false; _autoDetectFilesToDecompileButton = new Button { Text = "Detect files to decompile", }; _autoDetectFilesToDecompileButton.Size = _autoDetectFilesToDecompileButton.PreferredSize; _autoDetectFilesToDecompileButton.Enabled = false; _filesToDecompileCheckBoxes = new[] { new MapFileCheckBox(MapFiles.Sounds, MapSounds.FileName), new MapFileCheckBox(MapFiles.Cameras, MapCameras.FileName), new MapFileCheckBox(MapFiles.Regions, MapRegions.FileName), new MapFileCheckBox(MapFiles.Triggers, MapSounds.FileName), new MapFileCheckBox(MapFiles.Units, MapUnits.FileName), }; foreach (var checkBox in _filesToDecompileCheckBoxes) { checkBox.Size = checkBox.PreferredSize; checkBox.Enabled = false; checkBox.CheckedChanged += (s, e) => { _saveAsButton.Enabled = _filesToDecompileCheckBoxes.Any(checkBox => checkBox.Checked); }; } _archiveInput.TextChanged += OnArchiveInputTextChanged; _archiveInputBrowseButton = new Button { Text = "Browse", }; _archiveInputBrowseButton.Size = _archiveInputBrowseButton.PreferredSize; _archiveInputBrowseButton.Click += (s, e) => { var openFileDialog = new OpenFileDialog { CheckFileExists = false, }; openFileDialog.Filter = string.Join('|', new[] { "Warcraft III map|*.w3m;*.w3x", "All files|*.*", }); var openFileDialogResult = openFileDialog.ShowDialog(); if (openFileDialogResult == DialogResult.OK) { _archiveInput.Text = openFileDialog.FileName; } }; _openCloseArchiveButton.Size = _openCloseArchiveButton.PreferredSize; _openCloseArchiveButton.Click += OnClickOpenCloseMap; _saveAsButton.Click += (s, e) => { var saveFileDialog = new SaveFileDialog { OverwritePrompt = true, CreatePrompt = false, }; var saveFileDialogResult = saveFileDialog.ShowDialog(); if (saveFileDialogResult == DialogResult.OK) { _progressBar.CustomText = "Starting..."; _progressBar.Value = 0; _openCloseArchiveButton.Enabled = false; _saveAsButton.Enabled = false; _autoDetectFilesToDecompileButton.Enabled = false; foreach (var checkBox in _filesToDecompileCheckBoxes) { checkBox.Enabled = false; } _progressBar.Visible = true; _worker.RunWorkerAsync(saveFileDialog.FileName); } }; _autoDetectFilesToDecompileButton.Click += (s, e) => { var filesToDecompile = MapDecompiler.AutoDetectMapFilesToDecompile(_map); foreach (var checkBox in _filesToDecompileCheckBoxes) { checkBox.Checked = filesToDecompile.HasFlag(checkBox.MapFile); } }; _progressBar = new TextProgressBar { Dock = DockStyle.Bottom, Style = ProgressBarStyle.Continuous, VisualMode = TextProgressBar.ProgressBarDisplayMode.CustomText, Visible = false, }; _worker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true, }; _worker.DoWork += DecompileMapBackgroundWork; _worker.ProgressChanged += DecompileMapProgressChanged; _worker.RunWorkerCompleted += DecompileMapCompleted; // Initialize parser JassSyntaxFactory.ParseCompilationUnit(string.Empty); var flowLayout = new FlowLayoutPanel { Dock = DockStyle.Fill, FlowDirection = FlowDirection.TopDown, WrapContents = false, }; var inputArchiveFlowLayout = new FlowLayoutPanel { FlowDirection = FlowDirection.LeftToRight, }; var buttonsFlowLayout = new FlowLayoutPanel { FlowDirection = FlowDirection.LeftToRight, }; var checkBoxesFlowLayout = new FlowLayoutPanel { FlowDirection = FlowDirection.TopDown, WrapContents = false, }; inputArchiveFlowLayout.AddControls(_archiveInput, _archiveInputBrowseButton, _openCloseArchiveButton); buttonsFlowLayout.AddControls(_saveAsButton, _autoDetectFilesToDecompileButton); checkBoxesFlowLayout.AddControls(_filesToDecompileCheckBoxes); checkBoxesFlowLayout.Size = checkBoxesFlowLayout.PreferredSize; flowLayout.AddControls(inputArchiveFlowLayout, buttonsFlowLayout, checkBoxesFlowLayout); form.AddControls(flowLayout, _progressBar); form.SizeChanged += (s, e) => { var width = form.Width; _archiveInput.Width = (width > 360 ? 360 : width) - 10; inputArchiveFlowLayout.Size = inputArchiveFlowLayout.GetPreferredSize(new Size(width, 0)); buttonsFlowLayout.Size = buttonsFlowLayout.GetPreferredSize(new Size(width, 0)); flowLayout.Height = inputArchiveFlowLayout.Margin.Top + inputArchiveFlowLayout.Height + inputArchiveFlowLayout.Margin.Bottom + buttonsFlowLayout.Margin.Top + buttonsFlowLayout.Height + buttonsFlowLayout.Margin.Bottom; }; form.Size = new Size(400, 400); form.MinimumSize = new Size(400, 300); form.FormClosing += (s, e) => { _archive?.Dispose(); _worker?.Dispose(); }; form.ShowDialog(); }
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}."); } }
private static void Main(string[] args) { _watcher = new FileSystemWatcher(); _watcher.Created += OnWatchedFileEvent; _watcher.Renamed += OnWatchedFileEvent; _watcher.Deleted += OnWatchedFileEvent; var form = new Form(); form.Text = Title; _archiveInput = new TextBox { PlaceholderText = "Input map...", }; _openCloseArchiveButton = new Button { Text = "Open archive", Enabled = false, }; _saveAsButton = new Button { Text = "Save As...", }; _saveAsButton.Size = _saveAsButton.PreferredSize; _saveAsButton.Enabled = false; _targetScriptLanguagesComboBox = new ComboBox { Enabled = false, DropDownStyle = ComboBoxStyle.DropDownList, Width = 120, }; _targetScriptLanguagesComboBox.SelectedIndexChanged += (s, e) => { _targetScriptLanguage = (ScriptLanguage?)_targetScriptLanguagesComboBox.SelectedItem; _saveAsButton.Enabled = _targetScriptLanguage.HasValue; }; _targetScriptLanguagesComboBox.FormattingEnabled = true; _targetScriptLanguagesComboBox.Format += (s, e) => { if (e.ListItem is ScriptLanguage scriptLanguage) { e.Value = scriptLanguage.ToString(); } }; _archiveInput.TextChanged += OnArchiveInputTextChanged; _archiveInputBrowseButton = new Button { Text = "Browse", }; _archiveInputBrowseButton.Size = _archiveInputBrowseButton.PreferredSize; _archiveInputBrowseButton.Click += (s, e) => { var openFileDialog = new OpenFileDialog { CheckFileExists = false, }; openFileDialog.Filter = string.Join('|', new[] { "Warcraft III map|*.w3m;*.w3x", "All files|*.*", }); var openFileDialogResult = openFileDialog.ShowDialog(); if (openFileDialogResult == DialogResult.OK) { _archiveInput.Text = openFileDialog.FileName; } }; _openCloseArchiveButton.Size = _openCloseArchiveButton.PreferredSize; _openCloseArchiveButton.Click += OnClickOpenCloseMap; _saveAsButton.Click += (s, e) => { var saveFileDialog = new SaveFileDialog { OverwritePrompt = true, CreatePrompt = false, }; var saveFileDialogResult = saveFileDialog.ShowDialog(); if (saveFileDialogResult == DialogResult.OK) { _progressStepIndex = 0; _progressBar.CustomText = _progressBarSteps[_progressStepIndex]; _progressBar.Value = 0; _openCloseArchiveButton.Enabled = false; _saveAsButton.Enabled = false; _targetScriptLanguagesComboBox.Enabled = false; _progressBar.Visible = true; _worker.RunWorkerAsync(saveFileDialog.FileName); } }; _progressBar = new TextProgressBar { Dock = DockStyle.Bottom, Style = ProgressBarStyle.Continuous, VisualMode = TextProgressBar.ProgressBarDisplayMode.CustomText, Visible = false, }; _worker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = false, }; _worker.DoWork += TranspileMapBackgroundWork; _worker.ProgressChanged += TranspileMapProgressChanged; _worker.RunWorkerCompleted += TranspileMapCompleted; // Initialize parser JassSyntaxFactory.ParseCompilationUnit(string.Empty); var flowLayout = new FlowLayoutPanel { Dock = DockStyle.Fill, FlowDirection = FlowDirection.TopDown, }; var inputArchiveFlowLayout = new FlowLayoutPanel { FlowDirection = FlowDirection.LeftToRight, }; var buttonsFlowLayout = new FlowLayoutPanel { FlowDirection = FlowDirection.LeftToRight, }; var targetScriptLanguageLabel = new Label { Text = "Transpile to", TextAlign = ContentAlignment.BottomRight, }; inputArchiveFlowLayout.AddControls(_archiveInput, _archiveInputBrowseButton, _openCloseArchiveButton); buttonsFlowLayout.AddControls(_saveAsButton, targetScriptLanguageLabel, _targetScriptLanguagesComboBox); flowLayout.AddControls(inputArchiveFlowLayout, buttonsFlowLayout); form.AddControls(flowLayout, _progressBar); targetScriptLanguageLabel.Size = targetScriptLanguageLabel.PreferredSize; form.SizeChanged += (s, e) => { var width = form.Width; _archiveInput.Width = (width > 360 ? 360 : width) - 10; inputArchiveFlowLayout.Size = inputArchiveFlowLayout.GetPreferredSize(new Size(width, 0)); buttonsFlowLayout.Size = buttonsFlowLayout.GetPreferredSize(new Size(width, 0)); flowLayout.Height = inputArchiveFlowLayout.Margin.Top + inputArchiveFlowLayout.Height + inputArchiveFlowLayout.Margin.Bottom + buttonsFlowLayout.Margin.Top + buttonsFlowLayout.Height + buttonsFlowLayout.Margin.Bottom; }; form.Size = new Size(400, 300); form.MinimumSize = new Size(400, 200); form.FormClosing += (s, e) => { _archive?.Dispose(); _worker?.Dispose(); }; form.ShowDialog(); }
private FunctionSyntax GetMainFunctionSyntax(float left, float right, float top, float bottom, Tileset tileset, SoundEnvironment sound, params string[] initFunctions) { var statements = new List <NewStatementSyntax>() { JassSyntaxFactory.CallStatement( "SetCameraBounds", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.VariableExpression("left"), JassSyntaxFactory.VariableExpression("bottom"), JassSyntaxFactory.VariableExpression("right"), JassSyntaxFactory.VariableExpression("top"), JassSyntaxFactory.VariableExpression("left"), JassSyntaxFactory.VariableExpression("top"), JassSyntaxFactory.VariableExpression("right"), JassSyntaxFactory.VariableExpression("bottom"))), JassSyntaxFactory.CallStatement( "SetDayNightModels", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.ConstantExpression(LightEnvironmentProvider.GetTerrainLightEnvironmentModel(tileset)), JassSyntaxFactory.ConstantExpression(LightEnvironmentProvider.GetUnitLightEnvironmentModel(tileset)))), JassSyntaxFactory.CallStatement( "NewSoundEnvironment", JassSyntaxFactory.ConstantExpression(SoundEnvironmentProvider.GetSoundEnvironment(sound))), JassSyntaxFactory.CallStatement( "SetAmbientDaySound", JassSyntaxFactory.ConstantExpression(SoundEnvironmentProvider.GetAmbientDaySound(tileset))), JassSyntaxFactory.CallStatement( "SetAmbientNightSound", JassSyntaxFactory.ConstantExpression(SoundEnvironmentProvider.GetAmbientNightSound(tileset))), JassSyntaxFactory.CallStatement( "SetMapMusic", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.ConstantExpression("Music"), JassSyntaxFactory.ConstantExpression(true), JassSyntaxFactory.ConstantExpression(0))), }; foreach (var initFunction in initFunctions) { statements.Add(JassSyntaxFactory.CallStatement(initFunction)); } return(JassSyntaxFactory.Function( JassSyntaxFactory.FunctionDeclaration("main"), JassSyntaxFactory.LocalVariableList( JassSyntaxFactory.VariableDefinition( JassSyntaxFactory.ParseTypeName("real"), "left", JassSyntaxFactory.BinaryAdditionExpression( JassSyntaxFactory.ConstantExpression(left), JassSyntaxFactory.InvocationExpression( "GetCameraMargin", JassSyntaxFactory.ArgumentList(JassSyntaxFactory.VariableExpression("CAMERA_MARGIN_LEFT"))))), JassSyntaxFactory.VariableDefinition( JassSyntaxFactory.ParseTypeName("real"), "right", JassSyntaxFactory.BinarySubtractionExpression( JassSyntaxFactory.ConstantExpression(right), JassSyntaxFactory.InvocationExpression( "GetCameraMargin", JassSyntaxFactory.ArgumentList(JassSyntaxFactory.VariableExpression("CAMERA_MARGIN_RIGHT"))))), JassSyntaxFactory.VariableDefinition( JassSyntaxFactory.ParseTypeName("real"), "top", JassSyntaxFactory.BinarySubtractionExpression( JassSyntaxFactory.ConstantExpression(top), JassSyntaxFactory.InvocationExpression( "GetCameraMargin", JassSyntaxFactory.ArgumentList(JassSyntaxFactory.VariableExpression("CAMERA_MARGIN_TOP"))))), JassSyntaxFactory.VariableDefinition( JassSyntaxFactory.ParseTypeName("real"), "bottom", JassSyntaxFactory.BinaryAdditionExpression( JassSyntaxFactory.ConstantExpression(bottom), JassSyntaxFactory.InvocationExpression( "GetCameraMargin", JassSyntaxFactory.ArgumentList(JassSyntaxFactory.VariableExpression("CAMERA_MARGIN_BOTTOM")))))), statements.ToArray())); }
public override void BuildConfigFunction(string path, string mapName, string mapDescription, string lobbyMusic, params PlayerSlot[] playerSlots) { var fileSyntax = JassSyntaxFactory.File(GetConfigFunctionSyntax(mapName, mapDescription, lobbyMusic, playerSlots)); RenderFunctionToFile(path, fileSyntax); }
public override void BuildMainFunction(string path, float left, float right, float top, float bottom, Tileset light, SoundEnvironment sound, params string[] initFunctions) { var fileSyntax = JassSyntaxFactory.File(GetMainFunctionSyntax(left, right, top, bottom, light, sound, initFunctions)); RenderFunctionToFile(path, fileSyntax); }
private FunctionSyntax GetConfigFunctionSyntax(string mapName, string mapDescription, string lobbyMusic, params PlayerSlot[] playerSlots) { var statements = new List <NewStatementSyntax>() { JassSyntaxFactory.CallStatement("SetMapName", JassSyntaxFactory.ConstantExpression(mapName)), JassSyntaxFactory.CallStatement("SetMapDescription", JassSyntaxFactory.ConstantExpression(mapDescription)), JassSyntaxFactory.CallStatement("SetPlayers", JassSyntaxFactory.ConstantExpression(playerSlots.Length)), JassSyntaxFactory.CallStatement("SetTeams", JassSyntaxFactory.ConstantExpression(playerSlots.Length)), JassSyntaxFactory.CallStatement("SetGamePlacement", JassSyntaxFactory.VariableExpression("MAP_PLACEMENT_TEAMS_TOGETHER")), }; if (lobbyMusic != null) { statements.Add(JassSyntaxFactory.CallStatement("PlayMusic", JassSyntaxFactory.ConstantExpression(lobbyMusic))); } for (var i = 0; i < playerSlots.Length; i++) { var playerSlot = playerSlots[i]; statements.Add(JassSyntaxFactory.CallStatement( "DefineStartLocation", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.ConstantExpression(i), JassSyntaxFactory.ConstantExpression(playerSlot.StartLocationX), JassSyntaxFactory.ConstantExpression(playerSlot.StartLocationY)))); statements.Add(JassSyntaxFactory.CallStatement( "SetPlayerStartLocation", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.InvocationExpression("Player", JassSyntaxFactory.ConstantExpression(i)), JassSyntaxFactory.ConstantExpression(i)))); statements.Add(JassSyntaxFactory.CallStatement( "ForcePlayerStartLocation", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.InvocationExpression("Player", JassSyntaxFactory.ConstantExpression(i)), JassSyntaxFactory.ConstantExpression(i)))); statements.Add(JassSyntaxFactory.CallStatement( "SetPlayerColor", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.InvocationExpression("Player", JassSyntaxFactory.ConstantExpression(i)), JassSyntaxFactory.InvocationExpression("ConvertPlayerColor", JassSyntaxFactory.ConstantExpression(i))))); statements.Add(JassSyntaxFactory.CallStatement( "SetPlayerRacePreference", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.InvocationExpression("Player", JassSyntaxFactory.ConstantExpression(i)), JassSyntaxFactory.VariableExpression(playerSlot.RacePreference)))); statements.Add(JassSyntaxFactory.CallStatement( "SetPlayerRaceSelectable", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.InvocationExpression("Player", JassSyntaxFactory.ConstantExpression(i)), JassSyntaxFactory.ConstantExpression(playerSlot.RaceSelectable)))); statements.Add(JassSyntaxFactory.CallStatement( "SetPlayerController", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.InvocationExpression("Player", JassSyntaxFactory.ConstantExpression(i)), JassSyntaxFactory.VariableExpression(playerSlot.Controller)))); statements.Add(JassSyntaxFactory.CallStatement( "SetPlayerTeam", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.InvocationExpression("Player", JassSyntaxFactory.ConstantExpression(i)), JassSyntaxFactory.ConstantExpression(playerSlot.Team)))); statements.Add(JassSyntaxFactory.CallStatement( "SetStartLocPrioCount", JassSyntaxFactory.ArgumentList( JassSyntaxFactory.ConstantExpression(i), JassSyntaxFactory.ConstantExpression(0)))); } return(JassSyntaxFactory.Function( JassSyntaxFactory.FunctionDeclaration("config"), statements.ToArray())); }