Example #1
0
        public bool MarkInstalled(ModMetadata meta, ModVersion version, ModDownloadResult downloadDetails)
        {
            ModStatus status = GetModStatus(meta);

            switch (status)
            {
            case ModStatus.Installed:
                ModVersions.Delete(m => m.MetadataId == meta.Id);
                ModVersions.Insert(version);
                return(true);

            case ModStatus.NotInstalled:
                Mods.Insert(meta);
                ModVersions.Insert(version);
                return(true);

            // Already added as requested, need to modify it
            case ModStatus.Requested:
                ModVersion requested = ModVersions.FindOne(v => v.GetModVersion() == version.GetModVersion());
                requested.Filename = downloadDetails.Filename;
                requested.Checksum = downloadDetails.Checksum;

                return(ModVersions.Update(requested));
            }

            return(false);
        }
Example #2
0
        void LoadMod(ModMetadata mod)
        {
            if (!Game.IsModInstalled(mod.Id))
            {
                var widgetArgs = new WidgetArgs
                {
                    { "modId", mod.Id }
                };

                Ui.OpenWindow("INSTALL_MOD_PANEL", widgetArgs);
                return;
            }

            if (!IsModInstalled(mod))
            {
                var widgetArgs = new WidgetArgs
                {
                    { "continueLoading", () =>
                      Game.RunAfterTick(() => Game.InitializeMod(mod.Id, new Arguments())) },
                    { "modId", mod.Id }
                };

                Ui.OpenWindow("CONTENT_PROMPT_PANEL", widgetArgs);

                return;
            }

            Game.RunAfterTick(() =>
            {
                Ui.CloseWindow();
                sheetBuilder.Dispose();
                Game.InitializeMod(mod.Id, null);
            });
        }
Example #3
0
        public Task <ModVersion> GetModVersion(ModMetadata metadata, string version)
        {
            if (metadata == null)
            {
                throw new Exception("Metadata is not defined; cannot get mod versions with it.");
            }

            if (!(metadata is CurseforgeModMetadata))
            {
                throw new Exception("Metadata needs to be a curseforge metadata object.");
            }

            CurseforgeModMetadata cfMeta = metadata as CurseforgeModMetadata;

            bool hasVersion = cfMeta.Versions.ContainsKey(cfMeta.MinecraftVersion);

            if (!hasVersion)
            {
                throw new Exception("Mod does not have versions for the requested Minecraft version.");
            }

            IEnumerable <ModVersion> versions = cfMeta.Versions[cfMeta.MinecraftVersion];

            if (version == null)
            {
                return(Task.FromResult(versions.First()));
            }

            ModVersion mv = versions.First(v => v.GetModVersion() == version);

            return(Task.FromResult(mv));
        }
Example #4
0
        /// <summary>
        /// Handles the mods versions {modid} command.
        /// </summary>
        /// <param name="domain">Domain handler to use for lookup.</param>
        /// <param name="modIdentifier">Mod to lookup versions for.</param>
        public static void HandleModVersions(IDomain domain, string modIdentifier)
        {
            IDomainHandler handler = domain.GetDomainHandler();

            ModMetadata meta = handler.GetModMetadata(Modifi.DefaultPack.MinecraftVersion, modIdentifier).Result;

            IEnumerable <ModVersion> latestVersions = handler.GetRecentVersions(meta).Result;

            // ModHelper.PrintModInformation(meta);
            foreach (ModVersion version in latestVersions)
            {
                Console.Write("[");
                Console.ForegroundColor = ConsoleColor.Gray;
                Console.Write(version.GetModVersion());
                Console.ForegroundColor = ConsoleColor.White;
                Console.Write("] ");

                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.Write(version.GetVersionName());

                Console.ForegroundColor = ConsoleColor.White;
                Console.Write(" (");
                Console.ForegroundColor = ConsoleColor.Magenta;
                Console.Write(version.GetReleaseType());
                Console.ForegroundColor = ConsoleColor.White;
                Console.Write(")");
                Console.ResetColor();
                Console.WriteLine();
            }
        }
        public ModMetadataBuilder WithVersion(string version)
        {
            Version parsed = new Version(version);

            _modMetadata = new ModMetadata(_modMetadata?.Name, parsed, _modMetadata?.Description);
            return(this);
        }
