utils/AttributesParser.cs

Generic parser that scans a source file for attribute-decorated fields (float, float2/3/4, Texture2D and DynamicCombo) and populates dictionaries of parsed default values. It uses a provided IAttributeTypeSet to parse or supply Particle/Native float and color types, and parses vector defaults from text.

File AccessObfuscated Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Sandbox;

public class AttributesParser<TFloat, TGradient>
{
	private readonly IAttributeTypeSet<TFloat, TGradient> _typeSet;
	public AttributesParser(IAttributeTypeSet<TFloat, TGradient> typeSet)
	{
		if (!((typeof(TFloat) == typeof(ParticleFloat) && typeof(TGradient) == typeof(ParticleGradient)) ||
		      (typeof(TFloat) == typeof(float) && typeof(TGradient) == typeof(Color))))
		{
			throw new InvalidOperationException("Only Particle or Native types allowed.");
		}
		_typeSet = typeSet;
	}
	public Dictionary<String, TGradient> Colors { get; set; }
	
	public Dictionary<String, TFloat> Floats { get; set; }
	
	public Dictionary<String, Vector2> Floats2 { get; set; }

	public Dictionary<String, Vector3> Floats3 { get; set; }
	
	public Dictionary<String, Vector4> Floats4 { get; set; }
	
	public Dictionary<String, Texture> Textures { get; set; }
	
	public Dictionary<String, int> DynamicCombos { get; set; }


	private const string AttributesPattern = @"(float(?:[2,3,4])?|Texture2D) +.+ +< *Attribute\(.?""(.+)"".?\)\;(?:[^>]*?Default(?:[1,2,3,4])?\(([^)]*)\))?[^>]*>\;";
	private const string DynamicComboPattern = "DynamicCombo\\(([^,]+),.+\\)\\;";

	public void ParseAttributes( string filePath )
	{
		string fileContent = FileSystem.Mounted.ReadAllText( filePath );
		var attributeMatches = Regex.Matches(fileContent, AttributesPattern);
		var dynamicComboMatches = Regex.Matches(fileContent, DynamicComboPattern);

		foreach ( Match match in dynamicComboMatches )
		{
			var value = match.Groups[1].Value.Trim();
			if(!DynamicCombos.ContainsKey(value)) DynamicCombos.Add(value, 0);
		}

		foreach (Match match in attributeMatches)
		{
			var type = match.Groups[1].Value;
			var value = match.Groups[2].Value;
			var defaultValue = match.Groups[3].Value;
			SetAttribute(type, value, defaultValue);
		}
	}

	private void SetAttribute( string attributeType, string attributeName, string defaultValue )
	{

		switch ( attributeType )
		{
			case "float":
				if ( !Floats.ContainsKey( attributeName ) ) SetFloat( attributeName, defaultValue );
				break;
			case "float2":
				if ( !Floats2.ContainsKey( attributeName ) ) SetFloat2( attributeName, defaultValue );
				break;
			case "float3":
				if ( !Floats3.ContainsKey( attributeName ) ) SetFloat3( attributeName, defaultValue );
				break;
			case "float4":
				if ( !Floats4.ContainsKey( attributeName ) && !Colors.ContainsKey( attributeName ) ) SetFloat4( attributeName );
				break;
			case "Texture2D":
				if ( !Textures.ContainsKey( attributeName ) ) Textures.Add( attributeName, Texture.White );
				break;
			default: break;
		}
	}

	private void SetFloat( string attributeName, string defaultValue )
	{
		TFloat value = !string.IsNullOrEmpty( defaultValue )
			? _typeSet.ParseFloat( defaultValue )
			: _typeSet.GetDefaultFloat();
		Floats.Add( attributeName, value );
	}

	private void SetFloat2( string attributeName, string defaultValue )
	{
		Vector2 value = !string.IsNullOrEmpty( defaultValue )
			? ParseVector2( defaultValue )
			: new Vector2();
		Floats2.Add( attributeName, value );
	}

	private void SetFloat3( string attributeName, string defaultValue )
	{
		Vector3 value = !string.IsNullOrEmpty( defaultValue )
			? ParseVector3( defaultValue )
			: new Vector3();
		Floats3.Add( attributeName, value );
	}

	private static Vector2 ParseVector2( string raw )
	{
		var p = raw.Split( ',' );
		return new Vector2(
			float.Parse( p[0].Trim(), System.Globalization.CultureInfo.InvariantCulture ),
			float.Parse( p[1].Trim(), System.Globalization.CultureInfo.InvariantCulture )
		);
	}

	private static Vector3 ParseVector3( string raw )
	{
		var p = raw.Split( ',' );
		return new Vector3(
			float.Parse( p[0].Trim(), System.Globalization.CultureInfo.InvariantCulture ),
			float.Parse( p[1].Trim(), System.Globalization.CultureInfo.InvariantCulture ),
			float.Parse( p[2].Trim(), System.Globalization.CultureInfo.InvariantCulture )
		);
	}

	private void SetFloat4( string attributeName)
	{
		if ( attributeName.ToLower().Contains( "color" ) )
		{
			Colors.Add( attributeName, _typeSet.GetDefaultColor() );
		}
		else
		{
			Floats4.Add( attributeName, new Vector4(  ) );	
		}
		
	}
}