Skip to content

Instantly share code, notes, and snippets.

@SChinchi
Forked from yekoc/RoR2AssetDump.cs
Last active May 19, 2024 20:51
Show Gist options
  • Save SChinchi/7dd6b321807e9166b65705e6aec96634 to your computer and use it in GitHub Desktop.
Save SChinchi/7dd6b321807e9166b65705e6aec96634 to your computer and use it in GitHub Desktop.
Label game object children as `currentIndex / total`
Awake of your mod
RoR2Application.onLoad += Thing;
private static bool IsNetworkBaseType(Type type)
{
return type.BaseType != null && type.BaseType == typeof(UnityEngine.Networking.NetworkBehaviour);
}
private static bool HasValidBaseType(Type type)
{
return type.BaseType != null
&& type.BaseType != typeof(UnityEngine.Object)
&& type.BaseType != typeof(UnityEngine.Component);
}
private static List<FieldInfo> GetOrderedFields(Type type)
{
var results = type.GetFields((BindingFlags)(-1)).ToList();
if (IsNetworkBaseType(type))
{
// Skip NetworkBehaviour because it's mostly noise
results.InsertRange(0, GetOrderedFields(type.BaseType.BaseType));
}
else if (HasValidBaseType(type))
{
results.InsertRange(0, GetOrderedFields(type.BaseType));
}
return results;
}
private static List<PropertyInfo> GetOrderedProperties(Type type)
{
var results = type.GetProperties((BindingFlags)(-1)).ToList();
if (IsNetworkBaseType(type))
{
// Skip NetworkBehaviour because it's mostly noise
results.InsertRange(0, GetOrderedProperties(type.BaseType.BaseType));
}
else if (HasValidBaseType(type))
{
results.InsertRange(0, GetOrderedProperties(type.BaseType));
}
return results;
}
public static void OutputComponents(StringBuilder sb, Component[] components, string delimi)
{
foreach (Component component in components)
{
OutputUnityObject(sb, component, delimi);
}
}
public static void OutputUnityObject(StringBuilder sb, UnityEngine.Object unityObject, string delimi)
{
string ParsePoolEntries(DccsPool.PoolEntry[] entries)
{
return "[" + string.Join(", ", entries.Select(x => $"({x.dccs.name}, {x.weight})")) + "]";
}
string ParseConditionalPoolEntries(DccsPool.ConditionalPoolEntry[] entries)
{
return "[" + string.Join(", ", entries.Select(x => $"({x.dccs.name}, {x.weight}, [{string.Join(", ", x.requiredExpansions.Select(x => x.name))}])")) + "]";
}
sb.Append($"\n{delimi} ");
if (unityObject is RectTransform rectTransform)
{
var transformOutput = $"RectTransform = p: {rectTransform.localPosition} r: {rectTransform.eulerAngles} s: {rectTransform.localScale}";
transformOutput += $"\n{delimi}v anchored3D: {rectTransform.anchoredPosition3D} pivot: {rectTransform.pivot} offsetMin: {rectTransform.offsetMin} offsetMax: {rectTransform.offsetMax}";
sb.AppendLine(transformOutput);
}
else if (unityObject is Transform transform)
{
var transformOutput = $"Transform = p: {transform.localPosition} r: {transform.eulerAngles} s: {transform.localScale}";
sb.AppendLine(transformOutput);
}
else if (unityObject is EntityStateConfiguration esc)
{
sb.AppendLine("EntityStateConfiguration: " + esc.targetType.LookupType().Name);
if (!esc.serializedFieldsCollection.serializedFields.Any())
{
sb.AppendLine($"{delimi} <Empty>");
}
else
{
foreach (var field in esc.serializedFieldsCollection.serializedFields)
{
try
{
var fieldOutput = $"{delimi}v {field.fieldName} = {(field.fieldValue.objectValue ? field.fieldValue.objectValue : field.fieldValue.stringValue)}";
sb.AppendLine(fieldOutput);
}
catch (Exception e)
{
//R2API.LogError(e);
}
}
}
}
else
{
Type type = unityObject.GetType();
sb.AppendLine(type.FullName);
foreach (FieldInfo fieldInfo in GetOrderedFields(type))
{
if (fieldInfo.Name.Contains("k__BackingField"))
{
continue;
}
try
{
string fieldOutput;
if (unityObject is not RoR2.Navigation.NodeGraph && typeof(System.Collections.ICollection).IsAssignableFrom(fieldInfo.FieldType))
{ //Nodegraphs are too meaninglessly large to expand,consider finding some method of visualisation if you wish to analyze them.
fieldOutput = $"{delimi}v {fieldInfo.Name} = ";
var collection = fieldInfo.GetValue(unityObject);
if (collection != null)
{
fieldOutput = $"{delimi}v {fieldInfo.Name} = {{ ";
foreach (var value in collection as System.Collections.IEnumerable)
{
if (value is DccsPool.Category dpCategory)
{
fieldOutput += $"{{name: {dpCategory.name}, weight: {dpCategory.categoryWeight}, always: {ParsePoolEntries(dpCategory.alwaysIncluded)}, if: {ParseConditionalPoolEntries(dpCategory.includedIfConditionsMet)}, ifno: {ParsePoolEntries(dpCategory.includedIfNoConditionsMet)}}}";
fieldOutput += "\n";
}
else if (value is DirectorCardCategorySelection.Category category)
{
fieldOutput += $"{{name: {category.name}, weight: {category.selectionWeight}, cards: [{string.Join(", ", category.cards.Select(card => $"({card.spawnCard.name}, {card.selectionWeight})"))}]}}";
fieldOutput += "\n";
}
else if (value is RangeFloat range)
{
fieldOutput += $"{{min: {range.min}, max: {range.max}}}";
fieldOutput += ", ";
}
else if (value is RoR2.Skills.SkillFamily.Variant variant)
{
fieldOutput += $"{variant.skillDef}";
fieldOutput += ", ";
}
else
{
fieldOutput += value;
fieldOutput += ", ";
}
}
fieldOutput = fieldOutput.TrimEnd(' ', ',', '\n');
fieldOutput += " }";
}
}
else if (fieldInfo.FieldType == typeof(EntityStates.SerializableEntityStateType))
{
var stateType = (EntityStates.SerializableEntityStateType)fieldInfo.GetValue(unityObject);
fieldOutput = $"{delimi}v {fieldInfo.Name} = {stateType.stateType}";
}
else if (fieldInfo.FieldType.IsSubclassOf(typeof(BaseConVar)))
{
fieldOutput = $"{delimi}v {fieldInfo.Name} = {((BaseConVar)fieldInfo.GetValue(unityObject)).GetString()}";
}
else
{
fieldOutput = $"{delimi}v {fieldInfo.Name} = {fieldInfo.GetValue(unityObject)}";
}
sb.AppendLine(fieldOutput);
}
catch (Exception e)
{
//R2API.Logger.LogError(e);
}
}
foreach (PropertyInfo propertyInfo in GetOrderedProperties(type))
{
if (propertyInfo.Name == "renderingDisplaySize" && unityObject is Canvas)
{ //Crash-preventation
continue;
}
try
{
if (propertyInfo.GetAccessors() != null && propertyInfo.GetAccessors().Length > 0)
{
var fieldOutput = $"{delimi}v {propertyInfo.Name} = {propertyInfo.GetValue(unityObject)}";
sb.AppendLine(fieldOutput);
}
}
catch (Exception e)
{
if (e.InnerException != null)
{
if (e.InnerException is NullReferenceException || e.InnerException is ArgumentNullException)
{
// Lots of properties internally refer to a field that is instantiated on Awake
sb.AppendLine($"{delimi}v {propertyInfo.Name} = ");
continue;
}
else if (e.InnerException is NotImplementedException)
{
// Ignore the error for some ScriptableObjects' name property
continue;
}
}
//R2API.Logger.LogError(e);
}
}
}
}
public static void GetChildren(StringBuilder sb, Transform transform, string delimi)
{
for (var i = 0; i < transform.childCount; i++)
{
GameObject gameObject = transform.GetChild(i).gameObject;
var childGameObjectHeader = $"\n{delimi}GameObject Child {i}/{transform.childCount}: {gameObject.name}";
sb.AppendLine(childGameObjectHeader);
Component[] components = gameObject.GetComponents<Component>();
OutputComponents(sb, components, delimi + ">");
GetChildren(sb, transform.GetChild(i), delimi + ">");
}
}
private static void Thing()
{
UnityEngine.Object assetlazy = Addressables.LoadAssetAsync<UnityEngine.Object>("RoR2/Base/Huntress/Skins.Huntress.Alt1.asset").WaitForCompletion();
R2API.Logger.LogWarning(assetlazy);
var i = 0;
foreach (UnityEngine.AddressableAssets.ResourceLocators.IResourceLocator item in Addressables.ResourceLocators)
{
foreach (var key in item.Keys)
{
try
{
i++;
if (key.ToString().Contains("bundle"))
{
continue;
}
if (!key.ToString().Contains("."))
{
}
else
{
var digitCount = 0;
foreach (var c in key.ToString())
{
if (char.IsDigit(c))
{
digitCount++;
if (digitCount > 5)
{
break;
}
}
}
if (digitCount > 5)
{
continue;
}
R2API.Logger.LogWarning(i + " | " + key.ToString());
UnityEngine.Object asset = Addressables.LoadAssetAsync<UnityEngine.Object>(key).WaitForCompletion();
if (asset)
{
var sb = new StringBuilder();
sb.AppendLine("Key Path : " + key.ToString() + " | UnityObject Type : " + asset.GetType() + " | UnityObject Name : " + asset.name);
if (asset is GameObject go)
{
Component[] components = go.GetComponents<Component>();
OutputComponents(sb, components, ">");
GetChildren(sb, go.transform, ">");
DumpToFile(key, sb);
}
else if (asset is UnityEngine.Object unityObject)
{
OutputUnityObject(sb, unityObject, ">");
DumpToFile(key, sb);
}
}
}
}
catch (Exception e)
{
R2API.Logger.LogError(e);
}
}
}
}
private static void DumpToFile(object key, StringBuilder sb)
{
const string dumpFolder = @"folder_path";
var relativeFilePathTxt = System.IO.Path.ChangeExtension(key.ToString(), ".txt");
var fullFilePath = System.IO.Path.Combine(dumpFolder, relativeFilePathTxt);
var directoryPath = System.IO.Path.GetDirectoryName(fullFilePath);
Directory.CreateDirectory(directoryPath);
File.WriteAllText(fullFilePath, sb.ToString());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment