Beispiel #1
0
        /// <summary>
        /// Register types attributed with `UIExtenderLibExtension`:
        /// 1. will add extensions to their respective components
        /// 2. will add standard patches and patch game
        /// 3. will force game to reload affected XMLs
        /// </summary>
        /// <param name="types"></param>
        public void Register(IEnumerable <Type> types)
        {
            foreach (var extensionType in types)
            {
                foreach (var baseAttribute in Attribute.GetCustomAttributes(extensionType, typeof(BaseUIExtenderAttribute)))
                {
                    switch (baseAttribute)
                    {
                    case PrefabExtensionAttribute xmlExtension:
                    {
                        var constructor = extensionType.GetConstructor(Type.EmptyTypes);
                        if (constructor == null)
                        {
                            Utils.Fail("Failed to find appropriate constructor for patch!");
                            continue;
                        }

                        // gauntlet xml extension
                        switch (constructor.Invoke(Array.Empty <object>()))
                        {
                        case PrefabExtensionInsertPatch patch:
                            PrefabComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                            break;

                        case PrefabExtensionReplacePatch patch:
                            PrefabComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                            break;

                        case PrefabExtensionInsertAsSiblingPatch patch:
                            PrefabComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                            break;

                        case CustomPatch <XmlDocument> patch:
                            PrefabComponent.RegisterPatch(xmlExtension.Movie, patch.Apply);
                            break;

                        case CustomPatch <XmlNode> patch:
                            PrefabComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch.Apply);
                            break;

                        default:
                            Utils.Fail($"Patch class is unsupported - {extensionType}!");
                            break;
                        }

                        break;
                    }

                    case ViewModelMixinAttribute viewModelExtension:
                        // view model mixin
                        ViewModelComponent.RegisterViewModelMixin(extensionType, viewModelExtension.RefreshMethodName);
                        break;

                    default:
                        Utils.Fail($"Failed to find appropriate clause for base type {extensionType} with attribute {baseAttribute}!");
                        break;
                    }
                }
            }
        }
Beispiel #2
0
        protected override void OnBeforeInitialModuleScreenSetAsRoot()
        {
            base.OnBeforeInitialModuleScreenSetAsRoot();

            /*
             * This method is run every time MainMenu appears, which could happen multiple times
             * during single application run.
             *
             * Code to apply extensions should be run after all of the mods has been loaded, therefore it could not
             * be placed in `OnSubModuleLoad`.
             *
             * In order to only run it once this flag is implemented.
             */
            if (_processedExtensions)
            {
                return;
            }
            _processedExtensions = true;

            // apply registered extensions
            foreach (var extensionType in UIExtender.Extensions)
            {
                var baseAttribute = Attribute.GetCustomAttribute(extensionType, typeof(UIExtenderLibExtension));
                if (baseAttribute is PrefabExtension xmlExtension)
                {
                    var constructor = extensionType.GetConstructor(new Type[] { });
                    if (constructor == null)
                    {
                        Debug.Fail("Failed to find appropriate constructor for patch!");
                    }

                    // gauntlet xml extension
                    switch (constructor.Invoke(new object[] {}))
                    {
                    case PrefabExtensionInsertPatch patch:
                        WidgetComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                        break;

                    case PrefabExtensionReplacePatch patch:
                        WidgetComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                        break;

                    case PrefabExtensionInsertAsSiblingPatch patch:
                        WidgetComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                        break;

                    case CustomPatch <XmlDocument> patch:
                        WidgetComponent.RegisterPatch(xmlExtension.Movie, patch.Apply);
                        break;

                    case CustomPatch <XmlNode> patch:
                        WidgetComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch.Apply);
                        break;

                    default:
                        Debug.Fail($"Patch class is unsupported - {extensionType}!");
                        break;
                    }
                }
                else if (baseAttribute is ViewModelMixin)
                {
                    // view model mixin
                    ViewModelComponent.RegisterViewModelMixin(extensionType);
                }
                else
                {
                    Debug.Fail($"Failed to find appropriate clause for base type {extensionType} with attribute {baseAttribute}!");
                }
            }

            // apply patches
            var harmony = new Harmony("net.shdwp.UIExtenderLibModule");

            harmony.PatchAll();

            // save .runtime_dll for troubleshooting
            ViewModelComponent.SaveRuntimeImages();

            // force reload movies that should be patched by extensions
            WidgetComponent.ForceReloadMovies();
        }