Example #6
0
        void LoadMod(ModMetadata mod)
        {
            if (!modPrerequisitesFulfilled[mod.Id])
            {
                var widgetArgs = new WidgetArgs
                {
                    { "modId", mod.Id }
                };

                Ui.OpenWindow("INSTALL_MOD_PANEL", widgetArgs);
                return;
            }

            if (!modInstallStatus[mod])
            {
                var widgetArgs = new WidgetArgs
                {
                    { "continueLoading", () =>
                      Game.RunAfterTick(() => Game.InitializeMod(Game.Settings.Game.Mod, new Arguments())) },
                    { "mirrorListUrl", mod.Content.PackageMirrorList },
                    { "modId", mod.Id }
                };

                Ui.OpenWindow("INSTALL_PANEL", widgetArgs);

                return;
            }

            Game.RunAfterTick(() =>
            {
                Ui.CloseWindow();
                sheetBuilder.Dispose();
                Game.InitializeMod(mod.Id, null);
            });
        }
Example #7
0
        public Task <IEnumerable <ModVersion> > GetRecentVersions(ModMetadata meta, int count = 5, ModReleaseType releaseType = ModReleaseType.Any)
        {
            if (!(meta is CurseforgeModMetadata))
            {
                throw new Exception("Metadata is not of Curseforge's type. Cannot fetch mod versions with this.");
            }

            CurseforgeModMetadata metaCF = (CurseforgeModMetadata)meta;

            if (String.IsNullOrEmpty(metaCF.MinecraftVersion))
            {
                throw new Exception("Minecraft version was not set on metadata, cannot properly fetch versions.");
            }

            if (!metaCF.Versions.ContainsKey(metaCF.MinecraftVersion))
            {
                return(null);
            }

            IEnumerable <ModVersion> versions = metaCF.Versions[metaCF.MinecraftVersion];

            if (releaseType != ModReleaseType.Any)
            {
                versions = versions.Where(v => v.GetReleaseType() == releaseType);
            }

            IEnumerable <ModVersion> limitedList = versions.Take(count);

            foreach (ModVersion mv in limitedList)
            {
                mv.MetadataId = meta.Id;
            }

            return(Task.FromResult(limitedList));
        }
Example #8
0
 public ModCircularDependencyException(ModMetadata modMetadata, ModMetadata dependency)
     : base($"Circular dependency found between mods " +
            $"`{modMetadata.Name} (v{modMetadata.Version})` and " +
            $"`{dependency.Name} (v{dependency.Version})`.")
 {
     this.modMetadata = modMetadata;
     this.dependency  = dependency;
 }
 static void LoadMod(ModMetadata mod)
 {
     Game.RunAfterTick(() =>
     {
         Ui.CloseWindow();
         Game.InitializeWithMod(mod.Id, null);
     });
 }
