internal LdstrFile MergeInternal(LdstrFile main, LdstrFile addition)
        {
            var result = new LdstrFile
            {
                LdstrEntries = new Dictionary <string, LdstrEntry>()
            };

            foreach (var e in main.LdstrEntries)
            {
                result.LdstrEntries.Add(e.Key, e.Value.Clone() as LdstrEntry);
            }

            foreach (var pair in addition.LdstrEntries)
            {
                if (result.LdstrEntries.ContainsKey(pair.Key))
                {
                    result.LdstrEntries[pair.Key] = Merge(main.LdstrEntries[pair.Key], pair.Value);
                }
                else
                {
                    result.LdstrEntries.Add(pair.Key, pair.Value);
                }
            }

            return(result);
        }
        protected override void ImportInternal(LdstrFile file, IMod mod, CultureInfo culture)
        {
            entries = new Dictionary <MethodBase, LdstrEntry>();

            var module    = mod.Code.ManifestModule;
            var entryDict = file.LdstrEntries;

            foreach (var entryPair in entryDict)
            {
                Utils.SafeWrap(() =>
                {
                    if (!HaveTranslation(entryPair.Value))
                    {
                        return;
                    }

                    Utils.LogDebug($"Finding method: [{entryPair.Key}]");
                    var method = module.FindMethod(entryPair.Key);
                    if (method == null)
                    {
                        Utils.LogDebug($"Cannot find.");
                        return;
                    }

                    entries.Add(method, entryPair.Value);

                    var transpiler = typeof(HarmonyLdstrImporter).GetMethod("Transpile", BindingFlags.NonPublic | BindingFlags.Static);

                    harmony.Patch(method, null, null, new HarmonyMethod(transpiler));
                    Utils.LogDebug($"Patched: {entryPair.Key}");
                });
            }
        }
Beispiel #3
0
        protected override void ImportInternal(LdstrFile file, IMod mod, CultureInfo culture)
        {
            entries = new Dictionary <MethodBase, LdstrEntry>();

            var module    = mod.Code.ManifestModule;
            var entryDict = file.LdstrEntries;

            foreach (var entryPair in entryDict)
            {
                Utils.SafeWrap(() =>
                {
                    if (!HaveTranslation(entryPair.Value))
                    {
                        return;
                    }

                    Utils.LogDebug($"Finding method: [{entryPair.Key}]");
                    var method = Utils.FindMethodByID(module, entryPair.Key);
                    if (method == null)
                    {
                        Utils.LogDebug($"Cannot find.");
                        return;
                    }

                    entries.Add(method, entryPair.Value);

                    harmony.Patch(method, transpiler: new HarmonyMethod(NoroHelper.MethodInfo(() => Transpile(null, null))));

                    Utils.LogDebug($"Patched: {entryPair.Key}");
                });
            }
        }
Beispiel #4
0
        public IFile Merge(IFile main, IFile addition)
        {
            if (main == null || main.GetType() != addition.GetType() || main.GetType() != typeof(LdstrFile))
            {
                return(null);
            }

            var mainFile     = main as LdstrFile;
            var additionFile = addition as LdstrFile;

            var result = new LdstrFile();

            result.LdstrEntries = new Dictionary <string, LdstrEntry>();
            foreach (var pair in additionFile.LdstrEntries)
            {
                if (mainFile.LdstrEntries.ContainsKey(pair.Key))
                {
                    result.LdstrEntries.Add(pair.Key, Merge(mainFile.LdstrEntries[pair.Key], pair.Value));
                }
                else
                {
                    result.LdstrEntries.Add(pair.Key, pair.Value);
                }
            }

            return(result);
        }