Beispiel #3
0
        protected override void OnBeforeInitialModuleScreenSetAsRoot()
        {
            base.OnBeforeInitialModuleScreenSetAsRoot();

            // apply registered extensions
            foreach (var extensionType in UIExtender.Extensions)
            {
                var baseAttribute = Attribute.GetCustomAttribute(extensionType, typeof(UIExtenderLibExtension));
                if (baseAttribute is PrefabExtension xmlExtension)
                {
                    var constructor = extensionType.GetConstructor(new Type[] { });
                    if (constructor == null)
                    {
                        Debug.Fail("Failed to find appropriate constructor for patch!");
                    }

                    // gauntlet xml extension
                    switch (constructor.Invoke(new object[] {}))
                    {
                    case PrefabExtensionInsertPatch patch:
                        WidgetComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                        break;

                    case PrefabExtensionReplacePatch patch:
                        WidgetComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                        break;

                    case PrefabExtensionInsertAsSiblingPatch patch:
                        WidgetComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                        break;

                    case CustomPatch <XmlDocument> patch:
                        WidgetComponent.RegisterPatch(xmlExtension.Movie, patch.Apply);
                        break;

                    case CustomPatch <XmlNode> patch:
                        WidgetComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch.Apply);
                        break;

                    default:
                        Debug.Fail($"Patch class is unsupported - {extensionType}!");
                        break;
                    }
                }
                else if (baseAttribute is ViewModelMixin)
                {
                    // view model mixin
                    ViewModelComponent.RegisterViewModelMixin(extensionType);
                }
                else
                {
                    Debug.Fail($"Failed to find appropriate clause for base type {extensionType} with attribute {baseAttribute}!");
                }
            }

            // apply patches
            var harmony = new Harmony("net.shdwp.UIExtenderLibModule");

            harmony.PatchAll();

            // save .runtime_dll for troubleshooting
            ViewModelComponent.SaveRuntimeImages();

            // force reload movies that should be patched by extensions
            WidgetComponent.ForceReloadMovies();
        }
Beispiel #4
0
        /// <summary>
        /// Register types attributed with `UIExtenderLibExtension`:
        /// 1. will add extensions to their respective components
        /// 2. will add standard patches and patch game
        /// 3. will force game to reload affected XMLs
        /// </summary>
        /// <param name="types"></param>
        internal void Register(IEnumerable <Type> types)
        {
            foreach (var extensionType in types)
            {
                var baseAttribute = Attribute.GetCustomAttribute(extensionType, typeof(UIExtenderLibExtension));
                switch (baseAttribute)
                {
                case PrefabExtension xmlExtension:
                {
                    var constructor = extensionType.GetConstructor(new Type[] { });
                    if (constructor == null)
                    {
                        Debug.Fail("Failed to find appropriate constructor for patch!");
                    }

                    // gauntlet xml extension
                    switch (constructor.Invoke(new object[] {}))
                    {
                    case PrefabExtensionInsertPatch patch:
                        PrefabComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                        break;

                    case PrefabExtensionReplacePatch patch:
                        PrefabComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                        break;

                    case PrefabExtensionInsertAsSiblingPatch patch:
                        PrefabComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch);
                        break;

                    case CustomPatch <XmlDocument> patch:
                        PrefabComponent.RegisterPatch(xmlExtension.Movie, patch.Apply);
                        break;

                    case CustomPatch <XmlNode> patch:
                        PrefabComponent.RegisterPatch(xmlExtension.Movie, xmlExtension.XPath, patch.Apply);
                        break;

                    default:
                        Debug.Fail($"Patch class is unsupported - {extensionType}!");
                        break;
                    }

                    break;
                }

                case ViewModelMixin _:
                    // view model mixin
                    ViewModelComponent.RegisterViewModelMixin(extensionType);
                    break;

                default:
                    Debug.Fail($"Failed to find appropriate clause for base type {extensionType} with attribute {baseAttribute}!");
                    break;
                }
            }

            var patchingResult = ViewModelPatches.Result.Success;

            // add core patches (in order for UIExtender to actually work)
            if (!CorePatches.AddTo(CodePatcher))
            {
                _userMessages.Add(new InformationMessage($"Failed to patch {ModuleName} (outdated).", Colors.Red));
                return;
            }

            patchingResult = ViewModelPatches.AddTo(CodePatcher);
            switch (patchingResult)
            {
            case ViewModelPatches.Result.Success:
                break;

            case ViewModelPatches.Result.Partial:
                AddUserWarning($"There were errors on {ModuleName} patching. Some functionality may not work (module outdated).");
                break;

            case ViewModelPatches.Result.Failure:
                AddUserError($"Failed to patch {ModuleName} (outdated).");
                break;
            }

            // finalize code patcher and let harmony apply patches
            CodePatcher.ApplyPatches();

            // save .dll for troubleshooting
            ViewModelComponent.SaveDebugImages();

            // force reload movies that should be patched by extensions
            PrefabComponent.ForceReloadMovies();
        }