Example #10
0
 public ModVersion GetMod(ModMetadata meta)
 {
     if (meta == null)
     {
         return(null);
     }
     return(GetMod(meta.GetModIdentifier()));
 }
        public ModMetadataActor()
        {
            Receive <LoadModMetadataCommand>(command =>
            {
                bool exists = Directory.Exists(command.Path);

                if (!exists)
                {
                    // TODO : User friendly message
                }

                string modInfoXmlPath = Path.Combine(command.Path, ModInfoXml);

                var modInfoXml = XDocument.Load(modInfoXmlPath);

                var modInfo = (from name in modInfoXml.Descendants()
                               select new
                {
                    Name = name.Element("Name")?.Value,
                    Id = name.Element("Id")?.Value,
                    Version = name.Element("Version")?.Value,
                    Signature = name.Element("Signature")?.Value
                }).FirstOrDefault();

                var dataFolderPath = Path.Combine(command.Path, "data");
                var databasePath   = Path.Combine(dataFolderPath, DefaultDatabaseName);

                if (!File.Exists(databasePath))
                {
                    // TODO : User friendly message
                }

                var stringTables = Directory.GetFiles(dataFolderPath, "*.gst");

                if (!stringTables.Any())
                {
                    // TODO : User friendly message
                }

                var builder = ImmutableDictionary.CreateBuilder <string, StringTableMetadata>();

                foreach (var stringTable in stringTables)
                {
                    string lang       = stringTable.Split('.')[1];
                    var tableMetadata = new StringTableMetadata(lang, stringTable);

                    builder.Add(lang, tableMetadata);
                }

                var stringTableMetadata = builder.ToImmutable();

                var modMetadata = new ModMetadata(modInfo.Id, modInfo.Name, modInfo.Version, modInfo.Signature, dataFolderPath, databasePath, stringTableMetadata);

                var readedEvent = new ModMetadataLoadedEvent(modMetadata);

                command.Sender.Tell(readedEvent);
            });
        }
Example #12
0
 void LoadMod(ModMetadata mod)
 {
     Game.RunAfterTick(() =>
     {
         Ui.CloseWindow();
         sheetBuilder.Dispose();
         Game.InitializeMod(mod.Id, null);
     });
 }
        public DesignViewModel(IApplicationActorContext applicationActorContext, ModMetadata modMetadata)
        {
            TabHeaderTitle = "Desings";

            _designViewActorRef = applicationActorContext.ActorSystem.ActorOf(Props.Create(() => new DesignsViewActor(this, modMetadata)).WithDispatcher("akka.actor.synchronized-dispatcher"));

            CloseCommand = new DelegateCommand(OnDesignViewClosed);

            _designViewActorRef.Tell(new LoadDesignsCommand(_designViewActorRef));
        }
Example #14
0
        public Task <ModVersion> GetLatestVersion(ModMetadata meta, ModReleaseType releaseType = ModReleaseType.Any)
        {
            if (!(meta is CurseforgeModMetadata))
            {
                throw new Exception("Metadata is not of Curseforge's type. Cannot fetch mod versions with this.");
            }

            IEnumerable <ModVersion> versions = GetRecentVersions(meta, 1, releaseType).Result;

            return(Task.FromResult(versions.First()));
        }
Example #15
0
        public static void HandleModInformation(IDomain domain, string modIdentifier, string modVersion = null)
        {
            ModMetadata meta = domain.GetDomainHandler().GetModMetadata(Modifi.DefaultPack.MinecraftVersion, modIdentifier).Result;

            ILogger log = Modifi.DefaultLogger;

            log.Information(meta.GetName());
            if (meta.HasDescription())
            {
                log.Information(meta.GetDescription());
            }
        }
Example #16
0
        public bool MarkRequested(ModMetadata meta, ModVersion version)
        {
            if (GetModStatus(meta) != ModStatus.NotInstalled)
            {
                throw new Exception("Mod is already marked requested, or already installed.");
            }

            Mods.Insert(meta);
            ModVersions.Insert(version);

            return(true);
        }
Example #17
0
        void SelectMod(ModMetadata mod)
        {
            selectedMod         = mod;
            selectedAuthor      = "By " + (mod.Author ?? "unknown author");
            selectedDescription = (mod.Description ?? "").Replace("\\n", "\n");
            var selectedIndex = Array.IndexOf(allMods, mod);

            if (selectedIndex - modOffset > 4)
            {
                modOffset = selectedIndex - 4;
            }
        }
        public void ResolveDependencies_CircularDependency_ThrowsException()
        {
            ModMetadata firstDep  = _metadataBuilder.WithName("Dep One").Build();
            ModMetadata secondDep = _metadataBuilder.WithName("Dep Two").Build();
            ModMetadata thirdDep  = _metadataBuilder.WithName("Dep Three").Build();

            firstDep.Dependencies.Add(secondDep);
            secondDep.Dependencies.Add(thirdDep);
            thirdDep.Dependencies.Add(firstDep);

            Assert.Throws <ModCircularDependencyException>(() => firstDep.TryResolveDependencies(new[] { firstDep, secondDep, thirdDep }));
        }
