From 4548c9b0aaa07dcc06d4a5fe0557e19d1c7fbd8a Mon Sep 17 00:00:00 2001 From: nya-a-cat <188900516+nya-a-cat@users.noreply.github.com> Date: Fri, 14 Aug 2026 12:02:06 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat(resource):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=BB=8E=E5=85=B6=E4=BB=96=E5=AE=9E=E4=BE=8B=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E8=B5=84=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../App/Localization/Languages/en-US.xaml | 6 +- .../App/Localization/Languages/zh-CN.xaml | 6 +- .../PageInstanceCompResource.xaml | 4 +- .../PageInstanceCompResource.xaml.cs | 55 +++++++++++++++++++ 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/PCL.Core/App/Localization/Languages/en-US.xaml b/PCL.Core/App/Localization/Languages/en-US.xaml index c090e7a13e..6e793f79a5 100644 --- a/PCL.Core/App/Localization/Languages/en-US.xaml +++ b/PCL.Core/App/Localization/Languages/en-US.xaml @@ -1069,6 +1069,10 @@ Export info Export detailed version info for resources Favorite + {0} file(s) available + No other instance contains files available for import + Select source instance + Import from another instance Install from files Loading resource list Loading resource list @@ -3570,4 +3574,4 @@ Minecraft window loaded: {0} ({1}) Minecraft window maximized: {0} - \ No newline at end of file + diff --git a/PCL.Core/App/Localization/Languages/zh-CN.xaml b/PCL.Core/App/Localization/Languages/zh-CN.xaml index 9bae29f93c..eeda141ff3 100644 --- a/PCL.Core/App/Localization/Languages/zh-CN.xaml +++ b/PCL.Core/App/Localization/Languages/zh-CN.xaml @@ -1069,6 +1069,10 @@ 导出信息 导出详细的资源的版本信息 收藏 + {0} 个可导入文件 + 没有找到包含可导入文件的其他实例 + 选择来源实例 + 从其他实例导入 从文件安装 正在加载资源列表 正在加载资源列表 @@ -3570,4 +3574,4 @@ Minecraft 窗口已加载:{0}({1}) 已最大化 Minecraft 窗口:{0} - \ No newline at end of file + diff --git a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml index 185ead92ab..1dbd6e10d4 100644 --- a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml +++ b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml @@ -20,6 +20,8 @@ + - \ No newline at end of file + diff --git a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs index 00ac8ee7d1..80422aeaf1 100644 --- a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs +++ b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs @@ -40,6 +40,7 @@ public PageInstanceCompResource() BtnHintOpen.Click += BtnManageOpen_Click; BtnManageSelectAll.Click += BtnManageSelectAll_Click; BtnManageInstall.Click += BtnManageInstall_Click; + BtnManageImport.Click += BtnManageImport_Click; BtnHintInstall.Click += BtnManageInstall_Click; BtnManageInfoExport.Click += BtnManageInfoExport_Click; BtnManageDownload.Click += BtnManageDownload_Click; @@ -117,6 +118,9 @@ public PageInstanceCompResource(ModComp.CompType loadCompType) BtnSelectDisable.Visibility = Visibility.Collapsed; } + if (new[] { ModComp.CompType.Shader, ModComp.CompType.ResourcePack }.Contains(currentCompType)) + BtnManageImport.Visibility = Visibility.Visible; + // 投影文件管理页隐藏下载按钮 if (currentCompType == ModComp.CompType.Schematic) { @@ -136,6 +140,7 @@ public PageInstanceCompResource(ModComp.CompType loadCompType) BtnHintOpen.Click += BtnManageOpen_Click; BtnManageSelectAll.Click += BtnManageSelectAll_Click; BtnManageInstall.Click += BtnManageInstall_Click; + BtnManageImport.Click += BtnManageImport_Click; BtnHintInstall.Click += BtnManageInstall_Click; BtnManageDownload.Click += BtnManageDownload_Click; BtnHintDownload.Click += BtnManageDownload_Click; @@ -1021,6 +1026,56 @@ private void BtnManageInstall_Click(object sender, MouseButtonEventArgs e) InstallCompFiles(fileList, currentCompType, CurrentFolderPath); } + /// + /// 从其他实例导入资源包或光影包。 + /// + private void BtnManageImport_Click(object sender, MouseButtonEventArgs e) + { + var folderName = currentCompType switch + { + ModComp.CompType.ResourcePack => "resourcepacks", + ModComp.CompType.Shader => "shaderpacks", + _ => null + }; + if (folderName is null) return; + + var targetFolder = Path.GetFullPath(Path.Combine(PageInstanceLeft.McInstance.PathIndie, folderName)); + var sources = ModInstanceList.mcInstanceList.Values.SelectMany(list => list) + .Where(instance => instance.state != McInstanceState.Error && + !instance.Equals(PageInstanceLeft.McInstance)) + .Select(instance => + { + var sourceFolder = Path.GetFullPath(Path.Combine(instance.PathIndie, folderName)); + var files = Directory.Exists(sourceFolder) + ? Directory.GetFiles(sourceFolder, "*.zip", SearchOption.TopDirectoryOnly) + : []; + return (Instance: instance, Folder: sourceFolder, Files: files); + }) + .Where(source => !source.Folder.Equals(targetFolder, StringComparison.OrdinalIgnoreCase) && + source.Files.Length > 0) + .OrderBy(source => source.Instance.Name) + .ToList(); + + if (sources.Count == 0) + { + HintService.Hint(Lang.Text("Instance.Resource.Import.NoAvailableInstance")); + return; + } + + var selection = sources.Select(source => (IMyRadio)new MyListItem + { + Title = source.Instance.Name, + Info = Lang.Text("Instance.Resource.Import.FileCount", source.Files.Length), + Type = MyListItem.CheckType.RadioBox + }).ToList(); + var selectedIndex = ModMain.MyMsgBoxSelect(selection, + Lang.Text("Instance.Resource.Import.SelectInstance"), + Lang.Text("Common.Action.Confirm"), Lang.Text("Common.Action.Cancel")); + if (selectedIndex is null) return; + + InstallCompFiles(sources[selectedIndex.Value].Files, currentCompType, CurrentFolderPath); + } + /// /// 尝试安装 Mod。 /// 返回输入的文件是否为一个 Mod 文件,仅用于判断拖拽行为。 From 94898521cab419c189bc1faa914ab03cf2e2a349 Mon Sep 17 00:00:00 2001 From: nya-a-cat <188900516+nya-a-cat@users.noreply.github.com> Date: Fri, 14 Aug 2026 12:18:29 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix(resource):=20=E8=A1=A5=E5=85=A8?= =?UTF-8?q?=E7=A9=BA=E5=88=97=E8=A1=A8=E5=AF=BC=E5=85=A5=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PageInstanceCompResource.xaml | 2 ++ .../PageInstanceCompResource.xaml.cs | 24 ++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml index 1dbd6e10d4..4d6572ed75 100644 --- a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml +++ b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml @@ -73,6 +73,8 @@ Padding="12,0" Visibility="Collapsed" /> + { var sourceFolder = Path.GetFullPath(Path.Combine(instance.PathIndie, folderName)); - var files = Directory.Exists(sourceFolder) - ? Directory.GetFiles(sourceFolder, "*.zip", SearchOption.TopDirectoryOnly) - : []; + var files = GetImportFiles(instance, sourceFolder); return (Instance: instance, Folder: sourceFolder, Files: files); }) .Where(source => !source.Folder.Equals(targetFolder, StringComparison.OrdinalIgnoreCase) && @@ -1076,6 +1079,21 @@ private void BtnManageImport_Click(object sender, MouseButtonEventArgs e) InstallCompFiles(sources[selectedIndex.Value].Files, currentCompType, CurrentFolderPath); } + private static string[] GetImportFiles(McInstance instance, string sourceFolder) + { + try + { + return Directory.Exists(sourceFolder) + ? Directory.GetFiles(sourceFolder, "*.zip", SearchOption.TopDirectoryOnly) + : []; + } + catch (Exception ex) + { + ModBase.Log(ex, $"读取实例 {instance.Name} 的资源文件失败"); + return []; + } + } + /// /// 尝试安装 Mod。 /// 返回输入的文件是否为一个 Mod 文件,仅用于判断拖拽行为。 From a0ce7dfc2943480c8abf664338b4caed6100a4ff Mon Sep 17 00:00:00 2001 From: nya-a-cat <188900516+nya-a-cat@users.noreply.github.com> Date: Fri, 14 Aug 2026 12:57:32 +0800 Subject: [PATCH 3/4] =?UTF-8?q?style(resource):=20=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E7=A7=81=E6=9C=89=E8=BE=85=E5=8A=A9=E6=96=B9=E6=B3=95=E5=91=BD?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pages/PageInstance/PageInstanceCompResource.xaml.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs index afdcb3a7d9..432f3468c9 100644 --- a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs +++ b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs @@ -1051,7 +1051,7 @@ private void BtnManageImport_Click(object sender, MouseButtonEventArgs e) .Select(instance => { var sourceFolder = Path.GetFullPath(Path.Combine(instance.PathIndie, folderName)); - var files = GetImportFiles(instance, sourceFolder); + var files = _GetImportFiles(instance, sourceFolder); return (Instance: instance, Folder: sourceFolder, Files: files); }) .Where(source => !source.Folder.Equals(targetFolder, StringComparison.OrdinalIgnoreCase) && @@ -1079,7 +1079,7 @@ private void BtnManageImport_Click(object sender, MouseButtonEventArgs e) InstallCompFiles(sources[selectedIndex.Value].Files, currentCompType, CurrentFolderPath); } - private static string[] GetImportFiles(McInstance instance, string sourceFolder) + private static string[] _GetImportFiles(McInstance instance, string sourceFolder) { try { From 0db2ec4028a45fdd189c77163356c209af562d9d Mon Sep 17 00:00:00 2001 From: nya-a-cat <188900516+nya-a-cat@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:57:51 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix(resource):=20=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E5=A4=8D=E5=88=B6=E5=85=B6=E4=BB=96=E5=AE=9E=E4=BE=8B=E8=B5=84?= =?UTF-8?q?=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../App/Localization/Languages/en-US.xaml | 7 +- .../App/Localization/Languages/zh-CN.xaml | 7 +- .../PageInstanceCompResource.xaml.cs | 92 +++++++++++++++++-- 3 files changed, 95 insertions(+), 11 deletions(-) diff --git a/PCL.Core/App/Localization/Languages/en-US.xaml b/PCL.Core/App/Localization/Languages/en-US.xaml index 6e793f79a5..d43ace93a5 100644 --- a/PCL.Core/App/Localization/Languages/en-US.xaml +++ b/PCL.Core/App/Localization/Languages/en-US.xaml @@ -1069,9 +1069,12 @@ Export info Export detailed version info for resources Favorite - {0} file(s) available - No other instance contains files available for import + {0} resource item(s) available + No other instance contains resources available for import + A resource named {0} already exists. Overwrite it? + Confirm resource overwrite Select source instance + Imported {0} resource item(s) Import from another instance Install from files Loading resource list diff --git a/PCL.Core/App/Localization/Languages/zh-CN.xaml b/PCL.Core/App/Localization/Languages/zh-CN.xaml index eeda141ff3..c78a5a4925 100644 --- a/PCL.Core/App/Localization/Languages/zh-CN.xaml +++ b/PCL.Core/App/Localization/Languages/zh-CN.xaml @@ -1069,9 +1069,12 @@ 导出信息 导出详细的资源的版本信息 收藏 - {0} 个可导入文件 - 没有找到包含可导入文件的其他实例 + {0} 个可导入资源 + 没有找到包含可导入资源的其他实例 + 已存在同名资源:{0},是否覆盖? + 资源覆盖确认 选择来源实例 + 已导入 {0} 个资源 从其他实例导入 从文件安装 正在加载资源列表 diff --git a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs index 432f3468c9..06869c3e48 100644 --- a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs +++ b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceCompResource.xaml.cs @@ -1051,11 +1051,11 @@ private void BtnManageImport_Click(object sender, MouseButtonEventArgs e) .Select(instance => { var sourceFolder = Path.GetFullPath(Path.Combine(instance.PathIndie, folderName)); - var files = _GetImportFiles(instance, sourceFolder); - return (Instance: instance, Folder: sourceFolder, Files: files); + var entries = _GetImportEntries(instance, sourceFolder); + return (Instance: instance, Folder: sourceFolder, Entries: entries); }) .Where(source => !source.Folder.Equals(targetFolder, StringComparison.OrdinalIgnoreCase) && - source.Files.Length > 0) + source.Entries.Length > 0) .OrderBy(source => source.Instance.Name) .ToList(); @@ -1068,7 +1068,7 @@ private void BtnManageImport_Click(object sender, MouseButtonEventArgs e) var selection = sources.Select(source => (IMyRadio)new MyListItem { Title = source.Instance.Name, - Info = Lang.Text("Instance.Resource.Import.FileCount", source.Files.Length), + Info = Lang.Text("Instance.Resource.Import.ItemCount", source.Entries.Length), Type = MyListItem.CheckType.RadioBox }).ToList(); var selectedIndex = ModMain.MyMsgBoxSelect(selection, @@ -1076,15 +1076,20 @@ private void BtnManageImport_Click(object sender, MouseButtonEventArgs e) Lang.Text("Common.Action.Confirm"), Lang.Text("Common.Action.Cancel")); if (selectedIndex is null) return; - InstallCompFiles(sources[selectedIndex.Value].Files, currentCompType, CurrentFolderPath); + _ImportEntries(sources[selectedIndex.Value].Entries, targetFolder); } - private static string[] _GetImportFiles(McInstance instance, string sourceFolder) + private static string[] _GetImportEntries(McInstance instance, string sourceFolder) { try { return Directory.Exists(sourceFolder) - ? Directory.GetFiles(sourceFolder, "*.zip", SearchOption.TopDirectoryOnly) + ? Directory.EnumerateFileSystemEntries(sourceFolder, "*", new EnumerationOptions + { + RecurseSubdirectories = false, + IgnoreInaccessible = false, + AttributesToSkip = FileAttributes.ReparsePoint + }).ToArray() : []; } catch (Exception ex) @@ -1094,6 +1099,79 @@ private static string[] _GetImportFiles(McInstance instance, string sourceFolder } } + private void _ImportEntries(IEnumerable entries, string targetFolder) + { + try + { + Directory.CreateDirectory(targetFolder); + var importedCount = 0; + foreach (var sourceEntry in entries) + { + var entryName = Path.GetFileName(Path.TrimEndingDirectorySeparator(sourceEntry)); + var targetEntry = Path.Combine(targetFolder, entryName); + if (File.Exists(targetEntry) || Directory.Exists(targetEntry)) + { + if (ModMain.MyMsgBox( + Lang.Text("Instance.Resource.Import.OverwriteConfirm.Message", entryName), + Lang.Text("Instance.Resource.Import.OverwriteConfirm.Title"), + Lang.Text("Common.Action.Overwrite"), Lang.Text("Common.Action.Cancel")) != 1) + continue; + _DeleteImportTarget(targetEntry); + } + + if (File.Exists(sourceEntry)) + ModBase.CopyFile(sourceEntry, targetEntry); + else if (Directory.Exists(sourceEntry)) + _CopyImportDirectory(sourceEntry, targetEntry); + else + continue; + importedCount += 1; + } + + if (importedCount > 0) + { + HintService.Hint(Lang.Text("Instance.Resource.Import.Success", importedCount), HintType.Success); + ReloadCompFileList(true); + } + } + catch (Exception ex) + { + ModBase.Log(ex, "从其他实例复制资源失败", ModBase.LogLevel.Msgbox, + userSummary: Lang.Text("Instance.Resource.Error.OperationFailed")); + } + } + + private static void _DeleteImportTarget(string targetEntry) + { + if (File.Exists(targetEntry)) + { + File.Delete(targetEntry); + return; + } + + if (!Directory.Exists(targetEntry)) return; + if (File.GetAttributes(targetEntry).HasFlag(FileAttributes.ReparsePoint)) + Directory.Delete(targetEntry); + else + ModBase.DeleteDirectory(targetEntry); + } + + private static void _CopyImportDirectory(string sourceFolder, string targetFolder) + { + Directory.CreateDirectory(targetFolder); + var options = new EnumerationOptions + { + RecurseSubdirectories = true, + IgnoreInaccessible = false, + AttributesToSkip = FileAttributes.ReparsePoint + }; + foreach (var sourceFile in Directory.EnumerateFiles(sourceFolder, "*", options)) + { + var targetFile = Path.Combine(targetFolder, Path.GetRelativePath(sourceFolder, sourceFile)); + ModBase.CopyFile(sourceFile, targetFile); + } + } + /// /// 尝试安装 Mod。 /// 返回输入的文件是否为一个 Mod 文件,仅用于判断拖拽行为。