Beispiel #1
0
        public Merger(string dataFolderPath, List <ModKey> plugins, ModKey outputKey)
        {
            _loadOrder = LoadOrder.Import(
                dataFolderPath,
                plugins,
                path => ModInstantiator <ISkyrimModGetter> .Importer(path, GameRelease.SkyrimSE));

            _outputMod  = new SkyrimMod(outputKey, SkyrimRelease.SkyrimSE);
            _outputPath = Path.Combine(dataFolderPath, outputKey.FileName);
        }
Beispiel #2
0
 public ProfileSimpleLinkCacheVm(
     ILogger logger,
     IProfileLoadOrder loadOrder,
     IProfileDataFolderVm dataFolder,
     IProfileIdentifier ident)
 {
     _simpleLinkCache = Observable.CombineLatest(
         dataFolder.WhenAnyValue(x => x.Path),
         loadOrder.LoadOrder.Connect()
         .QueryWhenChanged()
         .Select(q => q.Where(x => x.Enabled).Select(x => x.ModKey).ToArray())
         .StartWithEmpty(),
         (dataFolder, loadOrder) => (dataFolder, loadOrder))
                        .Throttle(TimeSpan.FromMilliseconds(100), RxApp.TaskpoolScheduler)
                        .Select(x =>
     {
         return(Observable.Create <(ILinkCache?Cache, IDisposable Disposable)>(obs =>
         {
             try
             {
                 var loadOrder = Mutagen.Bethesda.Plugins.Order.LoadOrder.Import(
                     x.dataFolder,
                     x.loadOrder,
                     factory: (modPath) => ModInstantiator.Importer(modPath, ident.Release));
                 obs.OnNext(
                     (loadOrder.ToUntypedImmutableLinkCache(LinkCachePreferences.OnlyIdentifiers()),
                      loadOrder));
                 obs.OnCompleted();
                 // ToDo
                 // Figure out why returning this is disposing too early.
                 // Gets disposed undesirably, which makes formlink pickers fail
                 // return loadOrder;
             }
             catch (Exception ex)
             {
                 logger.Error(ex, "Error creating simple link cache for GUI lookups");
                 obs.OnNext((default, Disposable.Empty));
Beispiel #3
0
        public SynthesisState <TModSetter, TModGetter> ToState <TModSetter, TModGetter>(RunSynthesisMutagenPatcher settings, PatcherPreferences userPrefs, ModKey exportKey)
            where TModSetter : class, IContextMod <TModSetter, TModGetter>, TModGetter
            where TModGetter : class, IContextGetterMod <TModSetter, TModGetter>
        {
            // Confirm target game release matches
            var regis = settings.GameRelease.ToCategory().ToModRegistration();

            if (!typeof(TModSetter).IsAssignableFrom(regis.SetterType))
            {
                throw new ArgumentException($"Target mod type {typeof(TModSetter)} was not of the expected type {regis.SetterType}");
            }
            if (!typeof(TModGetter).IsAssignableFrom(regis.GetterType))
            {
                throw new ArgumentException($"Target mod type {typeof(TModGetter)} was not of the expected type {regis.GetterType}");
            }

            // Set up target language
            System.Console.WriteLine($"Language: {settings.TargetLanguage}");
            TranslatedString.DefaultLanguage = settings.TargetLanguage;

            // Get load order
            var loadOrderListing = _getStateLoadOrder.GetLoadOrder(!settings.LoadOrderIncludesCreationClub, userPrefs)
                                   .ToExtendedList();
            var rawLoadOrder = loadOrderListing.Select(x => new ModListing(x.ModKey, x.Enabled)).ToExtendedList();

            // Trim past export key
            var synthIndex = loadOrderListing.IndexOf(exportKey, (listing, key) => listing.ModKey == key);

            if (synthIndex != -1)
            {
                loadOrderListing.RemoveToCount(synthIndex);
            }

            if (userPrefs.AddImplicitMasters)
            {
                _enableImplicitMasters
                .Get(settings.DataFolderPath, settings.GameRelease)
                .Add(loadOrderListing);
            }

            // Remove disabled mods
            if (!userPrefs.IncludeDisabledMods)
            {
                loadOrderListing = loadOrderListing.OnlyEnabled().ToExtendedList();
            }

            var loadOrder = _loadOrderImporter
                            .Get <TModGetter>(
                settings.DataFolderPath,
                loadOrderListing,
                settings.GameRelease)
                            .Import();

            // Create or import patch mod
            TModSetter patchMod;
            ILinkCache <TModSetter, TModGetter> cache;
            IFormKeyAllocator?formKeyAllocator = null;

            if (userPrefs.NoPatch)
            {
                // Pass null, even though it isn't normally
                patchMod = null !;

                TModGetter readOnlyPatchMod;
                if (settings.SourcePath == null)
                {
                    readOnlyPatchMod = ModInstantiator <TModGetter> .Activator(exportKey, settings.GameRelease);
                }
                else
                {
                    readOnlyPatchMod = ModInstantiator <TModGetter> .Importer(new ModPath(exportKey, settings.SourcePath), settings.GameRelease, fileSystem : _fileSystem);
                }
                loadOrder.Add(new ModListing <TModGetter>(readOnlyPatchMod, enabled: true));
                rawLoadOrder.Add(new ModListing(readOnlyPatchMod.ModKey, enabled: true));
                cache = loadOrder.ToImmutableLinkCache <TModSetter, TModGetter>();
            }
            else
            {
                if (settings.SourcePath == null)
                {
                    patchMod = ModInstantiator <TModSetter> .Activator(exportKey, settings.GameRelease);
                }
                else
                {
                    patchMod = ModInstantiator <TModSetter> .Importer(new ModPath(exportKey, settings.SourcePath), settings.GameRelease, fileSystem : _fileSystem);
                }
                if (settings.PersistencePath is not null && settings.PatcherName is not null)
                {
                    if (TextFileSharedFormKeyAllocator.IsPathOfAllocatorType(settings.PersistencePath))
                    {
                        System.Console.WriteLine($"Using {nameof(TextFileSharedFormKeyAllocator)} allocator");
                        patchMod.SetAllocator(formKeyAllocator = new TextFileSharedFormKeyAllocator(patchMod, settings.PersistencePath, settings.PatcherName, fileSystem: _fileSystem));
                    }
                    // else if (SQLiteFormKeyAllocator.IsPathOfAllocatorType(settings.PersistencePath))
                    // {
                    //     System.Console.WriteLine($"Using {nameof(SQLiteFormKeyAllocator)} allocator");
                    //     patchMod.SetAllocator(formKeyAllocator = new SQLiteFormKeyAllocator(patchMod, settings.PersistencePath, settings.PatcherName));
                    // }
                    else
                    {
                        System.Console.WriteLine($"Allocation systems were marked to be on, but could not identify allocation system to be used");
                    }
                }
                cache = loadOrder.ToMutableLinkCache(patchMod);
                loadOrder.Add(new ModListing <TModGetter>(patchMod, enabled: true));
                rawLoadOrder.Add(new ModListing(patchMod.ModKey, enabled: true));

                System.Console.WriteLine($"Can use localization: {patchMod.CanUseLocalization}");
                if (patchMod.CanUseLocalization)
                {
                    System.Console.WriteLine($"Localized: {settings.Localize}");
                    patchMod.UsingLocalization = settings.Localize;
                }
            }

            return(new SynthesisState <TModSetter, TModGetter>(
                       runArguments: settings,
                       loadOrder: loadOrder,
                       rawLoadOrder: rawLoadOrder,
                       linkCache: cache,
                       internalDataPath: settings.InternalDataFolder,
                       patchMod: patchMod,
                       extraDataPath: settings.ExtraDataFolder == null ? string.Empty : Path.GetFullPath(settings.ExtraDataFolder),
                       defaultDataPath: settings.DefaultDataFolderPath,
                       cancellation: userPrefs.Cancel,
                       formKeyAllocator: formKeyAllocator));
        }
Beispiel #4
0
 public IModGetter Import(ModPath modPath, StringsReadParameters?stringsParam = null)
 {
     return(ModInstantiator.Importer(modPath, _gameRelease.Release, _fileSystem, stringsParam));
 }
Beispiel #5
0
 public TMod Import <TMod>(ModPath modPath, StringsReadParameters?stringsParam = null)
     where TMod : IModGetter
 {
     return(ModInstantiator <TMod> .Importer(modPath, _gameRelease.Release, _fileSystem, stringsParam));
 }
Beispiel #6
0
        public static SynthesisState <TMod, TModGetter> ToState <TMod, TModGetter>(RunSynthesisMutagenPatcher settings, UserPreferences userPrefs)
            where TMod : class, IMod, TModGetter
            where TModGetter : class, IModGetter
        {
            // Confirm target game release matches
            var regis = settings.GameRelease.ToCategory().ToModRegistration();

            if (!typeof(TMod).IsAssignableFrom(regis.SetterType))
            {
                throw new ArgumentException($"Target mod type {typeof(TMod)} was not of the expected type {regis.SetterType}");
            }
            if (!typeof(TModGetter).IsAssignableFrom(regis.GetterType))
            {
                throw new ArgumentException($"Target mod type {typeof(TModGetter)} was not of the expected type {regis.GetterType}");
            }

            // Get load order
            var loadOrderListing = SynthesisPipeline.Instance.GetLoadOrder(settings, userPrefs)
                                   .ToExtendedList();
            var rawLoadOrder = loadOrderListing.Select(x => new LoadOrderListing(x.ModKey, x.Enabled)).ToExtendedList();

            // Trim past Synthesis.esp
            var synthIndex = loadOrderListing.IndexOf(BaseSynthesis.Constants.SynthesisModKey, (listing, key) => listing.ModKey == key);

            if (synthIndex != -1)
            {
                loadOrderListing.RemoveToCount(synthIndex);
            }

            if (userPrefs.AddImplicitMasters)
            {
                AddImplicitMasters(settings, loadOrderListing);
            }

            // Remove disabled mods
            if (!userPrefs.IncludeDisabledMods)
            {
                loadOrderListing = loadOrderListing.OnlyEnabled().ToExtendedList();
            }

            var loadOrder = LoadOrder.Import <TModGetter>(
                settings.DataFolderPath,
                loadOrderListing,
                settings.GameRelease);

            // Get Modkey from output path
            var modKey = BaseSynthesis.Constants.SynthesisModKey;

            // Create or import patch mod
            TMod       patchMod;
            ILinkCache cache;

            if (userPrefs.NoPatch)
            {
                // Pass null, even though it isn't normally
                patchMod = null !;

                TModGetter readOnlyPatchMod;
                if (settings.SourcePath == null)
                {
                    readOnlyPatchMod = ModInstantiator <TModGetter> .Activator(modKey, settings.GameRelease);
                }
                else
                {
                    readOnlyPatchMod = ModInstantiator <TModGetter> .Importer(new ModPath(modKey, settings.SourcePath), settings.GameRelease);
                }
                loadOrder.Add(new ModListing <TModGetter>(readOnlyPatchMod, enabled: true));
                cache = loadOrder.ToImmutableLinkCache();
            }
            else
            {
                if (settings.SourcePath == null)
                {
                    patchMod = ModInstantiator <TMod> .Activator(modKey, settings.GameRelease);
                }
                else
                {
                    patchMod = ModInstantiator <TMod> .Importer(new ModPath(modKey, settings.SourcePath), settings.GameRelease);
                }
                cache = loadOrder.ToMutableLinkCache(patchMod);
                loadOrder.Add(new ModListing <TModGetter>(patchMod, enabled: true));
            }

            return(new SynthesisState <TMod, TModGetter>(
                       settings: settings,
                       loadOrder: loadOrder,
                       rawLoadOrder: rawLoadOrder,
                       linkCache: cache,
                       patchMod: patchMod,
                       extraDataPath: settings.ExtraDataFolder == null ? string.Empty : Path.GetFullPath(settings.ExtraDataFolder),
                       cancellation: userPrefs.Cancel));
        }
Beispiel #7
0
        public MainVM(HostSettings host)
        {
            WindowName = $"{host.PatcherName} Settings";
            WarmupAll.Init();

            var loadOrderResult = Observable.Return(Unit.Default)
                                  .ObserveOn(RxApp.TaskpoolScheduler)
                                  .Select(_ =>
            {
                System.Console.Error.WriteLine($"Getting live load order for {host.GameRelease} -> {host.DataFolderPath}");
                var liveLo = Mutagen.Bethesda.LoadOrder.GetLiveLoadOrder(host.GameRelease, host.DataFolderPath, out IObservable <ErrorResponse> errors)
                             .Transform(listing => new LoadOrderEntryVM(listing, host.DataFolderPath))
                             .DisposeMany();
                return(Results: liveLo, State: errors);
            })
                                  .StartWith((Results: Observable.Empty <IChangeSet <LoadOrderEntryVM> >(), State: Observable.Return(ErrorResponse.Fail("Load order uninitialized"))))
                                  .Replay(1)
                                  .RefCount();

            loadOrderResult.Select(x => x.State)
            .Switch()
            .Subscribe(e =>
            {
                Console.Error.WriteLine(e);
            })
            .DisposeWith(this);

            var loadOrder = loadOrderResult
                            .Select(x => x.Results)
                            .Switch()
                            .AsObservableList();

            var linkCache = loadOrder.Connect()
                            .QueryWhenChanged()
                            .Select(q => q.Where(x => x.Listing.Enabled).Select(x => x.Listing.ModKey).ToArray())
                            .StartWithEmpty()
                            .Throttle(TimeSpan.FromMilliseconds(100), RxApp.TaskpoolScheduler)
                            .Select(x =>
            {
                return(Observable.Create <ILinkCache>(obs =>
                {
                    var loadOrder = Mutagen.Bethesda.LoadOrder.Import(
                        host.DataFolderPath,
                        x,
                        factory: (modPath) => ModInstantiator.Importer(modPath, host.GameRelease));
                    obs.OnNext(loadOrder.ToUntypedImmutableLinkCache(LinkCachePreferences.OnlyIdentifiers()));
                    obs.OnCompleted();
                    return Disposable.Empty;
                }));
            })
                            .Switch()
                            .Replay(1)
                            .RefCount();

            _AutogeneratedSettings = Observable.Return(Unit.Default)
                                     .ObserveOn(RxApp.TaskpoolScheduler)
                                     .SelectTask(async _ =>
            {
                try
                {
                    var config = await Synthesis.Bethesda.Execution.CLI.Commands.GetSettingsStyle(
                        host.PatcherPath,
                        directExe: false,
                        cancel: CancellationToken.None,
                        build: false,
                        log: (s) => Console.WriteLine(s));
                    return(new AutogeneratedSettingsVM(
                               config,
                               projPath: host.PatcherPath,
                               displayName: host.PatcherName,
                               loadOrder: loadOrder.Connect(),
                               linkCache: linkCache,
                               log: (s) => Console.WriteLine(s)));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                    return(default(AutogeneratedSettingsVM?));
                }
            })
                                     .ToGuiProperty(this, nameof(AutogeneratedSettings), default);
        }
        public static void Generate(GenerateFromMod gen)
        {
            var mod  = ModInstantiator.Importer(gen.Path, gen.Release);
            var list = new List <(FormKey FormKey, string Edid, ILoquiRegistration Regis)>();

            foreach (var rec in mod.EnumerateMajorRecords())
            {
                if (!rec.EditorID.TryGet(out var edid))
                {
                    continue;
                }
                var formKey = rec.FormKey;
                // Only register FormKeys originating from the mod itself
                if (formKey.ModKey != mod.ModKey)
                {
                    continue;
                }
                var regis = GetMajorRecord(rec.Registration);
                list.Add((formKey, edid, regis));
            }

            var namespaceStr = $"Mutagen.Bethesda.FormKeys.{gen.Release}";
            var importStr    = $"Mutagen.Bethesda.{gen.Release.ToCategory()}";
            var modName      = mod.ModKey.Name.TrimStart("DLC");

            foreach (var regis in list.GroupBy(x => x.Regis))
            {
                FileGeneration fg = new FileGeneration();
                fg.AppendLine($"using {importStr};");
                fg.AppendLine();

                using (new NamespaceWrapper(fg, namespaceStr))
                {
                    using (var c = new ClassWrapper(fg, modName))
                    {
                        c.Static  = true;
                        c.Partial = true;
                    }
                    using (new BraceWrapper(fg))
                    {
                        using (var c = new ClassWrapper(fg, regis.Key.Name))
                        {
                            c.Static = true;
                        }
                        using (new BraceWrapper(fg))
                        {
                            fg.AppendLine($"private readonly static ModKey ModKey = ModKey.{nameof(ModKey.FromNameAndExtension)}(\"{mod.ModKey}\");");
                            fg.AppendLine($"private static FormLink<{regis.Key.GetterType.Name}> Construct(uint id) => new FormLink<{regis.Key.GetterType.Name}>(ModKey.{nameof(ModKeyExt.MakeFormKey)}(id));");
                            foreach (var rec in regis)
                            {
                                fg.AppendLine($"public static FormLink<{regis.Key.GetterType.Name}> {CleanName(rec.Edid, regis.Key.Name)} => Construct(0x{rec.FormKey.ID:x});");
                            }
                        }
                    }
                }

                var path = Path.Combine("Output", gen.Release.ToString(), modName, $"{regis.Key.Name}.cs");
                fg.Generate(path);
                System.Console.WriteLine($"Exported: {path}");
            }
        }
Beispiel #9
0
 public TMod Activate <TMod>(ModKey modKey)
     where TMod : IModGetter
 {
     return(ModInstantiator <TMod> .Activator(modKey, _gameRelease.Release));
 }