Example #19
0
        public ModVersion GetMod(string modIdentifier)
        {
            ModMetadata meta = Mods.FindOne(x => x.GetModIdentifier() == modIdentifier);

            if (meta == null)
            {
                return(null);
            }

            Guid v = meta.Id;

            return(ModVersions.FindOne(x => x.MetadataId == meta.Id));
        }
        public void ResolveDependencies_NotAllDependenciesLoaded_ReturnsFalse()
        {
            ModMetadata firstDep  = _metadataBuilder.WithName("Dep One").Build();
            ModMetadata secondDep = _metadataBuilder.WithName("Dep Two").Build();

            ModMetadata rootMod = _metadataBuilder
                                  .WithName("Root Mod")
                                  .WithVersion("1.0")
                                  .WithDependency(firstDep)
                                  .WithDependency(secondDep)
                                  .Build();

            Assert.IsFalse(rootMod.TryResolveDependencies(new[] { firstDep }));
        }
Example #21
0
        void SelectMod(ModMetadata mod)
        {
            selectedMod         = mod;
            selectedAuthor      = "By " + (mod.Author ?? "unknown author");
            selectedDescription = (mod.Description ?? "").Replace("\\n", "\n");
            var selectedIndex = Array.IndexOf(allMods, mod);

            if (selectedIndex - modOffset > 4)
            {
                modOffset = selectedIndex - 4;
            }

            loadButton.Text = modInstallStatus[mod] ? "Load Mod" : "Install Assets";
        }
Example #22
0
        public static ModDownloadResult?HandleModDownload(IDomain domain, string modIdentifier, string modVersion = null)
        {
            IDomainHandler handler = domain.GetDomainHandler();

            // Fetch the mod version information from the Curseforge API
            try {
                ModMetadata meta = handler.GetModMetadata(Modifi.DefaultPack.MinecraftVersion, modIdentifier).Result;
                ModVersion  mod  = handler.GetModVersion(meta, modVersion).Result;

                return(handler.DownloadMod(mod, Settings.ModPath).Result);
            }

            catch (Exception) { return(null); }
        }
Example #23
0
        /// <summary>
        /// Gets the installation status for a mod.
        /// </summary>
        /// <param name="meta">Mod to get status for</param>
        /// <returns></returns>
        public ModStatus GetModStatus(ModMetadata meta)
        {
            ModMetadata installed = this.Mods.FindOne(x => x.GetModIdentifier() == meta.GetModIdentifier());

            if (installed == null)
            {
                return(ModStatus.NotInstalled);
            }

            ModVersion installedVersion = GetMod(meta);

            // If we have a request in meta, but no requested version, error.
            // Delete the meta information and let the user know to re-request the mod.
            // TODO: Make new exception for this
            if (installedVersion == null)
            {
                this.Mods.Delete(x => x.GetModIdentifier() == installed.GetModIdentifier());
                throw new Exception("Mod metadata was in requests, but no matching version was found with it.");
            }

            // Check filename exists - if not, mod is requested and not yet downloaded
            string filename = installedVersion.Filename;

            if (filename == null)
            {
                return(ModStatus.Requested);
            }

            // Filename exists- check if properly downloaded
            string path = Path.Combine(Settings.ModPath, filename);

            if (File.Exists(path))
            {
                // If our checksum matches, the mod is installed
                if (ModUtilities.ChecksumMatches(path, installedVersion.Checksum))
                {
                    return(ModStatus.Installed);
                }
                else
                {
                    // TODO: Should we remove the mod metadata if the checksum failed here?
                    throw new Exception("Checksum does not match version information.");
                }
            }

            return(ModStatus.Requested);
        }