Beispiel #5
0
        public void Export(IPackage package, IExportConfig config)
        {
            if (package?.Mod == null)
            {
                return;
            }

            var modFile      = package.Mod.File;
            var asmManager   = "Terraria.ModLoader.Core.AssemblyManager".Type();
            var assemblyName = (string)asmManager.Invoke("GetModAssemblyFileName", modFile, true);
            var loadedMod    = asmManager.ValueOf("loadedMods").Invoke("get_Item", package.Mod.Name);
            var reref        = (byte[])asmManager.GetNestedType("LoadedMod", NoroHelper.Any).Method("EncapsulateReferences")
                               .Invoke(loadedMod, new object[] { modFile.GetBytes(assemblyName), null });
            var asm = AssemblyDefinition.ReadAssembly(new MemoryStream(reref));

            var file = new LdstrFile
            {
                LdstrEntries = new Dictionary <string, LdstrEntry>()
            };

            foreach (var type in asm.MainModule.GetTypes())
            {
                if (type.Namespace == null)
                {
                    continue;
                }

                foreach (var method in type.Methods)
                {
                    if (method.DeclaringType?.Namespace == null || method.IsAbstract)
                    {
                        continue;
                    }

                    try
                    {
                        LogDebug($"Exporting method: [{method.GetID()}]");
                        var entry = GetEntryFromMethod(method);
                        if (entry != null && !file.LdstrEntries.ContainsKey(method.GetID()))
                        {
                            file.LdstrEntries.Add(method.GetID(), entry);
                        }
                    }
                    catch (Exception e)
                    {
                        Localizer.Log.Error(e.ToString());
                    }
                }
            }

            package.AddFile(file);
        }
        protected override void ImportInternal(LdstrFile file, IMod mod, CultureInfo culture)
        {
            Terraria.ModLoader.ContentInstance.Register(Utils.GetModByName(mod.Name));
            var module = mod.Code.ManifestModule;

            var entryDict = file.LdstrEntries;

            foreach (var entryPair in entryDict)
            {
                var method = Utils.FindMethodByID(module, entryPair.Key);
                if (method == null)
                {
                    continue;
                }

                var e = entryPair.Value;

                if (!HaveTranslation(e))
                {
                    continue;
                }

                var modification = new ILContext.Manipulator(il =>
                {
                    foreach (var instruction in il.Instrs)
                    {
                        var ins = e.Instructions.FirstOrDefault(i => instruction.MatchLdstr(i.Origin));
                        if (ins == null || string.IsNullOrEmpty(ins.Translation))
                        {
                            continue;
                        }

                        instruction.Operand = ins.Translation;

                        foreach (var label in il.Labels)
                        {
                            if (label.Target.MatchLdstr(ins.Origin))
                            {
                                label.Target = instruction;
                            }
                        }
                    }
                });

                if (!modifications.ContainsKey(method))
                {
                    HookEndpointManager.Modify(method, modification);
                    modifications.Add(method, modification);
                }
            }
        }
Beispiel #7
0
        public void Export(IPackage package, IExportConfig config)
        {
            if (package?.Mod == null)
            {
                return;
            }

            var asm = package.Mod.Code;

            var file = new LdstrFile
            {
                LdstrEntries = new Dictionary <string, LdstrEntry>()
            };

            foreach (var type in asm.ManifestModule.GetTypes())
            {
                /* The return value of GetTypes() and other methods will include types they derived from.
                 * So we should check the namespace to ensure it belongs to the assembly, but there still are
                 * some issues. */
                if (type.Namespace == null || !type.Namespace.StartsWith(package.Mod.Name))
                {
                    continue;
                }

                foreach (var method in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static))
                {
                    if (method.DeclaringType?.Namespace == null || !method.DeclaringType.Namespace.StartsWith(
                            package.Mod.Name) ||
                        method.IsAbstract)
                    {
                        continue;
                    }

                    try
                    {
                        var entry = GetEntryFromMethod(method);
                        if (entry != null && !file.LdstrEntries.ContainsKey(method.GetID()))
                        {
                            file.LdstrEntries.Add(method.GetID(), entry);
                        }
                    }
                    catch (Exception e)
                    {
                        Localizer.Log.Error(e.ToString());
                    }
                }
            }

            package.AddFile(file);
        }
