2025-09-17 16:40:02 -07:00

58 lines
2.6 KiB
C#

using AssetRipper.AssemblyDumper.Attributes;
using AssetRipper.AssemblyDumper.Methods;
using AssetRipper.AssemblyDumper.Types;
namespace AssetRipper.AssemblyDumper.Passes;
public static class Pass555_CreateCommonString
{
public static void DoPass()
{
ThrowIfStringCountIsWrong();
TypeDefinition newTypeDef = StaticClassCreator.CreateEmptyStaticClass(SharedState.Instance.Module, SharedState.RootNamespace, "CommonString");
GenericInstanceTypeSignature readOnlyUintStringDictionary = SharedState.Instance.Importer.ImportType(typeof(IReadOnlyDictionary<,>))
.MakeGenericInstanceType(SharedState.Instance.Importer.UInt32, SharedState.Instance.Importer.String);
GenericInstanceTypeSignature uintStringDictionary = SharedState.Instance.Importer.ImportType(typeof(Dictionary<,>))
.MakeGenericInstanceType(SharedState.Instance.Importer.UInt32, SharedState.Instance.Importer.String);
IMethodDefOrRef dictionaryConstructor = MethodUtils.MakeConstructorOnGenericType(SharedState.Instance.Importer, uintStringDictionary, 0);
IMethodDefOrRef addMethod = MethodUtils.MakeMethodOnGenericType(SharedState.Instance.Importer, uintStringDictionary, SharedState.Instance.Importer.LookupMethod(typeof(Dictionary<,>), m => m.Name == "Add"));
const string propertyName = "Dictionary";
FieldDefinition field = newTypeDef.AddField($"<{propertyName}>k__BackingField", readOnlyUintStringDictionary, true, Visibility.Private);
field.Attributes |= FieldAttributes.InitOnly;
field.AddCompilerGeneratedAttribute(SharedState.Instance.Importer);
MethodDefinition staticConstructor = newTypeDef.AddEmptyConstructor(true);
CilInstructionCollection instructions = staticConstructor.GetInstructions();
instructions.Add(CilOpCodes.Newobj, dictionaryConstructor);
foreach ((uint index, string str) in SharedState.Instance.CommonString.Strings)
{
instructions.Add(CilOpCodes.Dup);
instructions.Add(CilOpCodes.Ldc_I4, (int)index);
instructions.Add(CilOpCodes.Ldstr, str);
instructions.Add(CilOpCodes.Call, addMethod);
}
instructions.Add(CilOpCodes.Stsfld, field);
instructions.Add(CilOpCodes.Ret);
instructions.OptimizeMacros();
newTypeDef.ImplementGetterProperty(
propertyName,
MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.SpecialName,
readOnlyUintStringDictionary,
field)
.GetMethod!.AddCompilerGeneratedAttribute(SharedState.Instance.Importer);
}
private static void ThrowIfStringCountIsWrong()
{
int count = SharedState.Instance.CommonString.Strings.Count;
if (count != 112)
{
throw new Exception($"The size of Common String has changed! {count}");
}
}
}