Example #24
0
        public DesignOperationsActor(ModMetadata modMetadata)
        {
            Receive <LoadDesignsCommand>(command =>
            {
                var connectionString = new FbConnectionStringBuilder
                {
                    Database      = modMetadata.ModDatabasePath,
                    ServerType    = FbServerType.Embedded,
                    UserID        = "SYSDBA",
                    Password      = "******",
                    ClientLibrary = "fbembed.dll"
                }.ToString();

                using (SuperPowerEditorDbContext context = new SuperPowerEditorDbContext(connectionString))
                {
                    List <Design> designs = context.Designs.Include(nameof(Design.CountryDesignerRef)).ToList();

                    command.Sender.Tell(new DesignsLoadedEvent(designs));
                }
            });
        }
Example #25
0
        /// <summary>
        /// Prints out some mod information in a standardized manner.
        /// </summary>
        /// <param name="meta"></param>
        public static void PrintModInformation(ModMetadata meta, bool header = false)
        {
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine();
            Console.WriteLine(meta.GetName());
            Console.ForegroundColor = ConsoleColor.White;

            if (meta.HasDescription())
            {
                Console.WriteLine();
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine(meta.GetDescription());
            }

            if (header)
            {
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("".PadLeft(Console.BufferWidth - 10, '='));
            }

            Console.ResetColor();
        }
Example #26
0
        private void MigrateModJsonPreClientVersion2()
        {
            foreach (var mod in _parkitect.Assets[AssetType.Mod])
            {
                var metaPath = Path.Combine(mod.InstallationPath, "modinfo.meta");
                if (!File.Exists(metaPath))
                {
                    var oldData =
                        JsonConvert.DeserializeObject <OldModJsonFile>(
                            File.ReadAllText(Path.Combine(mod.InstallationPath, "mod.json")));

                    var meta = new ModMetadata
                    {
                        Tag              = oldData.Tag,
                        Repository       = oldData.Repository,
                        Id               = null,
                        InstalledVersion = DateTime.Now
                    };

                    File.WriteAllText(metaPath, JsonConvert.SerializeObject(meta));
                }
            }
        }
