Example #1
0
        /// <summary>
        /// Checks whether the patch is valid for current game's version.
        /// </summary>
        /// <param name="patchType">Type of the patching method.</param>
        /// <param name="showDebuggingMessage">Whether to show debugging message in logs.</param>
        /// <returns>Patch's current availability in <see cref="bool"/>.</returns>
        public static bool IsValidPatch(Type patchType, bool showDebuggingMessage = false)
        {
            showDebuggingMessage = true;
            var patchAttr = patchType.GetCustomAttribute <SafePatchAttribute>();

            if (patchAttr == null)
            {
                if (showDebuggingMessage)
                {
                    ADOLib.Log($"Patch Type {patchType.FullName} is invalid! - no SafePatch attribute found!\n");
                }
                return(false);
            }
            var classType = patchAttr.Assembly.GetType(patchAttr.ClassName);

            if ((patchAttr.MinVersion <= ADOLib.RELEASE_NUMBER_FIELD || patchAttr.MinVersion == -1) &&
                (patchAttr.MaxVersion >= ADOLib.RELEASE_NUMBER_FIELD || patchAttr.MaxVersion == -1) &&
                classType != null)
            {
                return(true);
            }

            if (showDebuggingMessage)
            {
                ADOLib.Log($"Patch {patchAttr.PatchId} is invalid! - Specific criteria check:\n" +
                           $"Metadata.MinVersion <= ADOLib.RELEASE_NUMBER_FIELD ({patchAttr.MinVersion} <= {ADOLib.RELEASE_NUMBER_FIELD}) is {patchAttr.MinVersion <= ADOLib.RELEASE_NUMBER_FIELD}\n" +
                           $"Metadata.MinVersion <= ADOLib.RELEASE_NUMBER_FIELD ({patchAttr.MaxVersion} >= {ADOLib.RELEASE_NUMBER_FIELD}) is {patchAttr.MaxVersion >= ADOLib.RELEASE_NUMBER_FIELD || patchAttr.MaxVersion == -1}\n" +
                           $"ClassType is {classType}\n" +
                           $"PatchType is {patchType}\n", LogType.Warning);
            }
            return(false);
        }
Example #2
0
        public static void PatchCategory(this HarmonyLib.Harmony harmony, Type type)
        {
            ADOLib.Log($"Patching category {type}");
            var patchAttr = type.GetCustomAttribute <CategoryAttribute>();

            if (!patchAttr.isValid)
            {
                ADOLib.Log($"{type} is not valid for this ADOFAI version", LogType.Warning);
                return;
            }
            var patchClass = patchAttr.PatchClass;

            if (patchClass == null)
            {
                ADOLib.Log($"No patch class found in category {type}", LogType.Warning);
                return;
            }
            var patches = patchClass.GetNestedTypes(AccessTools.all).Where(t => t.GetCustomAttribute <SafePatchAttribute>() != null);

            foreach (var p in patches)
            {
                harmony.SafePatch(p);
            }
            ADOLib.Log($"Successfully patched category {type}", LogType.Success);
        }
Example #3
0
        /// <summary>
        /// Unpatches patch.
        /// </summary>
        public static void SafeUnpatch(this HarmonyLib.Harmony harmony, Type patchType)
        {
            var metadata = patchType.GetCustomAttribute <SafePatchAttribute>();

            if (metadata == null)
            {
                ADOLib.Log($"Type {patchType} doesn't have SafePatch attribute.");
                return;
            }
            ADOLib.Log($"Unpatching {metadata.PatchId}");

            if (!metadata.IsEnabled)
            {
                ADOLib.Log($"{metadata.PatchId} is not patched!", LogType.Warning);
                return;
            }

            var classType = metadata.Assembly.GetType(metadata.ClassName);

            if (classType == null)
            {
                ADOLib.Log($"Type {metadata.ClassName} not found in assembly {metadata.Assembly}.");
                return;
            }

            var original = metadata.info.method;

            foreach (var patch in patchType.GetMethods())
            {
                harmony.Unpatch(original, patch);
            }

            metadata.IsEnabled = false;
            ADOLib.Log($"Successfully unpatched {metadata.PatchId}", LogType.Success);
        }
