public static void StartPublishItem(ContentPackage contentPackage, Workshop.Editor item) { if (instance == null || !instance.isInitialized) { return; } if (string.IsNullOrEmpty(item.Title)) { DebugConsole.ThrowError("Cannot publish workshop item - title not set."); return; } if (string.IsNullOrEmpty(item.Folder)) { DebugConsole.ThrowError("Cannot publish workshop item \"" + item.Title + "\" - folder not set."); return; } contentPackage.Name = item.Title; contentPackage.GameVersion = GameMain.Version; contentPackage.Save(Path.Combine(WorkshopItemStagingFolder, MetadataFileName)); if (File.Exists(PreviewImageName)) { File.Delete(PreviewImageName); } //move the preview image out of the staging folder, it does not need to be included in the folder sent to Workshop File.Move(Path.GetFullPath(Path.Combine(item.Folder, PreviewImageName)), PreviewImageName); item.PreviewImage = Path.GetFullPath(PreviewImageName); CoroutineManager.StartCoroutine(PublishItem(item)); }
/// <summary> /// Creates a new folder, copies the specified files there and creates a metadata file with install instructions. /// </summary> public static void CreateWorkshopItemStaging(List <ContentFile> contentFiles, out Workshop.Editor itemEditor, out ContentPackage contentPackage) { var stagingFolder = new DirectoryInfo(WorkshopItemStagingFolder); if (stagingFolder.Exists) { SaveUtil.ClearFolder(stagingFolder.FullName); } else { stagingFolder.Create(); } Directory.CreateDirectory(Path.Combine(WorkshopItemStagingFolder, "Submarines")); Directory.CreateDirectory(Path.Combine(WorkshopItemStagingFolder, "Mods")); Directory.CreateDirectory(Path.Combine(WorkshopItemStagingFolder, "Mods", "ModName")); itemEditor = instance.client.Workshop.CreateItem(Workshop.ItemType.Community); itemEditor.Visibility = Workshop.Editor.VisibilityType.Public; itemEditor.WorkshopUploadAppId = AppID; itemEditor.Folder = stagingFolder.FullName; string previewImagePath = Path.GetFullPath(Path.Combine(itemEditor.Folder, PreviewImageName)); File.Copy("Content/DefaultWorkshopPreviewImage.png", previewImagePath); //copy content files to the staging folder List <string> copiedFilePaths = new List <string>(); foreach (ContentFile file in contentFiles) { string relativePath = UpdaterUtil.GetRelativePath(Path.GetFullPath(file.Path), Environment.CurrentDirectory); string destinationPath = Path.Combine(stagingFolder.FullName, relativePath); //make sure the directory exists Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); File.Copy(file.Path, destinationPath); copiedFilePaths.Add(destinationPath); } System.Diagnostics.Debug.Assert(copiedFilePaths.Count == contentFiles.Count); //create a new content package and include the copied files in it contentPackage = ContentPackage.CreatePackage("ContentPackage", Path.Combine(itemEditor.Folder, MetadataFileName), false); for (int i = 0; i < copiedFilePaths.Count; i++) { contentPackage.AddFile(copiedFilePaths[i], contentFiles[i].Type); } contentPackage.Save(Path.Combine(stagingFolder.FullName, MetadataFileName)); }
/// <summary> /// Enables a workshop item by moving it to the game folder. /// </summary> public static bool EnableWorkShopItem(Workshop.Item item, bool allowFileOverwrite, out string errorMsg) { if (!item.Installed) { errorMsg = TextManager.GetWithVariable("WorkshopErrorInstallRequiredToEnable", "[itemname]", item.Title); DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); return(false); } string metaDataFilePath = Path.Combine(item.Directory.FullName, MetadataFileName); ContentPackage contentPackage = new ContentPackage(metaDataFilePath); string newContentPackagePath = GetWorkshopItemContentPackagePath(contentPackage); if (!contentPackage.IsCompatible()) { errorMsg = TextManager.GetWithVariables(contentPackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage", new string[3] { "[packagename]", "[packageversion]", "[gameversion]" }, new string[3] { contentPackage.Name, contentPackage.GameVersion.ToString(), GameMain.Version.ToString() }); return(false); } if (contentPackage.CorePackage && !contentPackage.ContainsRequiredCorePackageFiles(out List <ContentType> missingContentTypes)) { errorMsg = TextManager.GetWithVariables("ContentPackageMissingCoreFiles", new string[2] { "[packagename]", "[missingfiletypes]" }, new string[2] { contentPackage.Name, string.Join(", ", missingContentTypes) }, new bool[2] { false, true }); return(false); } var allPackageFiles = Directory.GetFiles(item.Directory.FullName, "*", SearchOption.AllDirectories); List <string> nonContentFiles = new List <string>(); foreach (string file in allPackageFiles) { if (file == metaDataFilePath) { continue; } string relativePath = UpdaterUtil.GetRelativePath(file, item.Directory.FullName); string fullPath = Path.GetFullPath(relativePath); if (contentPackage.Files.Any(f => { string fp = Path.GetFullPath(f.Path); return(fp == fullPath); })) { continue; } if (ContentPackage.IsModFilePathAllowed(relativePath)) { nonContentFiles.Add(relativePath); } } if (!allowFileOverwrite) { if (File.Exists(newContentPackagePath) && !CheckFileEquality(newContentPackagePath, metaDataFilePath)) { errorMsg = TextManager.GetWithVariables("WorkshopErrorOverwriteOnEnable", new string[2] { "[itemname]", "[filename]" }, new string[2] { item.Title, newContentPackagePath }); DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); return(false); } foreach (ContentFile contentFile in contentPackage.Files) { string sourceFile = Path.Combine(item.Directory.FullName, contentFile.Path); if (File.Exists(sourceFile) && File.Exists(contentFile.Path) && !CheckFileEquality(sourceFile, contentFile.Path)) { errorMsg = TextManager.GetWithVariables("WorkshopErrorOverwriteOnEnable", new string[2] { "[itemname]", "[filename]" }, new string[2] { item.Title, contentFile.Path }); DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); return(false); } } } try { foreach (ContentFile contentFile in contentPackage.Files) { string sourceFile = Path.Combine(item.Directory.FullName, contentFile.Path); //path not allowed -> the content file must be a reference to an external file (such as some vanilla file outside the Mods folder) if (!ContentPackage.IsModFilePathAllowed(contentFile)) { //the content package is trying to copy a file to a prohibited path, which is not allowed if (File.Exists(sourceFile)) { errorMsg = TextManager.GetWithVariable("WorkshopErrorIllegalPathOnEnable", "[filename]", contentFile.Path); return(false); } //not trying to copy anything, so this is a reference to an external file //if the external file doesn't exist, we cannot enable the package else if (!File.Exists(contentFile.Path)) { errorMsg = TextManager.GetWithVariable("WorkshopErrorEnableFailed", "[itemname]", item.Title) + " " + TextManager.GetWithVariable("WorkshopFileNotFound", "[path]", "\"" + contentFile.Path + "\""); return(false); } continue; } else if (!File.Exists(sourceFile)) { if (File.Exists(contentFile.Path)) { //the file is already present in the game folder, all good continue; } else { //file not present in either the mod or the game folder -> cannot enable the package errorMsg = TextManager.GetWithVariable("WorkshopErrorEnableFailed", "[itemname]", item.Title) + " " + TextManager.GetWithVariable("WorkshopFileNotFound", "[path]", "\"" + contentFile.Path + "\""); return(false); } } //make sure the destination directory exists Directory.CreateDirectory(Path.GetDirectoryName(contentFile.Path)); File.Copy(sourceFile, contentFile.Path, overwrite: true); } foreach (string nonContentFile in nonContentFiles) { string sourceFile = Path.Combine(item.Directory.FullName, nonContentFile); if (!File.Exists(sourceFile)) { continue; } if (!ContentPackage.IsModFilePathAllowed(nonContentFile)) { DebugConsole.ThrowError(TextManager.GetWithVariable("WorkshopErrorIllegalPathOnEnable", "[filename]", nonContentFile)); continue; } Directory.CreateDirectory(Path.GetDirectoryName(nonContentFile)); File.Copy(sourceFile, nonContentFile, overwrite: true); } } catch (Exception e) { errorMsg = TextManager.GetWithVariable("WorkshopErrorEnableFailed", "[itemname]", item.Title) + " {" + e.Message + "}"; DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); return(false); } var newPackage = new ContentPackage(contentPackage.Path, newContentPackagePath) { SteamWorkshopUrl = item.Url, InstallTime = item.Modified > item.Created ? item.Modified : item.Created }; newPackage.Save(newContentPackagePath); ContentPackage.List.Add(newPackage); if (newPackage.CorePackage) { //if enabling a core package, disable all other core packages GameMain.Config.SelectedContentPackages.RemoveWhere(cp => cp.CorePackage); } GameMain.Config.SelectedContentPackages.Add(newPackage); GameMain.Config.SaveNewPlayerConfig(); if (newPackage.Files.Any(f => f.Type == ContentType.Submarine)) { Submarine.RefreshSavedSubs(); } errorMsg = ""; return(true); }
/// <summary> /// Enables a workshop item by moving it to the game folder. /// </summary> public static bool EnableWorkShopItem(Workshop.Item item, bool allowFileOverwrite, out string errorMsg) { if (!item.Installed) { errorMsg = TextManager.Get("WorkshopErrorInstallRequiredToEnable").Replace("[itemname]", item.Title); DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); return(false); } string metaDataFilePath = Path.Combine(item.Directory.FullName, MetadataFileName); ContentPackage contentPackage = new ContentPackage(metaDataFilePath); string newContentPackagePath = GetWorkshopItemContentPackagePath(contentPackage); var allPackageFiles = Directory.GetFiles(item.Directory.FullName, "*", SearchOption.AllDirectories); List <string> nonContentFiles = new List <string>(); foreach (string file in allPackageFiles) { if (file == metaDataFilePath) { continue; } string relativePath = UpdaterUtil.GetRelativePath(file, item.Directory.FullName); string fullPath = Path.GetFullPath(relativePath); if (contentPackage.Files.Any(f => { string fp = Path.GetFullPath(f.Path); return(fp == fullPath); })) { continue; } if (ContentPackage.IsModFilePathAllowed(relativePath)) { nonContentFiles.Add(relativePath); } } if (!allowFileOverwrite) { if (File.Exists(newContentPackagePath)) { errorMsg = TextManager.Get("WorkshopErrorOverwriteOnEnable") .Replace("[itemname]", item.Title) .Replace("[filename]", newContentPackagePath); DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); return(false); } foreach (ContentFile contentFile in contentPackage.Files) { string sourceFile = Path.Combine(item.Directory.FullName, contentFile.Path); if (File.Exists(sourceFile) && File.Exists(contentFile.Path)) { errorMsg = TextManager.Get("WorkshopErrorOverwriteOnEnable") .Replace("[itemname]", item.Title) .Replace("[filename]", contentFile.Path); DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); return(false); } } } try { foreach (ContentFile contentFile in contentPackage.Files) { string sourceFile = Path.Combine(item.Directory.FullName, contentFile.Path); if (!File.Exists(sourceFile)) { continue; } if (!ContentPackage.IsModFilePathAllowed(contentFile)) { DebugConsole.ThrowError(TextManager.Get("WorkshopErrorIllegalPathOnEnable").Replace("[filename]", contentFile.Path)); continue; } //make sure the destination directory exists Directory.CreateDirectory(Path.GetDirectoryName(contentFile.Path)); File.Copy(sourceFile, contentFile.Path, overwrite: true); } foreach (string nonContentFile in nonContentFiles) { string sourceFile = Path.Combine(item.Directory.FullName, nonContentFile); if (!File.Exists(sourceFile)) { continue; } if (!ContentPackage.IsModFilePathAllowed(nonContentFile)) { DebugConsole.ThrowError(TextManager.Get("WorkshopErrorIllegalPathOnEnable").Replace("[filename]", nonContentFile)); continue; } Directory.CreateDirectory(Path.GetDirectoryName(nonContentFile)); File.Copy(sourceFile, nonContentFile, overwrite: true); } } catch (Exception e) { errorMsg = TextManager.Get("WorkshopErrorEnableFailed").Replace("[itemname]", item.Title) + " " + e.Message; DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); return(false); } var newPackage = new ContentPackage(contentPackage.Path, newContentPackagePath) { SteamWorkshopUrl = item.Url, InstallTime = item.Modified > item.Created ? item.Modified : item.Created }; newPackage.Save(newContentPackagePath); ContentPackage.List.Add(newPackage); if (newPackage.CorePackage) { //if enabling a core package, disable all other core packages GameMain.Config.SelectedContentPackages.RemoveWhere(cp => cp.CorePackage); } GameMain.Config.SelectedContentPackages.Add(newPackage); GameMain.Config.SaveNewPlayerConfig(); if (newPackage.Files.Any(f => f.Type == ContentType.Submarine)) { Submarine.RefreshSavedSubs(); } errorMsg = ""; return(true); }