Example #27
0
        public ModStringTableActor(ModMetadata modMetadata)
        {
            var dataPath      = modMetadata.DataPath;
            var spStringTable = new SpStringTable();

            spStringTable.Load(dataPath);

            Receive <LoadStringTableValueFromIdCommand>(command =>
            {
                try
                {
                    string spString = spStringTable.GetString(command.StId, command.Lang);

                    //string spString = "Deniz";

                    Sender.Tell(new StringTableValueLoadedEvent(command.StId, spString, command.Lang), Self);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            });
        }
Example #28
0
        public ModBrowserLogic(Widget widget)
        {
            var panel      = widget;
            var loadButton = panel.Get <ButtonWidget>("LOAD_BUTTON");

            loadButton.OnClick    = () => LoadMod(selectedMod);
            loadButton.IsDisabled = () => selectedMod.Id == Game.ModData.Manifest.Mod.Id;

            panel.Get <ButtonWidget>("QUIT_BUTTON").OnClick = Game.Exit;

            modList     = panel.Get("MOD_LIST");
            modTemplate = modList.Get <ButtonWidget>("MOD_TEMPLATE");

            panel.Get <LabelWidget>("MOD_DESC").GetText    = () => selectedDescription;
            panel.Get <LabelWidget>("MOD_TITLE").GetText   = () => selectedMod.Title;
            panel.Get <LabelWidget>("MOD_AUTHOR").GetText  = () => selectedAuthor;
            panel.Get <LabelWidget>("MOD_VERSION").GetText = () => selectedMod.Version;

            var prevMod = panel.Get <ButtonWidget>("PREV_MOD");

            prevMod.OnClick   = () => { modOffset -= 1; RebuildModList(); };
            prevMod.IsVisible = () => modOffset > 0;

            var nextMod = panel.Get <ButtonWidget>("NEXT_MOD");

            nextMod.OnClick   = () => { modOffset += 1; RebuildModList(); };
            nextMod.IsVisible = () => modOffset + 5 < allMods.Length;

            panel.Get <RGBASpriteWidget>("MOD_PREVIEW").GetSprite = () =>
            {
                Sprite ret = null;
                previews.TryGetValue(selectedMod.Id, out ret);
                return(ret);
            };

            sheetBuilder = new SheetBuilder(SheetType.BGRA);
            allMods      = ModMetadata.AllMods.Values.Where(m => !m.Hidden)
                           .OrderBy(m => m.Title)
                           .ToArray();

            // Load preview images, and eat any errors
            foreach (var mod in allMods)
            {
                try
                {
                    using (var preview = new Bitmap(Platform.ResolvePath(".", "mods", mod.Id, "preview.png")))
                        if (preview.Width == 296 && preview.Height == 196)
                        {
                            previews.Add(mod.Id, sheetBuilder.Add(preview));
                        }
                }
                catch (Exception) { }

                try
                {
                    using (var logo = new Bitmap(Platform.ResolvePath(".", "mods", mod.Id, "logo.png")))
                        if (logo.Width == 96 && logo.Height == 96)
                        {
                            logos.Add(mod.Id, sheetBuilder.Add(logo));
                        }
                }
                catch (Exception) { }
            }

            ModMetadata initialMod = null;

            ModMetadata.AllMods.TryGetValue(Game.Settings.Game.PreviousMod, out initialMod);
            SelectMod(initialMod ?? ModMetadata.AllMods["ra"]);

            RebuildModList();
        }
Example #29
0
		void SelectMod(ModMetadata mod)
		{
			selectedMod = mod;
			selectedAuthor = "By " + (mod.Author ?? "unknown author");
			selectedDescription = (mod.Description ?? "").Replace("\\n", "\n");
			var selectedIndex = Array.IndexOf(allMods, mod);
			if (selectedIndex - modOffset > 4)
				modOffset = selectedIndex - 4;

			loadButton.Text = modInstallStatus[mod] ? "Load Mod" : "Install Assets";
		}
Example #30
0
		void LoadMod(ModMetadata mod)
		{
			if (!modInstallStatus[mod])
			{
				var widgetArgs = new WidgetArgs
				{
					{ "continueLoading", () =>
						Game.RunAfterTick(() => Game.InitializeMod(Game.Settings.Game.Mod, new Arguments())) },
					{ "mirrorListUrl", mod.Content.PackageMirrorList },
					{ "modId", mod.Id }
				};

				Ui.OpenWindow("INSTALL_PANEL", widgetArgs);

				return;
			}

			Game.RunAfterTick(() =>
			{
				Ui.CloseWindow();
				sheetBuilder.Dispose();
				Game.InitializeMod(mod.Id, null);
			});
		}
Example #31
0
 static bool IsModInstalled(ModMetadata mod)
 {
     return(mod.Content.TestFiles.All(file => File.Exists(Path.GetFullPath(Platform.ResolvePath(file)))));
 }
Example #32
0
		static bool IsModInstalled(ModMetadata mod)
		{
			return mod.Content.TestFiles.All(file => File.Exists(Path.GetFullPath(Platform.ResolvePath(file))));
		}
Example #33
0
 static void LoadMod(ModMetadata mod)
 {
     Game.RunAfterTick(() =>
     {
         Ui.CloseWindow();
         Game.InitializeWithMod(mod.Id, null);
     });
 }
Example #34
0
 void SelectMod(ModMetadata mod)
 {
     selectedMod = mod;
     selectedAuthor = "By " + mod.Author ?? "unknown author";
     selectedDescription = (mod.Description ?? "").Replace("\\n", "\n");
     var selectedIndex = Array.IndexOf(allMods, mod);
     if (selectedIndex - modOffset > 4)
         modOffset = selectedIndex - 4;
 }
        public async Task <IAsset> StoreAsset(IDownloadedAsset downloadedAsset)
        {
            switch (downloadedAsset.ApiAsset.Type)
            {
            case AssetType.Blueprint:
            case AssetType.Savegame:
            case AssetType.Scenario:
            {
                // Create the directory where the asset should be stored and create a path to where the asset should be stored.
                var storagePath = _parkitect.Paths.GetAssetPath(downloadedAsset.ApiAsset.Type);
                var assetPath   = Path.Combine(storagePath, downloadedAsset.FileName);
                Directory.CreateDirectory(storagePath);

                _log.WriteLine($"Storing asset to {assetPath}.");

                // If the file already exists, add a number behind the file name.
                if (File.Exists(assetPath))
                {
                    _log.WriteLine("Asset already exists, comparing hashes.");

                    // Compute hash of downloaded asset to match with installed hash.
                    var validHash = downloadedAsset.Stream.CreateMD5Checksum();

                    if (validHash.SequenceEqual(File.OpenRead(assetPath).CreateMD5Checksum()))
                    {
                        _log.WriteLine("Asset hashes match, aborting.");
                        return(null);
                    }

                    _log.WriteLine("Asset hashes mismatch, computing new file name.");
                    // Separate the filename and the extension.
                    var attempt       = 1;
                    var fileName      = Path.GetFileNameWithoutExtension(downloadedAsset.FileName);
                    var fileExtension = Path.GetExtension(downloadedAsset.FileName);

                    // Update the path to where the the asset should be stored by adding a number behind the name until an available filename has been found.
                    do
                    {
                        assetPath = Path.Combine(storagePath, $"{fileName} ({++attempt}){fileExtension}");

                        if (File.Exists(assetPath) &&
                            validHash.SequenceEqual(File.OpenRead(assetPath).CreateMD5Checksum()))
                        {
                            return(null);
                        }
                    } while (File.Exists(assetPath));

                    _log.WriteLine($"Newly computed path is {assetPath}.");
                }

                _log.WriteLine("Writing asset to file.");
                // Write the stream to a file at the asset path.
                using (var fileStream = File.Create(assetPath))
                {
                    downloadedAsset.Stream.Seek(0, SeekOrigin.Begin);
                    await downloadedAsset.Stream.CopyToAsync(fileStream);
                }

                var meta = new AssetMetadata
                {
                    Id = downloadedAsset.ApiAsset.Id
//                        InstalledVersion = downloadedAsset.ApiAsset.UpdatedAt
                };    // TODO: Re-add installed version

                _assetMetadataStorage.StoreMetadata(downloadedAsset.ApiAsset.Type, assetPath, meta);
                var cachedData =
                    await _assetCachedDataStorage.GetData(downloadedAsset.ApiAsset.Type, meta, assetPath);

                Asset createdAsset = null;
                switch (downloadedAsset.ApiAsset.Type)
                {
                case AssetType.Blueprint:
                    createdAsset = new BlueprintAsset(assetPath, meta, cachedData);
                    break;

                case AssetType.Savegame:
                    createdAsset = new SavegameAsset(assetPath, meta, cachedData as AssetWithImageCachedData);
                    break;

                case AssetType.Scenario:
                    createdAsset = new ScenarioAsset(assetPath, meta, cachedData as AssetWithImageCachedData);
                    break;
                }

                OnAssetAdded(new AssetEventArgs(createdAsset));
                return(createdAsset);
            }

            case AssetType.Mod:
            {
                _log.WriteLine("Attempting to open mod stream.");
                using (var zip = new ZipArchive(downloadedAsset.Stream, ZipArchiveMode.Read))
                {
                    // Compute name of main directory inside archive.
                    var mainFolder = zip.Entries.FirstOrDefault()?.FullName;
                    if (mainFolder == null)
                    {
                        throw new Exception("invalid archive");
                    }

                    _log.WriteLine($"Mod archive main folder is {mainFolder}.");

                    // Find the mod.json file. Yay for / \ path divider compatibility.
                    var modJsonPath = Path.Combine(mainFolder, "mod.json").Replace('/', '\\');
                    var modJson     = zip.Entries.FirstOrDefault(e => e.FullName.Replace('/', '\\') == modJsonPath);

                    // Read mod.json.
                    if (modJson == null)
                    {
                        throw new Exception("mod is missing mod.json file");
                    }
                    using (var streamReader = new StreamReader(modJson.Open()))
                    {
                        var modInformationString = await streamReader.ReadToEndAsync();

                        var modInformation = JsonConvert.DeserializeObject <ModInformation>(modInformationString);

                        var meta = new ModMetadata
                        {
                            Id = downloadedAsset.ApiAsset.Id,
//                                InstalledVersion = downloadedAsset.ApiAsset.UpdatedAt,
                            Tag        = downloadedAsset.Info.Tag,
                            Repository = downloadedAsset.Info.Repository
                        };     // TODO: Re-add installed version

                        var installationPath = Path.Combine(_parkitect.Paths.GetAssetPath(AssetType.Mod),
                                                            downloadedAsset.Info.Repository.Replace('/', '@'));

                        // TODO: Should actually try and look if the mod has been updated since and delete the whole folder.
                        if (Directory.Exists(installationPath))
                        {
                            if (File.Exists(Path.Combine(installationPath, "modinfo.meta")))
                            {
                                File.Delete(Path.Combine(installationPath, "modinfo.meta"));
                            }
                            if (File.Exists(Path.Combine(installationPath, "moddata.cache")))
                            {
                                File.Delete(Path.Combine(installationPath, "moddata.cache"));
                            }
                        }

                        _log.WriteLine($"mod.json was deserialized to mod object '{modInformation}'.");

                        // Set default mod properties.
                        modInformation.IsEnabled     = true;
                        modInformation.IsDevelopment = false;

                        // Find previous version of mod.
                        // TODO uninstall previous versions

                        // Install mod.
                        _log.WriteLine("Copying mod to mods folder.");
                        foreach (var entry in zip.Entries)
                        {
                            if (!entry.FullName.StartsWith(mainFolder))
                            {
                                continue;
                            }

                            // Compute path.
                            var partDir      = entry.FullName.Substring(mainFolder.Length);
                            var path         = Path.Combine(installationPath, partDir);
                            var ignoredFiles = new[] { "moddata.cache", "modinfo.meta", "mod.log" };

                            if (ignoredFiles.Contains(partDir))
                            {
                                continue;
                            }

                            if (string.IsNullOrEmpty(entry.Name))
                            {
                                _log.WriteLine($"Creating directory '{path}'.");
                                Directory.CreateDirectory(path);
                            }
                            else
                            {
                                _log.WriteLine($"Storing mod file '{path}'.");
                                using (var openStream = entry.Open())
                                    using (var fileStream = File.OpenWrite(path))
                                        await openStream.CopyToAsync(fileStream);
                            }
                        }

                        _log.WriteLine("Register installation to API.");
                        _website.API.RegisterDownload(downloadedAsset.ApiAsset.Id);

                        _assetMetadataStorage.StoreMetadata(downloadedAsset.ApiAsset.Type, installationPath, meta);
                        var cachedData = await _assetCachedDataStorage.GetData(downloadedAsset.ApiAsset.Type, meta,
                                                                               installationPath);

                        modInformationString = JsonConvert.SerializeObject(modInformation);
                        File.WriteAllText(Path.Combine(installationPath, "mod.json"), modInformationString);

                        var createdAsset = new ModAsset(installationPath, meta,
                                                        cachedData as AssetWithImageCachedData, modInformation);
                        OnAssetAdded(new AssetEventArgs(createdAsset));

                        return(createdAsset);
                    }
                }
            }

            default:
                throw new Exception("unknown asset type");
            }
        }
Example #36
0
 void LoadMod(ModMetadata mod)
 {
     Game.RunAfterTick(() =>
     {
         Ui.CloseWindow();
         sheetBuilder.Dispose();
         Game.InitializeMod(mod.Id, null);
     });
 }