Example #4
0
        /// <summary>
        /// Get instance of the <see cref="Category"/>.
        /// </summary>
        /// <param name="type">Category type to get the instance.</param>
        /// <returns>Instance of the input Category. </returns>
        public static Category GetCategory(Type type)
        {
            if (Categories.ContainsKey(type))
            {
                return(Categories[type]);
            }
            if (!(Activator.CreateInstance(type) is Category category))
            {
                ADOLib.Log($"Type {type} is not a category!", LogType.Error);
                return(null);
            }
            var mod  = category.Mod;
            var path = category.XmlPath;

            if (File.Exists(path))
            {
                try {
                    using FileStream fileStream = File.OpenRead(path);
                    Categories[type]            = (Category) new XmlSerializer(type).Deserialize(fileStream);
                    return(Categories[type]);
                }
                catch (Exception e)
                {
                    MelonLogger.Error("Can't read " + path + ".");
                    MelonLogger.Error(e);
                }

                Categories[type] = category;
                RegisterCategories(new [] { type });
                return(Categories[type]);
            }
            Categories[type] = category;
            RegisterCategories(new [] { type });
            return(Categories[type]);
        }
Example #5
0
        /// <summary>
        /// Instantiates new translator with path.
        /// </summary>
        /// <param name="path">Path the language files are located.</param>
        public Translator(string path)
        {
            Path       = path;
            StringsMap = new Dictionary <SystemLanguage, Dictionary <string, string> >();
            var lPath = Path + Setting.LanguageDirectory;

            if (!Directory.Exists(lPath))
            {
                Directory.CreateDirectory(lPath);
            }
            var langFiles = Directory.GetFiles(lPath);

            ADOLib.Log(langFiles.Length);
            foreach (var langFile in langFiles)
            {
                ADOLib.Log(langFile);
                SystemLanguage lang;
                var            langNames = langFile.Split('\\');
                var            langName  = langNames[langNames.Length - 1].Replace(".lang", "");
                if (!Enum.TryParse(langName, out lang))
                {
                    continue;
                }

                var builder = new DeserializerBuilder().Build();
                Dictionary <string, string> langStrings;
                using (var stream = File.Open(langFile, FileMode.Open, FileAccess.Read))
                {
                    using (var reader = new StreamReader(stream))
                    {
                        try
                        {
                            langStrings =
                                builder.Deserialize(reader, typeof(Dictionary <string, string>)) as
                                Dictionary <string, string>;
                        }
                        catch (YamlException)
                        {
                            ADOLib.Log($"Cannot load language {lang} from {path}", LogType.Error);
                            langStrings = new Dictionary <string, string>();
                        }
                    }
                }

                StringsMap[lang] = langStrings;
            }
            if (!StringsMap.ContainsKey(SystemLanguage.English))
            {
                StringsMap[SystemLanguage.English] = new Dictionary <string, string>();
            }
        }
Example #6
0
        public void Awake()
        {
            BG.LoadImage(File.ReadAllBytes($"{ADOLib.PathStatic}settingsBG.png"));
            Background.normal.background = BG;

            ButtonActivated.LoadImage(File.ReadAllBytes($"{ADOLib.PathStatic}buttonActivated.png"));
            ButtonNotActivated.LoadImage(File.ReadAllBytes($"{ADOLib.PathStatic}buttonNotActivated.png"));

            Text            = GUIExtended.Text;
            Selection       = GUIExtended.Selection;
            SelectionActive = GUIExtended.SelectionActive;
            TextInput       = GUIExtended.TextInput;
            ADOLib.Log("SettingsUI Awake");
        }
Example #7
0
 /// <summary>
 /// Translates text with key.
 /// </summary>
 /// <param name="input">Key of the translated string</param>
 /// <param name="language"><see cref="SystemLanguage">Language</see> to translate into.</param>
 /// <returns>String translated into the language.</returns>
 public string Translate(string input, SystemLanguage language)
 {
     if (!StringsMap.ContainsKey(language))
     {
         language = SystemLanguage.English;
     }
     if (!StringsMap[language].ContainsKey(input))
     {
         ADOLib.Log(input);
         StringsMap[language][input] = $"{language}.{input}.NotTranslated";
         var serializer = new SerializerBuilder().Build();
         var path       = Path + Setting.LanguageDirectory + $"{language}.lang";
         ADOLib.Log(path);
         File.WriteAllText(path, serializer.Serialize(StringsMap[language]));
     }
     return(StringsMap[language][input].Replace("\\n", "\n"));
 }
