reword because the way I worded it was misinformation |
m this shit is NOT MARKDOWN |
||
(3 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 | 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 | 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 | since <code>type</code> is dynamic, these things ~do~ need to be reflected in a local sense--you can't invoke a <code>function<T>()</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