Beispiel #8
0
        public void Export(IPackage package, IExportConfig config)
        {
            if (package?.Mod == null)
            {
                return;
            }

            var asm = package.Mod.Code;

            var file = new LdstrFile
            {
                LdstrEntries = new Dictionary <string, LdstrEntry>()
            };

            foreach (var type in asm.ManifestModule.GetTypes())
            {
                if (type.Namespace == null)
                {
                    continue;
                }

                var methodBases = new List <MethodBase>();
                methodBases.AddRange(type.GetMethods(All | BindingFlags.DeclaredOnly));
                methodBases.AddRange(type.GetConstructors(All | BindingFlags.DeclaredOnly));
                foreach (var method in methodBases)
                {
                    if (method.DeclaringType?.Namespace == null || method.IsAbstract)
                    {
                        continue;
                    }

                    try
                    {
                        Utils.LogDebug($"Exporting method: [{method.GetID()}]");
                        var entry = GetEntryFromMethod(method);
                        if (entry != null && !file.LdstrEntries.ContainsKey(method.GetID()))
                        {
                            file.LdstrEntries.Add(method.GetID(), entry);
                        }
                    }
                    catch (Exception e)
                    {
                        Localizer.Log.Error(e.ToString());
                    }
                }
            }

            package.AddFile(file);
        }
Beispiel #9
0
 protected override void ImportInternal(LdstrFile file, IMod mod, CultureInfo culture)
 {
     Importing = true;
     try
     {
         ImportingFile = file;
         ImportingMod  = mod;
         if ((mod as LoadedModWrapper).wrapped.TryGetTarget(out var loadedMod))
         {
             loadedMod.Invoke("set_NeedsReload", true);
             loadedMod.Invoke("LoadAssemblies");
         }
     }
     finally
     {
         Importing = false;
     }
 }
Beispiel #10
0
        public void UpdateInternal(LdstrFile oldFile, LdstrFile newFile, IUpdateLogger logger)
        {
            var oldEntries = oldFile.LdstrEntries;
            var newEntries = newFile.LdstrEntries;

            foreach (var newEntryKey in newEntries.Keys)
            {
                if (oldEntries.Keys.Contains(newEntryKey))
                {
                    var o = oldEntries[newEntryKey];
                    var n = newEntries[newEntryKey];
                    foreach (var newIns in n.Instructions)
                    {
                        if (o.Instructions.Exists(oi => oi.Origin == newIns.Origin))
                        {
                            continue;
                        }

                        o.Instructions.Add(newIns);
                        logger.Change($"New instruction of {newEntryKey}: [{newIns}]");
                    }
                }
                else
                {
                    logger.Add($"[{newEntryKey}]");
                    var entry = newEntries[newEntryKey];
                    oldEntries.Add(newEntryKey, entry);
                }
            }

            var removed = oldEntries.Keys.Where(k => !newEntries.ContainsKey(k));

            foreach (var r in removed)
            {
                logger.Remove($"[{r}]");
            }
        }
