User:Yosh/Weird things in decompilation: Difference between revisions

From Resonite Wiki
m this shit isn't markdown
m this shit is NOT MARKDOWN
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
this documents weird things I've seen (or friends of mine have seen) in decompilation of Resonite. I will try to focus on more higher-level stuff rather than specific code flow, since specific code flow is very subject to decompilation artifacts
this documents weird things I've seen (or friends of mine have seen) in decompilation of Resonite. I will try to focus on more higher-level stuff rather than specific code flow, since specific code flow is very subject to decompilation artifacts


some of these might be debug stuff left in development, some might just be old tech debt, some might have been written when the author was tired, some I probably just don't know the overarching reason for and will learn later since I'm still not quite versed in c#. things happen. this page is made with no ill intent. It's just something that's not really appropriate for GitHub issues or Resonance questions. it's more of a learning experience
there isn't any real intent in this page. some of this stuff I can confidently wonder why it was done, others I am not confident. it's more like a... bookmark kind of thing? things to look and delve into later, since I'm endlessly learning the very expansive language that is C# and decompilation provides zero comments and artifacts that make following flow a bit harder than source.


== FrooxEngine ==
== FrooxEngine ==
Line 17: Line 17:
</syntaxhighlight>
</syntaxhighlight>


these are only used within `SettingsDataFeed` itself, built during the constructor:
these are only used within <code>SettingsDataFeed</code> itself, built during the constructor:


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 80: Line 80:
</syntaxhighlight>
</syntaxhighlight>


since <code>type</code> is dynamic, these things have to be reflected in the scope of this feed, but I do wonder if there's a better way to go about it
since <code>type</code> is dynamic, these things ~do~ need to be reflected in a local sense--you can't invoke a <code>function&lt;T&gt;()</code> dynamically, but I do wonder if there's a slightly more elegant way to go about it than this

Latest revision as of 17:58, 11 July 2025

this documents weird things I've seen (or friends of mine have seen) in decompilation of Resonite. I will try to focus on more higher-level stuff rather than specific code flow, since specific code flow is very subject to decompilation artifacts

there isn't any real intent in this page. some of this stuff I can confidently wonder why it was done, others I am not confident. it's more like a... bookmark kind of thing? things to look and delve into later, since I'm endlessly learning the very expansive language that is C# and decompilation provides zero comments and artifacts that make following flow a bit harder than source.

FrooxEngine

SettingsDataFeed

there appears to be some private static MethodInfo fields on this component:

private static MethodInfo _generateValueField;
private static MethodInfo _generateEnumField;
private static MethodInfo _generateSlider;
private static MethodInfo _generateQuantityField;
private static MethodInfo _generateIndicator;

these are only used within SettingsDataFeed itself, built during the constructor:

static SettingsDataFeed()
{
	Type typeFromHandle = typeof(SettingsDataFeed);
	BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
	_generateValueField = typeFromHandle.GetMethod("GenerateValueField", bindingAttr);
	_generateEnumField = typeFromHandle.GetMethod("GenerateEnumField", bindingAttr);
	_generateSlider = typeFromHandle.GetMethod("GenerateSlider", bindingAttr);
	_generateQuantityField = typeFromHandle.GetMethod("GenerateQuantityField", bindingAttr);
	_generateIndicator = typeFromHandle.GetMethod("GenerateIndicator", bindingAttr);
}

and only used in the static GenerateItem function:

private static DataFeedItem GenerateItem(FieldIdentity identity, SettingPropertyAttribute setting, IReadOnlyList<string> path, IReadOnlyList<string> grouping)
{
	Type fieldType = identity.field.FieldType;
	if (setting is SettingSubcategoryListAttribute settingSubcategoryListAttribute) {
		DataFeedCategory dataFeedCategory = new DataFeedCategory();
		InitBase(dataFeedCategory, identity, setting, path, grouping);
		dataFeedCategory.SetOverrideSubpath(identity.settingType.Name + "." + identity.field.Name);
		if (settingSubcategoryListAttribute.EnabledProperty != null) {
			FieldIdentity fieldIdentity = new FieldIdentity();
			fieldIdentity.InitBaseFrom(identity);
			fieldIdentity.field = identity.settingType.GetField(settingSubcategoryListAttribute.EnabledProperty);
			dataFeedCategory.InitEnabled(GenerateFieldSync<bool>(fieldIdentity));
		}
		return dataFeedCategory;
	}
	foreach (Type item in fieldType.EnumerateInterfacesRecursively()) {
		if (item.IsGenericType && item.GetGenericTypeDefinition() == typeof(IField<>)) {
			Type type = item.GetGenericArguments()[0];
			if (setting is SettingIndicatorProperty) {
				return (DataFeedItem)_generateIndicator.MakeGenericMethod(type).Invoke(null, new object[4] { identity, setting, path, grouping });
			}
			if (type == typeof(bool)) {
				DataFeedToggle dataFeedToggle = new DataFeedToggle();
				InitBase(dataFeedToggle, identity, setting, path, grouping);
				dataFeedToggle.InitSetupValue(GenerateFieldSync<bool>(identity));
				return dataFeedToggle;
			}
			if (type.IsEnum) {
				return (DataFeedItem)_generateEnumField.MakeGenericMethod(type).Invoke(null, new object[4] { identity, setting, path, grouping });
			}
			RangeAttribute customAttribute = identity.field.GetCustomAttribute<RangeAttribute>();
			QuantityAttribute customAttribute2 = identity.field.GetCustomAttribute<QuantityAttribute>();
			if (customAttribute2 != null) {
				return (DataFeedItem)_generateQuantityField.MakeGenericMethod(customAttribute2.QuantityType, type).Invoke(null, new object[6] { identity, setting, customAttribute2, customAttribute, path, grouping });
			}
			if (customAttribute != null) {
				return (DataFeedItem)_generateSlider.MakeGenericMethod(type).Invoke(null, new object[5] { identity, setting, customAttribute, path, grouping });
			}
			return (DataFeedItem)_generateValueField.MakeGenericMethod(type).Invoke(null, new object[4] { identity, setting, path, grouping });
		}
	}
	return new DataFeedLabel(identity.field.Name, path, grouping, "<color=red>" + identity.field.Name + " (" + identity.field.FieldType.GetNiceName() + ")</color>");
}

since type is dynamic, these things ~do~ need to be reflected in a local sense--you can't invoke a function<T>() dynamically, but I do wonder if there's a slightly more elegant way to go about it than this