Example #8
0
        /// <summary>
        /// Patches patch.
        /// <param name="harmony">Harmony class to apply patch.</param>
        /// <param name="patchType">Harmony class to apply patch.</param>
        /// </summary>
        public static void SafePatch(this HarmonyLib.Harmony harmony, Type patchType)
        {
            var metadata = patchType.GetCustomAttribute <SafePatchAttribute>();

            if (metadata == null)
            {
                ADOLib.Log($"Type {patchType} doesn't have SafePatch attribute.", LogType.Error);
                return;
            }
            ADOLib.Log($"Patching {metadata.PatchId}");

            if (metadata.IsEnabled)
            {
                ADOLib.Log($"{metadata.PatchId} is already patched!", LogType.Warning);
                return;
            }

            if (!IsValidPatch(patchType))
            {
                ADOLib.Log($"Type {patchType} is not valid for this ADOFAI version", LogType.Warning);
                return;
            }

            Type declaringType = metadata.Assembly.GetType(metadata.ClassName);

            if (declaringType == null)
            {
                ADOLib.Log($"Type {metadata.ClassName} not found", LogType.Warning);
                return;
            }

            try {
                harmony.CreateClassProcessor(patchType).Patch();
            }
            catch (Exception) {
                ADOLib.Log($"Wrong patch method {metadata.MethodName}", LogType.Warning);
                return;
            }

            metadata.IsEnabled = true;
            var metadata2 = patchType.GetCustomAttribute <SafePatchAttribute>();

            ADOLib.Log($"Successfully patched {metadata.PatchId}", LogType.Success);
        }
Example #9
0
        public static void UnpatchCategory(this HarmonyLib.Harmony harmony, Type type)
        {
            ADOLib.Log($"Unpatching category {type}");
            var patchAttr = type.GetCustomAttribute <CategoryAttribute>();

            if (!patchAttr.isValid)
            {
                ADOLib.Log($"Not unpatching {type}; ADOFAI version is not compatible", LogType.Warning);
                return;
            }
            var patchClass = patchAttr.PatchClass;

            if (patchClass == null)
            {
                ADOLib.Log($"No patch class found in category {type}", LogType.Warning);
                return;
            }
            ADOLib.Log("Unpatching SafePatch...");
            var patches = patchClass.GetNestedTypes(AccessTools.all).Where(t => t.GetCustomAttribute <SafePatchAttribute>() != null);

            patches.Do(harmony.SafeUnpatch);
            ADOLib.Log($"Successfully patched category {type}", LogType.Success);
        }
Example #10
0
 public void Start()
 {
     ADOLib.Log("SettingsUI Start");
     Category.RegisterCategories(AppDomain.CurrentDomain.GetAssemblies().SelectMany(assembly => assembly.GetTypes()));
 }
Example #11
0
 public override void OnDisable()
 {
     ADOLib.Log("ADOLib Settings Disabled");
 }
Example #12
0
 public override void OnEnable()
 {
     ADOLib.Log("ADOLib Settings Enabled");
 }