Beispiel #11
0
 protected abstract void ImportInternal(LdstrFile file, IMod mod, CultureInfo culture);
        public void MergeFile_Correct()
        {
            var service = new HarmonyLdstrFileImport();

            var main = new LdstrFile()
            {
                LdstrEntries = new Dictionary <string, LdstrEntry>()
                {
                    { "Key1", new LdstrEntry()
                      {
                          Instructions = new List <BaseEntry>()
                          {
                              new BaseEntry()
                              {
                                  Origin = "Origin1", Translation = "Translation1"
                              },
                              new BaseEntry()
                              {
                                  Origin = "Origin2", Translation = "Translation2"
                              },
                          }
                      } },
                    { "Key2", new LdstrEntry()
                      {
                          Instructions = new List <BaseEntry>()
                          {
                              new BaseEntry()
                              {
                                  Origin = "Origin3", Translation = "Translation3"
                              },
                              new BaseEntry()
                              {
                                  Origin = "Origin4", Translation = "Translation4"
                              },
                          }
                      } },
                }
            };

            var addition = new LdstrFile()
            {
                LdstrEntries = new Dictionary <string, LdstrEntry>()
                {
                    { "Key1", new LdstrEntry()
                      {
                          Instructions = new List <BaseEntry>()
                          {
                              new BaseEntry()
                              {
                                  Origin = "Origin1", Translation = "AnotherTranslation1"
                              },
                              new BaseEntry()
                              {
                                  Origin = "AnotherOrigin1", Translation = "Translation1"
                              },
                              new BaseEntry()
                              {
                                  Origin = "Origin5", Translation = "Translation5"
                              },
                          }
                      } },
                    { "Key3", new LdstrEntry()
                      {
                          Instructions = new List <BaseEntry>()
                          {
                              new BaseEntry()
                              {
                                  Origin = "Origin6", Translation = "Translation6"
                              }
                          }
                      } },
                }
            };

            var result = service.Merge(main, addition);

            result.LdstrEntries.Count.Should().Be(3);

            result.LdstrEntries["Key1"].Instructions.Should().ContainSingle(i => i.Origin == "Origin1" && i.Translation == "Translation1");
            result.LdstrEntries["Key1"].Instructions.Should().ContainSingle(i => i.Origin == "AnotherOrigin1" && i.Translation == "Translation1");
            result.LdstrEntries["Key1"].Instructions.Should().ContainSingle(i => i.Origin == "Origin5" && i.Translation == "Translation5");

            result.LdstrEntries["Key3"].Instructions.Count.Should().Be(1);
            result.LdstrEntries["Key3"].Instructions[0].Origin.Should().Be("Origin6");
            result.LdstrEntries["Key3"].Instructions[0].Translation.Should().Be("Translation6");
        }
        public void Update_Correct()
        {
            var service = new LdstrFileUpdater();

            var logger = new UpdateLogger();

            var oldFile = new LdstrFile()
            {
                LdstrEntries = new Dictionary <string, LdstrEntry>()
                {
                    { "Key1", new LdstrEntry()
                      {
                          Instructions = new List <BaseEntry>()
                          {
                              new BaseEntry()
                              {
                                  Origin = "Origin1", Translation = "Translation1"
                              },
                              new BaseEntry()
                              {
                                  Origin = "Origin2", Translation = "Translation2"
                              },
                          }
                      } },
                    { "Key2", new LdstrEntry()
                      {
                          Instructions = new List <BaseEntry>()
                          {
                              new BaseEntry()
                              {
                                  Origin = "Origin3", Translation = "Translation3"
                              },
                              new BaseEntry()
                              {
                                  Origin = "Origin4", Translation = "Translation4"
                              },
                          }
                      } },
                }
            };

            var newFile = new LdstrFile()
            {
                LdstrEntries = new Dictionary <string, LdstrEntry>()
                {
                    { "Key1", new LdstrEntry()
                      {
                          Instructions = new List <BaseEntry>()
                          {
                              new BaseEntry()
                              {
                                  Origin = "Origin1", Translation = ""
                              },
                              new BaseEntry()
                              {
                                  Origin = "AnotherOrigin1", Translation = ""
                              },
                              new BaseEntry()
                              {
                                  Origin = "Origin5", Translation = ""
                              },
                          }
                      } },
                    { "Key3", new LdstrEntry()
                      {
                          Instructions = new List <BaseEntry>()
                          {
                              new BaseEntry()
                              {
                                  Origin = "Origin6", Translation = ""
                              }
                          }
                      } },
                }
            };

            service.Update(oldFile, newFile, logger);

            logger.Added.Count.Should().Be(1);
            logger.Changed.Count.Should().Be(2);
            logger.Added.Count.Should().Be(1);

            oldFile.LdstrEntries.Count.Should().Be(3);

            oldFile.LdstrEntries["Key1"].Instructions.Count.Should().Be(4);
            oldFile.LdstrEntries["Key1"].Instructions.Should().ContainSingle(i => i.Origin == "Origin1" && i.Translation == "Translation1");
            oldFile.LdstrEntries["Key1"].Instructions.Should().ContainSingle(i => i.Origin == "Origin2" && i.Translation == "Translation2");
            oldFile.LdstrEntries["Key1"].Instructions.Should().ContainSingle(i => i.Origin == "AnotherOrigin1" && i.Translation == "");
            oldFile.LdstrEntries["Key1"].Instructions.Should().ContainSingle(i => i.Origin == "Origin5" && i.Translation == "");

            oldFile.LdstrEntries["Key2"].Instructions.Count.Should().Be(2);
            oldFile.LdstrEntries["Key2"].Instructions.Should().ContainSingle(i => i.Origin == "Origin3" && i.Translation == "Translation3");
            oldFile.LdstrEntries["Key2"].Instructions.Should().ContainSingle(i => i.Origin == "Origin4" && i.Translation == "Translation4");

            oldFile.LdstrEntries["Key3"].Instructions.Count.Should().Be(1);
            oldFile.LdstrEntries["Key3"].Instructions.Should().ContainSingle(i => i.Origin == "Origin6" && i.Translation == "");
        }