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);
        }
Exemple #2
0
            /// <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()
            });
        }
Exemple #4
0
 AssemblyRef TryResolveAssembly(UTF8String name)
 {
     return(TargetModule.GetAssemblyRef(name) ?? TargetModule.Context.AssemblyResolver.Resolve(new AssemblyRefUser(name), TargetModule).ToAssemblyRef());
 }