private void LoadTypeDefinitions() { var assemblyName = typeof(Terraria.BitsByte).Assembly.GetName().Name; TerrariaAssembly = _module.GetAssemblyRef(assemblyName) ?? new AssemblyRefUser(assemblyName); ModTranslationType = new TypeRefUser(_module, typeof(Terraria.ModLoader.ModTranslation).Namespace, nameof(Terraria.ModLoader.ModTranslation), TerrariaAssembly); SetDefaultMethod = new MemberRefUser(_module, nameof(Terraria.ModLoader.ModTranslation.SetDefault), MethodSig.CreateInstance(_module.CorLibTypes.Void, _module.CorLibTypes.String), ModTranslationType); var gameCultureType = new TypeRefUser(_module, typeof(Terraria.Localization.GameCulture).Namespace, nameof(Terraria.Localization.GameCulture), TerrariaAssembly); AddTranslationMethod = new MemberRefUser(_module, nameof(Terraria.ModLoader.ModTranslation.AddTranslation), MethodSig.CreateInstance(_module.CorLibTypes.Void, new ClassSig(gameCultureType), _module.CorLibTypes.String), ModTranslationType); GameCultureField = new MemberRefUser(_module, _lang.ToString(), new FieldSig(new ClassSig(gameCultureType)), gameCultureType); GetTextValueMethod = new MemberRefUser(_module, nameof(Terraria.Localization.Language.GetTextValue), MethodSig.CreateStatic(_module.CorLibTypes.String, _module.CorLibTypes.String), new TypeRefUser(_module, typeof(Terraria.Localization.Language).Namespace, nameof(Terraria.Localization.Language), TerrariaAssembly)); var modType = new TypeRefUser(_module, typeof(Terraria.ModLoader.Mod).Namespace, nameof(Terraria.ModLoader.Mod), TerrariaAssembly); AddGlobalTranslationMethod = new MemberRefUser(_module, nameof(Terraria.ModLoader.Mod.AddTranslation), MethodSig.CreateInstance(_module.CorLibTypes.Void, new ClassSig(ModTranslationType)), modType); CreateGlobalTranslationMethod = new MemberRefUser(_module, nameof(Terraria.ModLoader.Mod.CreateTranslation), MethodSig.CreateInstance(new ClassSig(ModTranslationType), _module.CorLibTypes.String), modType); }
/// <inheritdoc /> public override ITypeDefOrRef Map(ITypeDefOrRef source) { if (DefMap.TryGetValue(source, out var mappedRef)) { return(mappedRef as ITypeDefOrRef); } // check if the assembly reference needs to be fixed. if (source is TypeRef sourceRef) { var targetAssemblyRef = TargetModule.GetAssemblyRef(sourceRef.DefinitionAssembly.Name); if (!(targetAssemblyRef is null) && !string.Equals(targetAssemblyRef.FullName, source.DefinitionAssembly.FullName, StringComparison.Ordinal)) { // We got a matching assembly by the simple name, but not by the full name. // This means the injected code uses a different assembly version than the target assembly. // We'll fix the assembly reference, to avoid breaking anything. var fixedTypeRef = new TypeRefUser(sourceRef.Module, sourceRef.Namespace, sourceRef.Name, targetAssemblyRef); return(Importer.Import(fixedTypeRef)); } } return(null); }
/// <summary> /// Initializes a new instance of TranslationEmitter. /// </summary> /// <param name="module">The module of the target assembly.</param> /// <param name="gameCulture">The game culture selection.</param> /// <param name="modName">The mod name.</param> public TranslationEmitter(ModuleDef module, string gameCulture, string modName) { _modName = modName; if (gameCulture == null) { throw new ArgumentNullException(nameof(gameCulture)); } Module = module ?? throw new ArgumentNullException(nameof(module)); var importer = new Importer(Module); var terraria = module.GetAssemblyRef("Terraria") ?? new AssemblyRefUser("Terraria", DefaultConfigurations.TerrariaVersion); _modTranslationType = new TypeRefUser(Module, "Terraria.ModLoader", "ModTranslation", terraria); _modTranslationSetDefaultMethod = new MemberRefUser(Module, "SetDefault", MethodSig.CreateInstance(Module.CorLibTypes.Void, Module.CorLibTypes.String), _modTranslationType); var gameCultureType = new TypeRefUser(Module, "Terraria.Localization", "GameCulture", terraria); _modTranslationAddTranslationMethod = new MemberRefUser(Module, "AddTranslation", MethodSig.CreateInstance(Module.CorLibTypes.Void, new ClassSig(gameCultureType), Module.CorLibTypes.String), _modTranslationType); _gameCultureField = new MemberRefUser(Module, gameCulture, new FieldSig(new ClassSig(gameCultureType)), gameCultureType); var languageType = new TypeRefUser(Module, "Terraria.Localization", "Language", terraria); _getTextValueMethod = new MemberRefUser(Module, "GetTextValue", MethodSig.CreateStatic(Module.CorLibTypes.String, Module.CorLibTypes.String), languageType); var modType = new TypeRefUser(Module, "Terraria.ModLoader", "Mod", terraria); _modAddTranslationMethod = new MemberRefUser(Module, "AddTranslation", MethodSig.CreateInstance(Module.CorLibTypes.Void, new ClassSig(_modTranslationType)), modType); _modCreateTranslationMethod = new MemberRefUser(Module, "CreateTranslation", MethodSig.CreateInstance(new ClassSig(_modTranslationType), Module.CorLibTypes.String), modType); var type = Module.Types.Single(x => string.Equals(x.BaseType?.FullName, "Terraria.ModLoader.Mod", StringComparison.Ordinal)); var ctor = importer.Import(typeof(CompilerGeneratedAttribute).GetConstructor(new Type[0])) as IMethodDefOrRef; _modSetTranslationMethod = new MethodDefUser(ModSetTranslationMethod, MethodSig.CreateInstance(Module.CorLibTypes.Void), MethodAttributes.Private); type.Methods.Add(_modSetTranslationMethod); _modSetTranslationMethod.CustomAttributes.Add(new CustomAttribute(ctor)); _modSetTranslationMethod.Body = new CilBody { Instructions = { OpCodes.Ret.ToInstruction() }, Variables = { new Local(new ClassSig(_modTranslationType), "translation", 0) } }; var loadMethod = type.FindMethod("Load", MethodSig.CreateInstance(Module.CorLibTypes.Void)); if (loadMethod?.HasBody != true) { Console.WriteLine("Could not find Mod.Load() method; trying to add one."); loadMethod = new MethodDefUser("Load", MethodSig.CreateInstance(Module.CorLibTypes.Void), MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual) { Body = new CilBody { Instructions = { OpCodes.Ret.ToInstruction() }, } }; type.Methods.Add(loadMethod); } loadMethod.Body.Instructions.AppendLast(new[] { OpCodes.Ldarg_0.ToInstruction(), OpCodes.Call.ToInstruction(_modSetTranslationMethod), OpCodes.Ret.ToInstruction() }); }
AssemblyRef TryResolveAssembly(UTF8String name) { return(TargetModule.GetAssemblyRef(name) ?? TargetModule.Context.AssemblyResolver.Resolve(new AssemblyRefUser(name), TargetModule).ToAssemblyRef()); }