Skip to content

Commit

Permalink
Major refactor of Jass Decompiler for ObjectManager data (units, item…
Browse files Browse the repository at this point in the history
…s, regions, cameras, sounds)
  • Loading branch information
speige committed Dec 17, 2024
1 parent 6c74fc1 commit a683b13
Show file tree
Hide file tree
Showing 22 changed files with 1,713 additions and 1,414 deletions.
21 changes: 21 additions & 0 deletions src/War3Net.Build/Extensions/SoundExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// ------------------------------------------------------------------------------
// <copyright file="RegionExtensions.cs" company="Drake53">
// Licensed under the MIT license.
// See the LICENSE file in the project root for more information.
// </copyright>
// ------------------------------------------------------------------------------

using War3Net.Build.Audio;
using War3Net.Build.Environment;

namespace War3Net.Build.Extensions
{

public static class SoundExtensions
{
public static string GetVariableName(this Sound sound)
{
return $"gg_snd_{sound.Name.Replace(' ', '_')}";
}
}
}
2 changes: 1 addition & 1 deletion src/War3Net.Build/Extensions/UnitDataExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static class UnitDataExtensions

public static string GetVariableName(this UnitData unitData)
{
return $"gg_unit_{unitData.TypeId.ToRawcode()}_{unitData.CreationNumber:D4}";
return $"{(unitData.IsItem() ? "gg_item_" : "gg_unit_")}{unitData.TypeId.ToRawcode()}_{unitData.CreationNumber:D4}";
}

public static string GetDropItemsFunctionName(this UnitData unitData, int id)
Expand Down
4 changes: 4 additions & 0 deletions src/War3Net.Build/War3Net.Build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@
<PackageReference Include="War3Net.CodeAnalysis.Transpilers" Version="$(War3NetCodeAnalysisTranspilersVersion)" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\War3Net.CodeAnalysis.Decompilers\War3Net.CodeAnalysis.Decompilers.csproj" />
</ItemGroup>

</Project>
661 changes: 326 additions & 335 deletions src/War3Net.CodeAnalysis.Decompilers/Audio/MapSoundsDecompiler.cs

Large diffs are not rendered by default.

121 changes: 85 additions & 36 deletions src/War3Net.CodeAnalysis.Decompilers/DecompilationContext.cs
Original file line number Diff line number Diff line change
@@ -1,56 +1,35 @@
// ------------------------------------------------------------------------------
// <copyright file="DecompilationContext.cs" company="Drake53">
//
// Licensed under the MIT license.
// See the LICENSE file in the project root for more information.
// </copyright>
// ------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;

using War3Net.Build;
using War3Net.Build.Info;
using War3Net.Build.Script;
using War3Net.CodeAnalysis.Jass;
using War3Net.CodeAnalysis.Jass.Syntax;