Example #13
0
        internal static void RegisterCategories(IEnumerable <Type> types)
        {
            ADOLib.Log("Registering Category");
            var categoryTypes = types.Where(t => t.GetCustomAttribute <CategoryAttribute>(true) != null).ToList();
            int success       = 0;

            foreach (var category in categoryTypes)
            {
                var categoryAttr = category.GetCustomAttribute <CategoryAttribute>();
                var tabName      = categoryAttr.TabName;

                var instance = GetCategory(category);
                if (instance.isRegistered)
                {
                    ADOLib.Log($"Category already registered, skipping category {category}", LogType.Warning);
                    continue;
                }
                instance.Name        = categoryAttr.Name;
                instance.TabName     = categoryAttr.TabName;
                instance.ForceType   = categoryAttr.ForceType;
                instance.InvalidMode = categoryAttr.InvalidMode;
                instance.ForceReason = categoryAttr.ForceReason;
                if (!instance.Metadata.isValid)
                {
                    if (instance.InvalidMode == InvalidMode.UnRegister)
                    {
                        ADOLib.Log($"Category version uncompatible, skipping category {category}", LogType.Warning);
                        continue;
                    }
                    instance.ForceType = ForceType.ForceDisable;
                    if (categoryAttr.MinVersion == -1)
                    {
                        instance.ForceReason = string.Format(ADOLib.translator
                                                             .Translate("Category.AdofaiVersionNotCompatible1"),
                                                             ADOLib.RELEASE_NUMBER_FIELD, categoryAttr.MaxVersion);
                    }
                    else if (categoryAttr.MaxVersion == -1)
                    {
                        instance.ForceReason = string.Format(ADOLib.translator
                                                             .Translate("Category.AdofaiVersionNotCompatible2"),
                                                             ADOLib.RELEASE_NUMBER_FIELD, categoryAttr.MinVersion);
                    }
                    else if (categoryAttr.MinVersion == categoryAttr.MaxVersion)
                    {
                        instance.ForceReason = string.Format(ADOLib.translator
                                                             .Translate("Category.AdofaiVersionNotCompatible3"),
                                                             ADOLib.RELEASE_NUMBER_FIELD, categoryAttr.MinVersion);
                    }
                    else
                    {
                        instance.ForceReason = string.Format(ADOLib.translator
                                                             .Translate("Category.AdofaiVersionNotCompatible0"),
                                                             ADOLib.RELEASE_NUMBER_FIELD, categoryAttr.MinVersion, categoryAttr.MaxVersion);
                    }
                }
                if (instance.ForceType == ForceType.ForceDisable)
                {
                    instance.IsEnabled = false;
                }
                else if (instance.ForceType == ForceType.ForceEnable)
                {
                    instance.IsEnabled = true;
                }
                var text = GUIExtended.Text;
                text.alignment = TextAnchor.MiddleLeft;
                text.font      = GUIExtended.ArialFont;
                text.fontSize  = 20;

                Action OnGUI = () => {
                    GUILayout.BeginHorizontal();
                    instance.IsExpanded = GUILayout.Toggle(
                        instance.IsExpanded,
                        instance.IsEnabled ? instance.IsExpanded ? "▼" : "━" : "<color=#444444>━</color>",
                        new GUIStyle {
                        fixedWidth = 10,
                        normal     = new GUIStyleState {
                            textColor = Color.black
                        },
                        fontSize = 20,
                        margin   = new RectOffset(4, 16, 24, 0)
                    });
                    if (instance.ForceType == ForceType.DontForce)
                    {
                        var wasEnabled = instance.IsEnabled;
                        instance.IsEnabled =
                            GUIExtended.Toggle(instance.IsEnabled, $"<size=50>{instance.Name}</size>");
                        if (instance.IsEnabled != wasEnabled)
                        {
                            if (instance.IsEnabled)
                            {
                                instance.OnEnable();
                            }
                            else
                            {
                                instance.OnDisable();
                            }
                        }
                    }
                    else if (instance.ForceType == ForceType.ForceDisable)
                    {
                        GUIExtended.Toggle(instance.IsEnabled,
                                           $"<size=50><color=#444444>{instance.Name}</color></size> <color=#555555>{instance.ForceReason}</color>",
                                           GUIExtended.Text, "<color=#555555>☐</color>", "<color=#555555>☐</color>");
                    }
                    else
                    {
                        GUIExtended.Toggle(instance.IsEnabled,
                                           $"<size=50>{instance.Name}</size> <color=#555555>{instance.ForceReason}</color>",
                                           GUIExtended.Text, "<color=#555555>☑</color>", "<color=#555555>☑</color>");
                    }

                    GUILayout.EndHorizontal();
                    if (instance.IsEnabled && instance.IsExpanded)
                    {
                        GUIExtended.BeginIndent(15);
                        instance.OnGUI();
                        GUIExtended.EndIndent();
                    }
                    GUIExtended.HorizontalLine(0.2f);
                };
                if (!SettingsUI.Tabs.Contains(tabName))
                {
                    SettingsUI.Categories[tabName] = instance;
                    SettingsUI.Settings[tabName]   = OnGUI;
                    SettingsUI.Saves[tabName]      = instance.Save;
                    SettingsUI.Tabs.Insert(0, tabName);
                }
                else
                {
                    SettingsUI.Settings[tabName] += OnGUI;
                    SettingsUI.Saves[tabName]    += instance.Save;
                }
                instance.Init();
                if (instance.IsEnabled)
                {
                    instance.OnEnable();
                }
                else
                {
                    instance.OnDisable();
                }
                ADOLib.Log($"Successfully registered category {category}", LogType.Success);
                success++;
            }
        }