namespace War3Net.CodeAnalysis.Decompilers
{
internal sealed class DecompilationContext
public class DecompilationContext
{
public DecompilationContext(Map map, Campaign? campaign, TriggerData? triggerData)
public DecompilationContext(JassCompilationUnitSyntax compilationUnit, DecompileOptions options = null, MapInfo mapInfo = null, TriggerData triggerData = null)
{
if (map is null)
{
throw new ArgumentNullException(nameof(map));
}

if (map.Info is null)
{
throw new Exception();
}

if (map.Info.ScriptLanguage != ScriptLanguage.Jass)
{
throw new Exception();
}
CompilationUnit = compilationUnit;
Options = options ?? new DecompileOptions();
MapInfo = mapInfo;

if (string.IsNullOrEmpty(map.Script))
{
throw new Exception();
}

ObjectData = new ObjectDataContext(map, campaign);
TriggerData = new TriggerDataContext(triggerData);

var compilationUnit = JassSyntaxFactory.ParseCompilationUnit(map.Script);

var comments = new List<JassCommentSyntax>();
var functionDeclarationsBuilder = ImmutableDictionary.CreateBuilder<string, FunctionDeclarationContext>(StringComparer.Ordinal);
var variableDeclarationsBuilder = ImmutableDictionary.CreateBuilder<string, VariableDeclarationContext>(StringComparer.Ordinal);

foreach (var declaration in compilationUnit.Declarations)
foreach (var declaration in CompilationUnit.Declarations)
{
if (declaration is JassCommentSyntax comment)
{
Expand Down Expand Up @@ -80,21 +59,91 @@ public DecompilationContext(Map map, Campaign? campaign, TriggerData? triggerDat
FunctionDeclarations = functionDeclarationsBuilder.ToImmutable();
VariableDeclarations = variableDeclarationsBuilder.ToImmutable();


ImportedFileNames = new(StringComparer.OrdinalIgnoreCase);
MaxPlayerSlots = mapInfo != null && mapInfo.EditorVersion >= EditorVersion.v6060 ? 24 : 12;
}

public TriggerDataContext TriggerData { get; }
public ImmutableDictionary<string, FunctionDeclarationContext> FunctionDeclarations { get; }
public ImmutableDictionary<string, VariableDeclarationContext> VariableDeclarations { get; }
public HashSet<string> ImportedFileNames { get; }
public int MaxPlayerSlots { get; }

public HashSet<IStatementLineSyntax> HandledStatements = new HashSet<IStatementLineSyntax>();
public JassCompilationUnitSyntax CompilationUnit { get; }
public MapInfo MapInfo { get; }
public DecompileOptions Options { get; }

MaxPlayerSlots = map.Info.EditorVersion >= EditorVersion.v6060 ? 24 : 12;
private readonly Dictionary<string, object> _variableNameToValueMapping = new();
private readonly List<object> _values = new();
private int _lastCreationNumber;

public int GetNextCreationNumber()
{
return _lastCreationNumber++;
}

public ObjectDataContext ObjectData { get; }
public string GetVariableName(object value)
{
return _variableNameToValueMapping.FirstOrDefault(x => x.Value == value).Key;
}

public TriggerDataContext TriggerData { get; }
public void Add<T>(T value, string variableName = null) where T : class
{
if (variableName != null)
{
_variableNameToValueMapping[variableName] = value;
}

public ImmutableDictionary<string, FunctionDeclarationContext> FunctionDeclarations { get; }
_values.Add(value);
}

public ImmutableDictionary<string, VariableDeclarationContext> VariableDeclarations { get; }
public void Add_Struct<T>(T value, string variableName = null) where T : struct
{
Add(new Nullable_Class<T>(value), variableName);
}

public HashSet<string> ImportedFileNames { get; }
public T Get<T>(string variableName) where T : class
{
if (variableName == null)
{
return default;
}

return _variableNameToValueMapping.GetValueOrDefault(variableName) as T;
}

public Nullable_Class<T> Get_Struct<T>(string variableName = null) where T : struct
{
return Get<Nullable_Class<T>>(variableName);
}

public T GetLastCreated<T>() where T : class
{
return _values.OfType<T>().LastOrDefault();
}

public Nullable_Class<T> GetLastCreated_Struct<T>() where T : struct
{
return GetLastCreated<Nullable_Class<T>>();
}

public IEnumerable<T> GetAll<T>() where T : class
{
return _values.OfType<T>();
}

public IEnumerable<Nullable_Class<T>> GetAll_Struct<T>() where T : struct
{
return GetAll<Nullable_Class<T>>();
}

private const string PSEUDO_VARIABLE_PREFIX = "##PSEUDO_VARIABLE_PREFIX##";
internal string CreatePseudoVariableName(string type, string name = "")
{
return PSEUDO_VARIABLE_PREFIX + "_" + type.ToString() + "_" + name;
}

public int MaxPlayerSlots { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// ------------------------------------------------------------------------------
//
// Licensed under the MIT license.
// See the LICENSE file in the project root for more information.
//
// ------------------------------------------------------------------------------

using War3Net.Build.Audio;
using War3Net.Build.Environment;
using War3Net.Build.Widget;

namespace War3Net.CodeAnalysis.Decompilers
{
public class DecompileOptions
{
public MapCamerasFormatVersion mapCamerasFormatVersion;
public bool mapCamerasUseNewFormat;
public MapRegionsFormatVersion mapRegionsFormatVersion;
public MapSoundsFormatVersion mapSoundsFormatVersion;
public MapWidgetsFormatVersion mapWidgetsFormatVersion;
public MapWidgetsSubVersion mapWidgetsSubVersion;
public bool mapWidgetsUseNewFormat = default;
public SpecialDoodadVersion specialDoodadVersion;
}
}
Loading

0 comments on commit a683b13

Please sign in to comment.