diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..f4820c8
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+# These are supported funding model platforms
+
+custom: ['https://afdian.com/a/LTCat']
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e0b81da..f2c4927 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -9,6 +9,7 @@ on:
paths:
- 'Plain Craft Launcher 2/**'
- '.github/workflows/**'
+ workflow_dispatch:
jobs:
@@ -29,7 +30,7 @@ jobs:
- name: Set Describe
shell: bash
run: |
- Describe=`git describe --tags`
+ Describe=`git describe --tags --always`
echo "Describe=$Describe" >> $GITHUB_ENV
- name: Setup MSBuild.exe
diff --git a/LICENCE b/LICENCE
index 5825c79..d06fab9 100644
--- a/LICENCE
+++ b/LICENCE
@@ -2,23 +2,23 @@
一、承诺与声明。
- 开发者承诺,在您遵守本指南的情况下,不会追究您的法律责任,但最终裁量权仍由开发者保留。
- 开发者仍保留所有权利(All Rights Reserved),且可能随时修改本指南,本指南并不是永久性保证。
+ 开发者承诺,在您遵守本指南的情况下,不会追究您的责任,但最终裁量权仍由开发者保留。
+ 法律上,开发者仍保留所有权利(All Rights Reserved),且可能随时修改本指南,本指南并不是永久性保证。
二、少量使用情形。
如果您仅合理使用本存储库中的少量内容,或是参考实现思路,您必须:
- (一)给出适当的署名,且提供指向本存储库的链接。
- (二)不得以任何方式暗示开发者为您或您的使用作担保。
+ 1、给出适当的署名,且提供指向本存储库的链接。
+ 2、不得以任何方式暗示开发者为您或您的使用作担保。
三、大量使用情形。
- 如果您基于该存储库进行衍生创作,或合理使用了本存储库中的较大量内容,您必须:
- (一)给出适当的署名,且提供指向本存储库的链接。
- (二)不得以任何方式暗示开发者为您或您的使用作担保。
- (三)给出适当的说明,表示这是第三方内容。
- (四)使用本指南文件作为协议,不得附加额外条款。
- (五)不得分发编译后的可执行文件。
+ 如果您基于该存储库创作衍生作品,或合理使用了本存储库中的较大量内容,您必须:
+ 1、给出适当的署名,且提供指向本存储库的链接。GitHub 上的 Fork 可视为满足此条。
+ 2、不得以任何方式暗示开发者为您或您的使用作担保,且需要给出适当的说明,表示这是非官方内容。
+ 3、使用本指南文件作为协议,不得附加额外条款。
+ 4、该衍生作品不能被允许用于再次分发,这包括制作整合包。
+ 5、该衍生作品的名称必须以 “PCL” 或 “Plain Craft Launcher” 开头,并在其后添加后缀,例如 “PCL 启动修复版”、“PCL PR Collection”。
————————————
@@ -27,9 +27,5 @@
因为没有法律专业人士检查,所以这不敢作为正式的法律协议,如果有专业人士愿意帮忙改一改我也很乐意……
这些规则主要是为了阻止恶意的使用和 “山寨版” 的出现,常规、善意的使用都没啥问题的,放心吧!
-如果你只是想参考一下,或者用了一小部分代码:
- 署名就行啦。
-如果你整了个魔改版,或者用了一大堆代码:
- 你不能把编译后的文件发给其他人,但可以私下使用。
-如果你修改了代码,并且打算公开:
- 请仔细参考上面的第三条。
+如果你只是想参考一下,或者用了一小部分代码,署个名就行啦。
+如果你整了个魔改版,或者用了一大堆代码,请仔细参考上面的第三条。
diff --git a/Plain Craft Launcher 2/Application.xaml.vb b/Plain Craft Launcher 2/Application.xaml.vb
index eb34ceb..34fc417 100644
--- a/Plain Craft Launcher 2/Application.xaml.vb
+++ b/Plain Craft Launcher 2/Application.xaml.vb
@@ -90,7 +90,7 @@ Public Class Application
ToolTipService.HorizontalOffsetProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(8.0))
ToolTipService.VerticalOffsetProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(4.0))
'设置初始窗口
- If Setup.Get("UiLauncherLogo") AndAlso Not FormMain.IsLinkRestart Then
+ If Setup.Get("UiLauncherLogo") Then
FrmStart = New SplashScreen("Images\icon.ico")
FrmStart.Show(False, True)
End If
@@ -103,6 +103,7 @@ Public Class Application
Log($"[Start] 识别码:{UniqueAddress}{If(ThemeCheckOne(9), ",已解锁反馈主题", "")}")
Log($"[Start] 程序路径:{PathWithName}")
Log($"[Start] 系统编码:{Encoding.Default} ({Encoding.Default.CodePage}, GBK={IsGBKEncoding})")
+ Log($"[Start] 管理员权限:{IsAdmin()}")
'检测压缩包运行
If Path.Contains(IO.Path.GetTempPath()) OrElse Path.Contains("AppData\Local\Temp\") Then
MyMsgBox("PCL 正在临时文件夹运行,设置、游戏存档等很可能无法保存,且部分功能会无法使用或出错。" & vbCrLf & "请将 PCL 从压缩文件中解压,或是更换文件夹后再继续使用!", "环境警告", "我知道了", IsWarn:=True)
diff --git a/Plain Craft Launcher 2/Controls/MyCard.vb b/Plain Craft Launcher 2/Controls/MyCard.vb
index 11b7669..8ae95ef 100644
--- a/Plain Craft Launcher 2/Controls/MyCard.vb
+++ b/Plain Craft Launcher 2/Controls/MyCard.vb
@@ -98,21 +98,13 @@
'排序
Select Case Type
Case 3
- Stack.Tag = Sort(CType(Stack.Tag, List(Of DlOptiFineListEntry)), Function(Left As DlOptiFineListEntry, Right As DlOptiFineListEntry) As Boolean
- Return VersionSortBoolean(Left.NameDisplay, Right.NameDisplay)
- End Function)
+ Stack.Tag = Sort(CType(Stack.Tag, List(Of DlOptiFineListEntry)), Function(a, b) VersionSortBoolean(a.NameDisplay, b.NameDisplay))
Case 4, 10
- Stack.Tag = Sort(CType(Stack.Tag, List(Of DlLiteLoaderListEntry)), Function(Left As DlLiteLoaderListEntry, Right As DlLiteLoaderListEntry) As Boolean
- Return VersionSortBoolean(Left.Inherit, Right.Inherit)
- End Function)
+ Stack.Tag = Sort(CType(Stack.Tag, List(Of DlLiteLoaderListEntry)), Function(a, b) VersionSortBoolean(a.Inherit, b.Inherit))
Case 6
- Stack.Tag = Sort(CType(Stack.Tag, List(Of DlForgeVersionEntry)), Function(Left As DlForgeVersionEntry, Right As DlForgeVersionEntry) As Boolean
- Return VersionSortBoolean(Left.Version, Right.Version)
- End Function)
+ Stack.Tag = Sort(CType(Stack.Tag, List(Of DlForgeVersionEntry)), Function(a, b) a.Version > b.Version)
Case 8, 9
- Stack.Tag = Sort(CType(Stack.Tag, List(Of CompFile)), Function(Left As CompFile, Right As CompFile) As Boolean
- Return Left.ReleaseDate > Right.ReleaseDate
- End Function)
+ Stack.Tag = Sort(CType(Stack.Tag, List(Of CompFile)), Function(a, b) a.ReleaseDate > b.ReleaseDate)
End Select
'控件转换
Select Case Type
@@ -144,9 +136,8 @@
Case 6
Stack.Children.Add(ForgeDownloadListItem(Data, AddressOf ForgeSave_Click, True))
Case 7
- Stack.Children.Add(McDownloadListItem(Data, Sub(sender, e) '不能使用 AddressOf,这导致了 #535,原因完全不明,疑似是编译器 Bug
- FrmDownloadInstall.MinecraftSelected(sender, e)
- End Sub, False))
+ '不能使用 AddressOf,这导致了 #535,原因完全不明,疑似是编译器 Bug
+ Stack.Children.Add(McDownloadListItem(Data, Sub(sender, e) FrmDownloadInstall.MinecraftSelected(sender, e), False))
Case 8
If CType(Stack.Tag, List(Of CompFile)).Distinct(Function(a, b) a.DisplayName = b.DisplayName).Count <>
CType(Stack.Tag, List(Of CompFile)).Count Then
@@ -171,6 +162,8 @@
Stack.Children.Add(CType(Data, HelpEntry).ToListItem)
Case 12
Stack.Children.Add(FabricDownloadListItem(CType(Data, JObject), AddressOf FrmDownloadInstall.Fabric_Selected))
+ Case 13
+ Stack.Children.Add(NeoForgeDownloadListItem(Data, AddressOf NeoForgeSave_Click, True))
Case Else
Log("未知的虚拟化种类:" & Type, LogLevel.Feedback)
End Select
diff --git a/Plain Craft Launcher 2/Controls/MyIconButton.xaml.vb b/Plain Craft Launcher 2/Controls/MyIconButton.xaml.vb
index ca8f99d..d7103c6 100644
--- a/Plain Craft Launcher 2/Controls/MyIconButton.xaml.vb
+++ b/Plain Craft Launcher 2/Controls/MyIconButton.xaml.vb
@@ -111,7 +111,16 @@
If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
If PanBack.Background Is Nothing Then PanBack.Background = New MyColor(0, 255, 255, 255)
- If Path.Fill Is Nothing AndAlso Theme = Themes.Black Then Path.Fill = New MyColor(140, 0, 0, 0)
+ If Path.Fill Is Nothing Then
+ Select Case Theme
+ Case Themes.Red
+ Path.Fill = New MyColor(160, 255, 76, 76)
+ Case Themes.Black
+ Path.Fill = New MyColor(160, 0, 0, 0)
+ Case Themes.Custom
+ Path.Fill = New MyColor(160, Foreground)
+ End Select
+ End If
If IsMouseOver Then
'指向
Dim AnimList As New List(Of AniData)
diff --git a/Plain Craft Launcher 2/Controls/MyPageRight.vb b/Plain Craft Launcher 2/Controls/MyPageRight.vb
index 9d1db6e..4fafd60 100644
--- a/Plain Craft Launcher 2/Controls/MyPageRight.vb
+++ b/Plain Craft Launcher 2/Controls/MyPageRight.vb
@@ -74,13 +74,13 @@
'添加结束 Invoke
If FinishedInvoke IsNot Nothing Then
AddHandler RealLoader.PreviewFinish,
- Sub()
- Do While PageState = MyPageRight.PageStates.PageExit OrElse PageState = MyPageRight.PageStates.ContentExit
- Thread.Sleep(10) '不在退出动画时执行 UI 线程操作,避免退出动画被重置
- Loop
- RunInUiWait(Sub() FinishedInvoke(RealLoader))
- Thread.Sleep(20) '由于大量初始化控件会导致掉帧,延迟触发 State 改变事件
- End Sub
+ Sub()
+ Do While PageState = MyPageRight.PageStates.PageExit OrElse PageState = MyPageRight.PageStates.ContentExit
+ Thread.Sleep(10) '不在退出动画时执行 UI 线程操作,避免退出动画被重置
+ Loop
+ RunInUiWait(Sub() FinishedInvoke(RealLoader))
+ Thread.Sleep(20) '由于大量初始化控件会导致掉帧,延迟触发 State 改变事件
+ End Sub
End If
AddHandler RealLoader.OnStateChangedUi, Sub(Loader As LoaderBase, NewState As LoadState, OldState As LoadState) RunInUi(Sub() PageLoaderState(Loader, NewState, OldState))
'隐藏 UI
diff --git a/Plain Craft Launcher 2/FormMain.xaml.vb b/Plain Craft Launcher 2/FormMain.xaml.vb
index 5ed09e6..4dedbcc 100644
--- a/Plain Craft Launcher 2/FormMain.xaml.vb
+++ b/Plain Craft Launcher 2/FormMain.xaml.vb
@@ -10,6 +10,22 @@ Public Class FormMain
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
'统计更新日志条目
#If BETA Then
+ If LastVersion < 332 Then 'Release 2.8.3
+ If LastVersion = 330 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复部分玩家无法启动 MC 的 Bug"))
+ End If
+ If LastVersion < 330 Then 'Release 2.8.2
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "NeoForge 兼容与自动安装"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持编译、运行 PCL 开源代码"))
+ FeatureCount += 15
+ BugCount += 22
+ End If
+ If LastVersion < 326 Then 'Release 2.7.4
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "会自动隐藏明显不可用的自动安装选项"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化正版登录流程和 MC 性能"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复正版登录时弹出脚本错误提示的 Bug"))
+ FeatureCount += 17
+ BugCount += 19
+ End If
If LastVersion < 323 Then 'Release 2.7.3
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 启动游戏前进行内存优化 设置"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化 MC 性能"))
@@ -108,6 +124,37 @@ Public Class FormMain
'3:BUG+ IMP* FEAT-
'2:BUG* IMP-
'1:BUG-
+ If LastVersion < 333 Then 'Snapshot 2.8.4
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "下载 Mod 时会使用 MCIM 国内镜像源"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "打开 PCL 时会自动安装同目录下的 modpack.zip"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "爱发电域名迁移至 afdian.com"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复 1.20.1+ 离线登录使用正版皮肤时无法保存游戏的 Bug"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复安装的 1.14~1.15 Forge+OptiFine 无法进入世界的 Bug"))
+ FeatureCount += 13
+ BugCount += 17
+ End If
+ If LastVersion < 331 Then 'Snapshot 2.8.3
+ If LastVersion = 329 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复部分玩家无法启动 MC 的 Bug"))
+ End If
+ If LastVersion < 329 Then 'Snapshot 2.8.2
+ If LastVersion >= 327 Then
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法安装 Beta 版 NeoForge 的整合包的 Bug"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复自动安装无法选择部分 OptiFine 的 Bug"))
+ End If
+ FeatureCount += 4
+ BugCount += 8
+ End If
+ If LastVersion < 328 Then 'Snapshot 2.8.1
+ If LastVersion = 327 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法安装 Forge 1.12.2- 的 Bug"))
+ If LastVersion = 327 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法输入解锁码的 Bug"))
+ If LastVersion = 327 Then BugCount += 1
+ End If
+ If LastVersion < 327 Then 'Snapshot 2.8.0
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "NeoForge 兼容与自动安装"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持编译、运行 PCL 开源代码"))
+ FeatureCount += 11
+ BugCount += 14
+ End If
If LastVersion < 325 Then 'Snapshot 2.7.4
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "会自动隐藏明显不可用的自动安装选项"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化正版登录流程和 MC 性能"))
@@ -269,17 +316,13 @@ Public Class FormMain
RunInNewThread(
Sub()
If MyMsgBox(Content, "PCL 已更新至 " & VersionDisplayName, "确定", "完整更新日志") = 2 Then
- OpenWebsite("https://afdian.net/a/LTCat?tab=feed")
+ OpenWebsite("https://afdian.com/a/LTCat?tab=feed")
End If
End Sub, "UpdateLog Output")
End Sub
'窗口加载
Private IsWindowLoadFinished As Boolean = False
- '''
- ''' 是否为联机提权后自动重启。
- '''
- Public Shared IsLinkRestart As Boolean = False
Public Sub New()
ApplicationStartTick = GetTimeTick()
'窗体参数初始化
@@ -317,7 +360,6 @@ Public Class FormMain
PanMainLeft.Child = FrmLaunchLeft
PanMainRight.Child = FrmLaunchRight
FrmLaunchRight.PageState = MyPageRight.PageStates.ContentStay
- If IsLinkRestart Then PageChange(PageType.Link, PageSubType.LinkIoi)
'模式提醒
#If DEBUG Then
Hint("[开发者模式] PCL 正以开发者模式运行,这可能会造成严重的性能下降,请务必立即向开发者反馈此问题!", HintType.Critical)
@@ -386,7 +428,7 @@ Public Class FormMain
Sub()
PanBack.RenderTransform = Nothing
IsWindowLoadFinished = True
- Log($"[System] DPI:{DPI},系统版本:{OsVersion},PCL 位置:{PathWithName}")
+ Log($"[System] DPI:{DPI},系统版本:{Environment.OSVersion.VersionString},PCL 位置:{PathWithName}")
End Sub, , True)
}, "Form Show")
'Timer 启动
@@ -532,7 +574,7 @@ Public Class FormMain
RunInNewThread(
Sub()
Log("[System] 正在强行停止任务")
- For Each Task As LoaderBase In LoaderTaskbar.ToArray
+ For Each Task As LoaderBase In LoaderTaskbar.ToList()
Task.Abort()
Next
End Sub, "强行停止下载任务")
@@ -851,10 +893,12 @@ Public Class FormMain
Install:
Try
For Each ModFile In FilePathList
- CopyFile(ModFile, TargetVersion.PathIndie & "mods\" & GetFileNameFromPath(ModFile))
+ Dim NewFileName = GetFileNameFromPath(ModFile).Replace(".disabled", "")
+ If Not NewFileName.Contains(".") Then NewFileName += ".jar" '#4227
+ CopyFile(ModFile, TargetVersion.PathIndie & "mods\" & NewFileName)
Next
If FilePathList.Count = 1 Then
- Hint($"已安装 {GetFileNameFromPath(FilePathList.First)}!", HintType.Finish)
+ Hint($"已安装 {GetFileNameFromPath(FilePathList.First).Replace(".disabled", "")}!", HintType.Finish)
Else
Hint($"已安装 {FilePathList.Count} 个 Mod!", HintType.Finish)
End If
@@ -871,7 +915,7 @@ Install:
'安装整合包
If {"zip", "rar", "mrpack"}.Any(Function(t) t = Extension) Then '部分压缩包是 zip 格式但后缀为 rar,总之试一试
Log("[System] 文件为压缩包,尝试作为整合包安装")
- If ModpackInstall(FilePath, ShowHint:=False) Then Exit Sub
+ If ModpackInstall(FilePath, ShowHint:=False) IsNot Nothing Then Exit Sub
End If
'RAR 处理
If Extension = "rar" Then
@@ -1019,10 +1063,11 @@ Install:
DownloadClient = 4
DownloadOptiFine = 5
DownloadForge = 6
- DownloadFabric = 7
- DownloadLiteLoader = 8
- DownloadMod = 10
- DownloadPack = 11
+ DownloadNeoForge = 7
+ DownloadFabric = 8
+ DownloadLiteLoader = 9
+ DownloadMod = 11
+ DownloadPack = 12
SetupLaunch = 0
SetupUI = 1
SetupSystem = 2
diff --git a/Plain Craft Launcher 2/Images/Blocks/NeoForge.png b/Plain Craft Launcher 2/Images/Blocks/NeoForge.png
new file mode 100644
index 0000000..7d46d39
Binary files /dev/null and b/Plain Craft Launcher 2/Images/Blocks/NeoForge.png differ
diff --git a/Plain Craft Launcher 2/Images/Heads/DoodleHuang.png b/Plain Craft Launcher 2/Images/Heads/DoodleHuang.png
deleted file mode 100644
index 803e812..0000000
Binary files a/Plain Craft Launcher 2/Images/Heads/DoodleHuang.png and /dev/null differ
diff --git a/Plain Craft Launcher 2/Images/Heads/z0z0r4.png b/Plain Craft Launcher 2/Images/Heads/z0z0r4.png
new file mode 100644
index 0000000..622a0bf
Binary files /dev/null and b/Plain Craft Launcher 2/Images/Heads/z0z0r4.png differ
diff --git a/Plain Craft Launcher 2/Modules/Base/ModBase.vb b/Plain Craft Launcher 2/Modules/Base/ModBase.vb
index 57a27cd..f41e5b1 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModBase.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModBase.vb
@@ -11,12 +11,12 @@ Public Module ModBase
#Region "声明"
'下列版本信息由更新器自动修改
- Public Const VersionBaseName As String = "2.7.4" '不含分支前缀的显示用版本名
- Public Const VersionStandardCode As String = "2.7.4." & VersionBranchCode '标准格式的四段式版本号
+ Public Const VersionBaseName As String = "2.8.4" '不含分支前缀的显示用版本名
+ Public Const VersionStandardCode As String = "2.8.4." & VersionBranchCode '标准格式的四段式版本号
#If BETA Then
- Public Const VersionCode As Integer = 323 'Release
+ Public Const VersionCode As Integer = 332 'Release
#Else
- Public Const VersionCode As Integer = 325 'Snapshot
+ Public Const VersionCode As Integer = 333 'Snapshot
#End If
'自动生成的版本信息
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
@@ -80,13 +80,9 @@ Public Module ModBase
'''
Public IsGBKEncoding As Boolean = Encoding.Default.CodePage = 936
'''
- ''' 操作系统版本。Win10 为 10.0。
- '''
- Public OsVersion As Version = Environment.OSVersion.Version
- '''
''' 系统盘盘符,以 \ 结尾。例如 “C:\”。
'''
- Public OsDrive As String = Environment.GetLogicalDrives().First.ToUpper.First & ":\"
+ Public OsDrive As String = Environment.GetLogicalDrives().Where(Function(p) Directory.Exists(p)).First.ToUpper.First & ":\" '#3799
'''
''' 程序的缓存文件夹路径,以 \ 结尾。
'''
@@ -1016,7 +1012,7 @@ Public Module ModBase
'''
Public Function CheckPermission(Path As String) As Boolean
Try
- If Path = "" Then Return False
+ If String.IsNullOrEmpty(Path) Then Return False
If Not Path.EndsWithF("\") Then Path += "\"
If Path.EndsWithF(":\System Volume Information\") OrElse Path.EndsWithF(":\$RECYCLE.BIN\") Then Return False
If Not Directory.Exists(Path) Then Return False
@@ -1108,8 +1104,6 @@ Re:
Dim Retry As Boolean = False
Re:
Try
- ''检测该文件是否在下载中,若在下载则放弃检测
- 'If IgnoreOnDownloading AndAlso NetManage.Files.ContainsKey(FilePath) AndAlso NetManage.Files(FilePath).State <= NetState.Merge Then Return ""
'获取 SHA1
Dim file As New FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
Dim sha1 As SHA1 = New SHA1CryptoServiceProvider()
@@ -1257,12 +1251,19 @@ Re:
Dim DeletedCount As Integer = 0
Dim Temp As String()
Temp = Directory.GetFiles(Path)
- For Each str As String In Temp
+ For Each FilePath As String In Temp
+ Dim RetriedFile As Boolean = False
+RetryFile:
Try
- File.Delete(str)
+ File.Delete(FilePath)
DeletedCount += 1
Catch ex As Exception
- If IgnoreIssue Then
+ If Not RetriedFile Then
+ RetriedFile = True
+ Log(ex, $"删除文件失败,将在 0.3s 后重试({FilePath})")
+ Thread.Sleep(300)
+ GoTo RetryFile
+ ElseIf IgnoreIssue Then
Log(ex, "删除单个文件可忽略地失败")
Else
Throw
@@ -1273,10 +1274,17 @@ Re:
For Each str As String In Temp
DeleteDirectory(str, IgnoreIssue)
Next
+ Dim RetriedDir As Boolean = False
+RetryDir:
Try
Directory.Delete(Path, True)
Catch ex As Exception
- If IgnoreIssue Then
+ If Not RetriedDir Then
+ RetriedDir = True
+ Log(ex, $"删除文件夹失败,将在 0.3s 后重试({Path})")
+ Thread.Sleep(300)
+ GoTo RetryDir
+ ElseIf IgnoreIssue Then
Log(ex, "删除单个文件夹可忽略地失败")
Else
Throw
@@ -1573,14 +1581,14 @@ Re:
''' 获取处于两个子字符串之间的部分。
''' 会裁切尽可能多的内容:匹配开始使用 LastIndexOf,匹配结束使用 IndexOf,但如果未找到子字符串则不裁切。
'''
- Public Function Between(Str As String, Before As String, After As String, Optional IgnoreCase As Boolean = False) As String
- Dim StartPos As Integer = If(String.IsNullOrEmpty(Before), -1, Str.LastIndexOfF(Before, IgnoreCase))
+ Public Function Between(Str As String, After As String, Before As String, Optional IgnoreCase As Boolean = False) As String
+ Dim StartPos As Integer = If(String.IsNullOrEmpty(After), -1, Str.LastIndexOfF(After, IgnoreCase))
If StartPos >= 0 Then
- StartPos += Before.Length
+ StartPos += After.Length
Else
StartPos = 0
End If
- Dim EndPos As Integer = If(String.IsNullOrEmpty(After), -1, Str.IndexOfF(After, StartPos, IgnoreCase))
+ Dim EndPos As Integer = If(String.IsNullOrEmpty(Before), -1, Str.IndexOfF(Before, StartPos, IgnoreCase))
If EndPos >= 0 Then
Return Str.Substring(StartPos, EndPos - StartPos)
ElseIf StartPos > 0 Then
@@ -1652,7 +1660,10 @@ Re:
''' 为字符串进行 XML 转义。
'''
Public Function EscapeXML(Str As String) As String
- Return Str.Replace("&", "&").Replace("<", "<").Replace(">", ">").Replace("'", "'").Replace("""", """).Replace(vbCrLf, "
")
+ If Str.StartsWithF("{") Then Str = "{}" & Str '#4187
+ Return Str.
+ Replace("&", "&").Replace("<", "<").Replace(">", ">").Replace("'", "'").
+ Replace("""", """).Replace(vbCrLf, "
")
End Function
'正则
@@ -2065,15 +2076,16 @@ NextElement:
''' 在新的工作线程中执行代码。
'''
Public Function RunInNewThread(Action As Action, Name As String, Optional Priority As ThreadPriority = ThreadPriority.Normal) As Thread
- Dim th As New Thread(Sub()
- Try
- Action()
- Catch ex As ThreadInterruptedException
- Log(Name & ":线程已中止")
- Catch ex As Exception
- Log(ex, Name & ":线程执行失败", LogLevel.Feedback)
- End Try
- End Sub) With {.Name = Name, .Priority = Priority}
+ Dim th As New Thread(
+ Sub()
+ Try
+ Action()
+ Catch ex As ThreadInterruptedException
+ Log(Name & ":线程已中止")
+ Catch ex As Exception
+ Log(ex, Name & ":线程执行失败", LogLevel.Feedback)
+ End Try
+ End Sub) With {.Name = Name, .Priority = Priority}
th.Start()
Return th
End Function
@@ -2186,7 +2198,9 @@ NextElement:
'''
Public Sub OpenWebsite(Url As String)
Try
- If Not Url.StartsWithF("http", True) Then Throw New Exception(Url & " 不是一个有效的网址,它必须以 http 开头!")
+ If Not Url.StartsWithF("http", True) AndAlso Not Url.StartsWithF("minecraft://", True) Then
+ Throw New Exception(Url & " 不是一个有效的网址,它必须以 http 开头!")
+ End If
Log("[System] 正在打开网页:" & Url)
Process.Start(Url)
Catch ex As Exception
@@ -2211,25 +2225,27 @@ NextElement:
''' 设置剪贴板。将在另一线程运行,且不会抛出异常。
'''
Public Sub ClipboardSet(Text As String, Optional ShowSuccessHint As Boolean = True)
- RunInThread(Sub()
- Dim RetryCount As Integer = 0
+ RunInThread(
+ Sub()
+ Dim RetryCount As Integer = 0
Retry:
- Try
- RunInUi(Sub()
- My.Computer.Clipboard.Clear()
- My.Computer.Clipboard.SetText(Text)
- End Sub)
- Catch ex As Exception
- RetryCount += 1
- If RetryCount <= 5 Then
- Thread.Sleep(20)
- GoTo Retry
- Else
- Log(ex, "可能由于剪贴板被其他程序占用,文本复制失败", LogLevel.Hint)
- End If
- End Try
- If ShowSuccessHint Then Hint("已成功复制!", HintType.Finish)
- End Sub)
+ Try
+ RunInUi(
+ Sub()
+ My.Computer.Clipboard.Clear()
+ My.Computer.Clipboard.SetText(Text)
+ End Sub)
+ Catch ex As Exception
+ RetryCount += 1
+ If RetryCount <= 5 Then
+ Thread.Sleep(20)
+ GoTo Retry
+ Else
+ Log(ex, "可能由于剪贴板被其他程序占用,文本复制失败", LogLevel.Hint)
+ End If
+ End Try
+ If ShowSuccessHint Then Hint("已成功复制!", HintType.Finish)
+ End Sub)
End Sub
'''
@@ -2448,39 +2464,40 @@ Retry:
Private LogList As New StringBuilder
Private LogWritter As StreamWriter
Public Sub LogStart()
- RunInNewThread(Sub()
- Dim IsInitSuccess As Boolean = True
- Try
- For i = 4 To 1 Step -1
- If File.Exists(Path & "PCL\Log" & i & ".txt") Then
- If File.Exists(Path & "PCL\Log" & (i + 1) & ".txt") Then File.Delete(Path & "PCL\Log" & (i + 1) & ".txt")
- CopyFile(Path & "PCL\Log" & i & ".txt", Path & "PCL\Log" & (i + 1) & ".txt")
- End If
- Next
- File.Create(Path & "PCL\Log1.txt").Dispose()
- Catch ex As IOException
- IsInitSuccess = False
- Hint("可能同时开启了多个 PCL,程序可能会出现未知问题!", HintType.Critical)
- Log(ex, "日志初始化失败(疑似文件占用问题)")
- Catch ex As Exception
- IsInitSuccess = False
- Log(ex, "日志初始化失败", LogLevel.Hint)
- End Try
- Try
- LogWritter = New StreamWriter(Path & "PCL\Log1.txt", True) With {.AutoFlush = True}
- Catch ex As Exception
- LogWritter = Nothing
- Log(ex, "日志写入失败", LogLevel.Hint)
- End Try
- While True
- If IsInitSuccess Then
- LogFlush()
- Else
- LogList = New StringBuilder '清空 LogList 避免内存爆炸
- End If
- Thread.Sleep(50)
- End While
- End Sub, "Log Writer", ThreadPriority.Lowest)
+ RunInNewThread(
+ Sub()
+ Dim IsInitSuccess As Boolean = True
+ Try
+ For i = 4 To 1 Step -1
+ If File.Exists(Path & "PCL\Log" & i & ".txt") Then
+ If File.Exists(Path & "PCL\Log" & (i + 1) & ".txt") Then File.Delete(Path & "PCL\Log" & (i + 1) & ".txt")
+ CopyFile(Path & "PCL\Log" & i & ".txt", Path & "PCL\Log" & (i + 1) & ".txt")
+ End If
+ Next
+ File.Create(Path & "PCL\Log1.txt").Dispose()
+ Catch ex As IOException
+ IsInitSuccess = False
+ Hint("可能同时开启了多个 PCL,程序可能会出现未知问题!", HintType.Critical)
+ Log(ex, "日志初始化失败(疑似文件占用问题)")
+ Catch ex As Exception
+ IsInitSuccess = False
+ Log(ex, "日志初始化失败", LogLevel.Hint)
+ End Try
+ Try
+ LogWritter = New StreamWriter(Path & "PCL\Log1.txt", True) With {.AutoFlush = True}
+ Catch ex As Exception
+ LogWritter = Nothing
+ Log(ex, "日志写入失败", LogLevel.Hint)
+ End Try
+ While True
+ If IsInitSuccess Then
+ LogFlush()
+ Else
+ LogList = New StringBuilder '清空 LogList 避免内存爆炸
+ End If
+ Thread.Sleep(50)
+ End While
+ End Sub, "Log Writer", ThreadPriority.Lowest)
End Sub
Private ReadOnly LogFlushLock As New Object '防止外部调用 LogFlush 时同时输出多次日志
Public Sub LogFlush()
@@ -2659,7 +2676,7 @@ Retry:
Public Sub FeedbackInfo()
On Error Resume Next
Log("[System] 诊断信息:" & vbCrLf &
- "操作系统:" & My.Computer.Info.OSFullName & vbCrLf &
+ "操作系统:" & My.Computer.Info.OSFullName & "(32 位:" & Is32BitSystem & ")" & vbCrLf &
"剩余内存:" & Int(My.Computer.Info.AvailablePhysicalMemory / 1024 / 1024) & " M / " & Int(My.Computer.Info.TotalPhysicalMemory / 1024 / 1024) & " M" & vbCrLf &
"DPI:" & DPI & "(" & Math.Round(DPI / 96, 2) * 100 & "%)" & vbCrLf &
"MC 文件夹:" & If(PathMcFolder, "Nothing") & vbCrLf &
diff --git a/Plain Craft Launcher 2/Modules/Base/ModLoader.vb b/Plain Craft Launcher 2/Modules/Base/ModLoader.vb
index 18ed602..05596a2 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModLoader.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModLoader.vb
@@ -566,38 +566,33 @@ Restart:
End Class
'任务栏进度条
- Public LoaderTaskbarLock As New Object
- Public LoaderTaskbar As New List(Of LoaderBase)
+ Public LoaderTaskbar As New Concurrent.ConcurrentBag(Of LoaderBase)
Public LoaderTaskbarProgress As Double = 0 '平滑后的进度
Private LoaderTaskbarProgressLast As Shell.TaskbarItemProgressState = Shell.TaskbarItemProgressState.None
Public Sub LoaderTaskbarAdd(Of T)(Loader As LoaderCombo(Of T))
If FrmSpeedLeft IsNot Nothing Then FrmSpeedLeft.TaskRemove(Loader)
- SyncLock LoaderTaskbarLock
- LoaderTaskbar.Add(Loader)
- Log($"[Taskbar] {Loader.Name} 已加入任务列表")
- End SyncLock
+ LoaderTaskbar.Add(Loader)
+ Log($"[Taskbar] {Loader.Name} 已加入任务列表")
End Sub
Public Sub LoaderTaskbarProgressRefresh()
Try
Dim NewState As Shell.TaskbarItemProgressState
Dim NewProgress As Double = LoaderTaskbarProgressGet()
'检查任务是否完成,若完成则移除
- SyncLock LoaderTaskbarLock
- '外显任务是否已经全部完成
- Dim IsAllDownloadTaskCompleted As Boolean = True
- For Each Loader In LoaderTaskbar
- If Loader.State = LoadState.Loading Then IsAllDownloadTaskCompleted = False
- Next
- '若单个任务已中止或全部任务已完成,则刷新并移除
- For Each Task In LoaderTaskbar.ToList()
- If IsAllDownloadTaskCompleted OrElse Task.State = LoadState.Aborted OrElse Task.State = LoadState.Waiting Then
- If FrmSpeedLeft IsNot Nothing Then FrmSpeedLeft.TaskRefresh(Task)
- LoaderTaskbar.Remove(Task)
- Log($"[Taskbar] {Task.Name} 已移出任务列表")
- End If
- Next
- End SyncLock
+ '外显任务是否已经全部完成
+ Dim IsAllDownloadTaskCompleted As Boolean = True
+ For Each Loader In LoaderTaskbar
+ If Loader.State = LoadState.Loading Then IsAllDownloadTaskCompleted = False
+ Next
+ '若单个任务已中止或全部任务已完成,则刷新并移除
+ For Each Task In LoaderTaskbar.ToList()
+ If IsAllDownloadTaskCompleted OrElse Task.State = LoadState.Aborted OrElse Task.State = LoadState.Waiting Then
+ If FrmSpeedLeft IsNot Nothing Then FrmSpeedLeft.TaskRefresh(Task)
+ LoaderTaskbar.TryTake(Task)
+ Log($"[Taskbar] {Task.Name} 已移出任务列表")
+ End If
+ Next
'更新平滑后的进度
If NewProgress <= 0 OrElse NewProgress >= 1 OrElse LoaderTaskbarProgress > NewProgress Then
LoaderTaskbarProgress = NewProgress
@@ -625,15 +620,8 @@ Restart:
End Sub
Public Function LoaderTaskbarProgressGet() As Double
Try
- Dim Total As Double = 0, Count As Integer = 0
- SyncLock LoaderTaskbarLock
- For Each Task In LoaderTaskbar.ToList
- Total += Task.Progress
- Count += 1 '避免多线程影响导致计数出错
- Next
- End SyncLock
- If Count = 0 Then Return 1
- Return MathClamp(Total / Count, 0, 1)
+ If Not LoaderTaskbar.Any Then Return 1
+ Return MathClamp(LoaderTaskbar.Select(Function(e) e.Progress).Average(), 0, 1)
Catch ex As Exception
Log(ex, "获取任务栏进度出错", LogLevel.Feedback)
Return 0.5
diff --git a/Plain Craft Launcher 2/Modules/Base/ModNet.vb b/Plain Craft Launcher 2/Modules/Base/ModNet.vb
index de97191..e93c699 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModNet.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModNet.vb
@@ -1,5 +1,4 @@
Imports System.Net
-Imports PCL.ModNet
Public Module ModNet
Public Const NetDownloadEnd As String = ".PCLDownloading"
@@ -207,10 +206,10 @@ RequestFinished:
Catch ex As ThreadInterruptedException
Throw
Catch ex As Exception
- If ex.GetType.Equals(GetType(WebException)) AndAlso CType(ex, WebException).Status = WebExceptionStatus.Timeout Then
- Throw New TimeoutException("连接服务器超时,已接收 " & Result.Count & " B(" & Url & ")")
+ If TypeOf ex Is WebException AndAlso CType(ex, WebException).Status = WebExceptionStatus.Timeout Then
+ Throw New TimeoutException($"获取结果失败({CType(ex, WebException).Status},{ex.Message},{Url})", ex)
Else
- Throw New WebException("获取结果失败," & ex.Message & "(" & Url & ")", ex)
+ Throw New WebException($"获取结果失败({If(TypeOf ex Is WebException, CType(ex, WebException).Status & ",", "")}{ex.Message},{Url})", ex)
End If
Finally
Request.Abort()
@@ -341,14 +340,15 @@ Retry:
Dim RequestEx As Exception = Nothing
Dim FailCount As Integer = 0
For i = 1 To RequestCount
- Dim th As New Thread(Sub()
- Try
- RequestResult = NetRequestOnce(Url, Method, Data, ContentType, 30000, Headers)
- Catch ex As Exception
- FailCount += 1
- RequestEx = ex
- End Try
- End Sub)
+ Dim th As New Thread(
+ Sub()
+ Try
+ RequestResult = NetRequestOnce(Url, Method, Data, ContentType, 30000, Headers)
+ Catch ex As Exception
+ FailCount += 1
+ RequestEx = ex
+ End Try
+ End Sub)
th.Start()
Threads.Add(th)
Thread.Sleep(i * 250)
@@ -382,7 +382,7 @@ RequestFinished:
Dim Resp As WebResponse = Nothing
Dim Req As HttpWebRequest
Try
- Req = WebRequest.Create(New Uri(Url))
+ Req = WebRequest.Create(Url)
Req.Method = Method
Dim SendData As Byte()
If TypeOf Data Is Byte() Then
@@ -418,7 +418,7 @@ RequestFinished:
Throw
Catch ex As WebException
If ex.Status = WebExceptionStatus.Timeout Then
- Throw New WebException("连接服务器超时,请检查你的网络环境是否良好(" & Url & ")", ex)
+ ex = New WebException($"连接服务器超时,请检查你的网络环境是否良好({ex.Message},{Url})", ex)
Else
'获取请求失败的返回
Dim Res As String = ""
@@ -432,10 +432,14 @@ RequestFinished:
End Using
Catch
End Try
- Throw New WebException("网络请求失败(" & Url & "," & ex.Message & ")" & If(String.IsNullOrEmpty(Res), "", vbCrLf & Res), ex)
+ ex = New WebException($"网络请求失败({ex.Status},{ex.Message},{Url}){If(String.IsNullOrEmpty(Res), "", vbCrLf & Res)}", ex)
End If
+ If MakeLog Then Log(ex, "NetRequestOnce 失败", LogLevel.Developer)
+ Throw ex
Catch ex As Exception
- Throw New WebException("网络请求失败(" & Url & ")", ex)
+ ex = New WebException("网络请求失败(" & Url & ")", ex)
+ If MakeLog Then Log(ex, "NetRequestOnce 失败", LogLevel.Developer)
+ Throw ex
Finally
If DataStream IsNot Nothing Then DataStream.Dispose()
If Resp IsNot Nothing Then Resp.Dispose()
@@ -687,7 +691,7 @@ RequestFinished:
'''
''' 所属的文件列表任务。
'''
- Public Tasks As New List(Of LoaderDownload)
+ Public Tasks As New Concurrent.ConcurrentBag(Of LoaderDownload)
'''
''' 所有下载源。
@@ -880,7 +884,6 @@ RequestFinished:
Public ReadOnly LockState As New Object
Public ReadOnly LockChain As New Object
Public ReadOnly LockSource As New Object
- Public ReadOnly LockTasks As New Object
Public ReadOnly Uuid As Integer = GetUuid()
Public Overrides Function Equals(obj As Object) As Boolean
@@ -963,7 +966,7 @@ Capture:
Next
'是否禁用多线程,以及规定碎片大小
Dim TargetUrl As String = GetSource().Url
- If TargetUrl.Contains("pcl2-server") OrElse TargetUrl.Contains("gitcode.net") OrElse TargetUrl.Contains("github.com") OrElse TargetUrl.Contains("modrinth.com") Then Return Nothing
+ If TargetUrl.Contains("pcl2-server") OrElse TargetUrl.Contains("gitcode.net") OrElse TargetUrl.Contains("github.com") OrElse TargetUrl.Contains("modrinth") Then Return Nothing
'寻找最大碎片
'FUTURE: 下载引擎重做,计算下载源平均链接时间和线程下载速度,按最高时间节省来开启多线程
Dim FilePieceMax As NetThread = Threads
@@ -979,10 +982,8 @@ StartThread:
If (StartPosition > FileSize AndAlso FileSize >= 0 AndAlso Not IsUnknownSize) OrElse StartPosition < 0 OrElse IsNothing(StartSource) Then Return Nothing
'构建线程
Dim ThreadUuid As Integer = GetUuid()
- SyncLock LockTasks
- If Not Tasks.Any() Then Return Nothing '由于中断,已没有可用任务
- Th = New Thread(AddressOf Thread) With {.Name = $"NetTask {Tasks(0).Uuid}/{Uuid} Download {ThreadUuid}#", .Priority = ThreadPriority.BelowNormal}
- End SyncLock
+ If Not Tasks.Any() Then Return Nothing '由于中断,已没有可用任务
+ Th = New Thread(AddressOf Thread) With {.Name = $"NetTask {Tasks(0).Uuid}/{Uuid} Download {ThreadUuid}#", .Priority = ThreadPriority.BelowNormal}
ThreadInfo = New NetThread With {.Uuid = ThreadUuid, .DownloadStart = StartPosition, .Thread = Th, .Source = StartSource, .Task = Me, .State = NetState.WaitForDownload}
'链表处理
If ThreadInfo.IsFirstThread OrElse Threads Is Nothing Then
@@ -1139,11 +1140,9 @@ NotSupportRange:
End If
SyncLock LockCount
Info.Source.FailCount = 0
- SyncLock LockTasks
- For Each Task In Tasks
- Task.FailCount = 0
- Next
- End SyncLock
+ For Each Task In Tasks
+ Task.FailCount = 0
+ Next
End SyncLock
NetManager.DownloadDone += RealDataCount
SyncLock LockDone
@@ -1197,11 +1196,9 @@ SourceBreak:
'状态变更
SyncLock LockCount
Info.Source.FailCount += 1
- SyncLock LockTasks
- For Each Task In Tasks
- Task.FailCount += 1
- Next
- End SyncLock
+ For Each Task In Tasks
+ Task.FailCount += 1
+ Next
End SyncLock
Dim IsTimeoutString As String = GetExceptionSummary(ex).ToLower.Replace(" ", "")
Dim IsTimeout As Boolean = IsTimeoutString.Contains("由于连接方在一段时间后没有正确答复或连接的主机没有反应") OrElse
@@ -1306,7 +1303,7 @@ Retry:
'合并文件
If IsNoSplit Then
'仅有一个线程,从缓存中输出
- If ModeDebug Then Log($"[Download] {LocalName}:下载结束,从缓存输出文件")
+ If ModeDebug Then Log($"[Download] {LocalName}:下载结束,从缓存输出文件,长度:" & SmailFileCache.Count)
MergeFile = New FileStream(LocalPath, FileMode.Create)
AddWriter = New BinaryWriter(MergeFile)
AddWriter.Write(SmailFileCache.ToArray)
@@ -1343,7 +1340,7 @@ Retry:
'检查文件
Dim CheckResult As String = Check?.Check(LocalPath)
If CheckResult IsNot Nothing Then
- Log($"[Download] {LocalName} 合并文件失败,下载线程细节:")
+ Log($"[Download] {LocalName} 文件校验失败,下载线程细节:")
For Each Th As NetThread In Threads
Log($"[Download] {Th.Uuid}#,状态 {GetStringFromEnum(Th.State)},范围 {Th.DownloadStart}~{Th.DownloadStart + Th.DownloadDone},完成 {Th.DownloadDone},剩余 {Th.DownloadUndone}")
Next
@@ -1396,10 +1393,8 @@ Retry:
'''
Public Sub Abort(CausedByTask As LoaderDownload)
'从特定任务中移除,如果它还属于其他任务,则继续下载
- SyncLock LockTasks
- Tasks.Remove(CausedByTask)
- If Tasks.Any Then Exit Sub
- End SyncLock
+ Tasks.TryTake(CausedByTask)
+ If Tasks.Any Then Exit Sub
'确认中断
SyncLock LockState
If State >= NetState.Finish Then Exit Sub
@@ -1429,11 +1424,9 @@ Retry:
NetManager.FileRemain -= 1
If PrintLog Then Log("[Download] " & LocalName & ":已完成,剩余文件 " & NetManager.FileRemain)
End SyncLock
- SyncLock LockTasks
- For Each Task In Tasks
- Task.OnFileFinish(Me)
- Next
- End SyncLock
+ For Each Task In Tasks
+ Task.OnFileFinish(Me)
+ Next
End Sub
End Class
@@ -1859,15 +1852,10 @@ Retry:
Try
While True
Thread.Sleep(20)
- '若已完成,则清空
- If Id = 0 AndAlso FileRemain = 0 AndAlso Files.Any() Then
- SyncLock LockFiles
- Files.Clear()
- End SyncLock
- End If
'获取文件列表
Dim AllFiles As List(Of NetFile)
SyncLock LockFiles
+ If Id = 0 AndAlso FileRemain = 0 AndAlso Files.Any() Then Files.Clear() '若已完成,则清空
AllFiles = Files.Values.ToList()
End SyncLock
Dim WaitingFiles As New List(Of NetFile)
@@ -1965,9 +1953,7 @@ Retry:
If Files(File.LocalPath).State >= NetState.Finish Then
'该文件已经下载过一次,且下载完成
'将已下载的文件替换成当前文件,重新下载
- SyncLock File.LockTasks
- File.Tasks.Add(Task)
- End SyncLock
+ File.Tasks.Add(Task)
Files(File.LocalPath) = File
SyncLock LockRemain
FileRemain += 1
@@ -1978,15 +1964,11 @@ Retry:
'该文件正在下载中
'将当前文件替换成下载中的文件,即两个任务指向同一个文件
File = Files(File.LocalPath)
- SyncLock File.LockTasks
- File.Tasks.Add(Task)
- End SyncLock
+ File.Tasks.Add(Task)
End If
Else
'没有该文件
- SyncLock File.LockTasks
- File.Tasks.Add(Task)
- End SyncLock
+ File.Tasks.Add(Task)
Files.Add(File.LocalPath, File)
SyncLock LockRemain
FileRemain += 1
@@ -2008,14 +1990,12 @@ Retry:
''' 是否有正在进行中、需要在下载管理页面显示的下载任务?
'''
Public Function HasDownloadingTask(Optional IgnoreCustomDownload As Boolean = False) As Boolean
- SyncLock LoaderTaskbarLock
- For Each Task In LoaderTaskbar
- If (Task.Show AndAlso Task.State = LoadState.Loading) AndAlso
- (Not IgnoreCustomDownload OrElse Not Task.Name.ToString.Contains("自定义下载")) Then
- Return True
- End If
- Next
- End SyncLock
+ For Each Task In LoaderTaskbar
+ If (Task.Show AndAlso Task.State = LoadState.Loading) AndAlso
+ (Not IgnoreCustomDownload OrElse Not Task.Name.ToString.Contains("自定义下载")) Then
+ Return True
+ End If
+ Next
Return False
End Function
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb
index 39dbf53..a893e44 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb
@@ -278,7 +278,8 @@
End If
'Tags
Tags = New List(Of String)
- For Each Category In Data("categories").Select(Of Integer)(Function(t) t("id")).Distinct.OrderByDescending(Function(c) c)
+ For Each Category In If(Data("categories"), New JArray). '镜像源 API 可能丢失此字段:https://github.com/Hex-Dragon/PCL2/issues/4267#issuecomment-2254590831
+ Select(Of Integer)(Function(t) t("id")).Distinct.OrderByDescending(Function(c) c)
Select Case Category
'Mod
Case 406 : Tags.Add("世界元素")
@@ -355,12 +356,12 @@
ModLoaders = New List(Of CompModLoaderType)
For Each Category In Data("categories").Select(Function(t) t.ToString)
Select Case Category
- '加载器
+ '加载器
Case "forge" : ModLoaders.Add(CompModLoaderType.Forge)
Case "fabric" : ModLoaders.Add(CompModLoaderType.Fabric)
Case "quilt" : ModLoaders.Add(CompModLoaderType.Quilt)
Case "neoforge" : ModLoaders.Add(CompModLoaderType.NeoForge)
- 'Mod
+ 'Mod
Case "worldgen" : Tags.Add("世界元素")
Case "technology" : Tags.Add("科技")
Case "food" : Tags.Add("食物/烹饪")
@@ -376,7 +377,7 @@
Case "social" : Tags.Add("服务器")
Case "utility" : Tags.Add("改良")
Case "library" : Tags.Add("支持库")
- '整合包
+ '整合包
Case "multiplayer" : Tags.Add("多人")
Case "optimization" : Tags.Add("性能优化")
Case "challenging" : Tags.Add("硬核")
@@ -385,7 +386,7 @@
Case "technology" : Tags.Add("科技")
Case "magic" : Tags.Add("魔法")
Case "adventure" : Tags.Add("冒险")
- Case "kitchen-sink" : Tags.Add("烹饪")
+ Case "kitchen-sink" : Tags.Add("大杂烩")
Case "lightweight" : Tags.Add("轻量")
'FUTURE: Res
End Select
@@ -629,19 +630,19 @@ NoSubtitle:
If Id = Project.Id Then Return True '相同实例
'提取字符串中的字母和数字
Dim GetRaw =
- Function(Data As String) As String
- Dim Result As New StringBuilder()
- For Each r As Char In Data.Where(Function(c) Char.IsLetterOrDigit(c))
- Result.Append(r)
- Next
- Return Result.ToString.ToLower
- End Function
+ Function(Data As String) As String
+ Dim Result As New StringBuilder()
+ For Each r As Char In Data.Where(Function(c) Char.IsLetterOrDigit(c))
+ Result.Append(r)
+ Next
+ Return Result.ToString.ToLower
+ End Function
'来自不同的网站
If FromCurseForge = Project.FromCurseForge Then Return False
'Mod 加载器一致
- If ModLoaders.Count <> Project.ModLoaders.Count OrElse ModLoaders.Except(Project.ModLoaders).Count > 0 Then Return False
+ If ModLoaders.Count <> Project.ModLoaders.Count OrElse ModLoaders.Except(Project.ModLoaders).Any() Then Return False
'MC 版本一致
- If GameVersions.Count <> Project.GameVersions.Count OrElse GameVersions.Except(Project.GameVersions).Count > 0 Then Return False
+ If GameVersions.Count <> Project.GameVersions.Count OrElse GameVersions.Except(Project.GameVersions).Any() Then Return False
'MCMOD 翻译名 / 原名 / 描述文本 / Slug 的英文部分相同
If TranslatedName = Project.TranslatedName OrElse
RawName = Project.RawName OrElse Description = Project.Description OrElse
@@ -947,7 +948,7 @@ Retry:
Try
'获取工程列表
Log("[Comp] 开始从 CurseForge 获取工程列表:" & CurseForgeUrl)
- Dim RequestResult As JObject = NetGetCodeByRequestRetry(CurseForgeUrl, IsJson:=True, Encode:=Encoding.UTF8)
+ Dim RequestResult As JObject = DlModRequest(CurseForgeUrl, IsJson:=True)
Task.Progress += 0.2
Dim ProjectList As New List(Of CompProject)
For Each JsonEntry As JObject In RequestResult("data")
@@ -962,7 +963,7 @@ Retry:
Log($"[Comp] 从 CurseForge 获取到了 {ProjectList.Count} 个工程(已获取 {Storage.CurseForgeOffset} 个,共 {Storage.CurseForgeTotal} 个)")
Catch ex As Exception
Log(ex, "从 CurseForge 获取工程列表失败")
- Storage.CurseForgeTotal = Storage.CurseForgeOffset
+ Storage.CurseForgeTotal = -1 'Storage.CurseForgeOffset
[Error] = ex
CurseForgeFailed = True
End Try
@@ -977,7 +978,7 @@ Retry:
Sub()
Try
Log("[Comp] 开始从 Modrinth 获取工程列表:" & ModrinthUrl)
- Dim RequestResult As JObject = NetGetCodeByRequestRetry(ModrinthUrl, IsJson:=True, Encode:=Encoding.UTF8)
+ Dim RequestResult As JObject = DlModRequest(ModrinthUrl, IsJson:=True)
Task.Progress += 0.2
Dim ProjectList As New List(Of CompProject)
For Each JsonEntry As JObject In RequestResult("hits")
@@ -995,7 +996,7 @@ Retry:
Log($"[Comp] 从 Modrinth 获取到了 {ProjectList.Count} 个工程(已获取 {Storage.ModrinthOffset} 个,共 {Storage.ModrinthTotal} 个)")
Catch ex As Exception
Log(ex, "从 Modrinth 获取工程列表失败")
- Storage.ModrinthTotal = Storage.ModrinthOffset
+ Storage.ModrinthTotal = -1 'Storage.ModrinthOffset
[Error] = ex
ModrinthFailed = True
End Try
@@ -1021,7 +1022,7 @@ Retry:
ElseIf Task.Input.Source = CompSourceType.Modrinth AndAlso Task.Input.Tag.EndsWithF("/") Then
Throw New Exception("Modrinth 不兼容所选的类型")
Else
- Throw New Exception("没有符合条件的结果")
+ Throw New Exception("没有搜索结果")
End If
End If
ElseIf [Error] IsNot Nothing Then
@@ -1253,7 +1254,9 @@ Retry:
DownloadUrls = (New List(Of String) From {Url.Replace("-service.overwolf.wtf", ".forgecdn.net").Replace("://edge", "://media"),
Url.Replace("-service.overwolf.wtf", ".forgecdn.net"),
Url.Replace("://edge", "://media"),
- Url}).Distinct().ToList()
+ Url}).Distinct.ToList '对脑残 CurseForge 的下载地址进行多种修正
+ DownloadUrls.AddRange(DownloadUrls.Select(Function(u) DlSourceModGet(u)).ToList) '添加镜像源,这个写法是为了让镜像源排在后面
+ DownloadUrls = DownloadUrls.Distinct.ToList '最终去重
'Dependencies
If Type = CompType.Mod Then
RawDependencies = Data("dependencies").
@@ -1287,11 +1290,10 @@ Retry:
ReleaseDate = Data("date_published")
Status = If(Data("version_type").ToString = "release", CompFileStatus.Release, If(Data("version_type").ToString = "beta", CompFileStatus.Beta, CompFileStatus.Alpha))
DownloadCount = Data("downloads")
- '可能为空
- If CType(Data("files"), JArray).Any() Then
+ If CType(Data("files"), JArray).Any() Then '可能为空
Dim File As JToken = Data("files")(0)
FileName = File("filename")
- DownloadUrls = New List(Of String) From {File("url")}
+ DownloadUrls = New List(Of String) From {File("url"), DlSourceModGet(File("url"))}.Distinct.ToList '同时添加了镜像源
Hash = File("hashes")("sha1")
End If
'Dependencies
@@ -1320,6 +1322,7 @@ Retry:
Dim RawLoaders As List(Of String) = Data("loaders").Select(Function(v) v.ToString).ToList
ModLoaders = New List(Of CompModLoaderType)
If RawLoaders.Contains("forge") Then ModLoaders.Add(CompModLoaderType.Forge)
+ If RawLoaders.Contains("neoforge") Then ModLoaders.Add(CompModLoaderType.NeoForge)
If RawLoaders.Contains("fabric") Then ModLoaders.Add(CompModLoaderType.Fabric)
If RawLoaders.Contains("quilt") Then ModLoaders.Add(CompModLoaderType.Quilt)
#End Region
@@ -1426,9 +1429,9 @@ Retry:
If CompProjectCache.ContainsKey(ProjectId) Then '存在缓存
TargetProject = CompProjectCache(ProjectId)
ElseIf FromCurseForge Then 'CurseForge
- TargetProject = New CompProject(NetGetCodeByRequestRetry("https://api.curseforge.com/v1/mods/" & ProjectId, IsJson:=True, Encode:=Encoding.UTF8)("data"))
+ TargetProject = New CompProject(DlModRequest("https://api.curseforge.com/v1/mods/" & ProjectId, IsJson:=True)("data"))
Else 'Modrinth
- TargetProject = New CompProject(NetGetCodeByRequestRetry("https://api.modrinth.com/v2/project/" & ProjectId, IsJson:=True, Encode:=Encoding.UTF8))
+ TargetProject = New CompProject(DlModRequest("https://api.modrinth.com/v2/project/" & ProjectId, IsJson:=True))
End If
'获取工程对象的文件列表
Log("[Comp] 开始获取文件列表:" & ProjectId)
@@ -1436,13 +1439,13 @@ Retry:
If FromCurseForge Then
'CurseForge
If TargetProject.Type = CompType.Mod Then 'Mod 使用每个版本最新的文件
- ResultJsonArray = GetJson(NetRequestRetry("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(TargetProject.CurseForgeFileIds, ",") & "]}", "application/json"))("data")
+ ResultJsonArray = GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(TargetProject.CurseForgeFileIds, ",") & "]}", "application/json"))("data")
Else '否则使用全部文件
- ResultJsonArray = NetGetCodeByRequestRetry($"https://api.curseforge.com/v1/mods/{ProjectId}/files?pageSize=999", Accept:="application/json", IsJson:=True)("data")
+ ResultJsonArray = DlModRequest($"https://api.curseforge.com/v1/mods/{ProjectId}/files?pageSize=999", IsJson:=True)("data")
End If
Else
'Modrinth
- ResultJsonArray = NetGetCodeByRequestRetry($"https://api.modrinth.com/v2/project/{ProjectId}/version", Accept:="application/json", IsJson:=True)
+ ResultJsonArray = DlModRequest($"https://api.modrinth.com/v2/project/{ProjectId}/version", IsJson:=True)
End If
CompFilesCache(ProjectId) = ResultJsonArray.Select(Function(a) New CompFile(a, TargetProject.Type)).
Where(Function(a) a.Available).ToList.Distinct(Function(a, b) a.Id = b.Id) 'CurseForge 可能会重复返回相同项(#1330)
@@ -1456,11 +1459,10 @@ Retry:
Log($"[Comp] {ProjectId} 文件列表中还需要获取信息的前置 Mod:{Join(UndoneDeps, ",")}")
Dim Projects As JArray
If TargetProject.FromCurseForge Then
- Projects = GetJson(NetRequestRetry("https://api.curseforge.com/v1/mods",
+ Projects = GetJson(DlModRequest("https://api.curseforge.com/v1/mods",
"POST", "{""modIds"": [" & Join(UndoneDeps, ",") & "]}", "application/json"))("data")
Else
- Projects = NetGetCodeByRequestRetry($"https://api.modrinth.com/v2/projects?ids=[""{Join(UndoneDeps, """,""")}""]",
- Accept:="application/json", IsJson:=True)
+ Projects = DlModRequest($"https://api.modrinth.com/v2/projects?ids=[""{Join(UndoneDeps, """,""")}""]", IsJson:=True)
End If
For Each Project In Projects
Dim NewProject As New CompProject(Project) '在 New 的时候就添加了缓存
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb
index ef52547..0228a49 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb
@@ -697,8 +697,8 @@ NextStack:
"forge", "setup", "block", "model", "mixin", "event", "unimi", "netty", "world",
"gitlab", "common", "server", "config", "loader", "launch", "entity", "assist", "client", "plugin", "modapi", "mojang", "shader", "events", "github", "recipe", "render", "packet", "events",
"preinit", "preload", "machine", "reflect", "channel", "general", "handler", "content", "systems", "modules", "service",
- "fastutil", "optifine", "internal", "platform", "override", "fabricmc",
- "injection", "listeners", "scheduler", "minecraft", "transformer", "transformers", "universal", "multipart", "minecraftforge", "blockentity", "spongepowered", "electronwill"
+ "fastutil", "optifine", "internal", "platform", "override", "fabricmc", "neoforge",
+ "injection", "listeners", "scheduler", "minecraft", "transformer", "transformers", "neoforged", "universal", "multipart", "minecraftforge", "blockentity", "spongepowered", "electronwill"
}.Contains(Word.ToLower) Then Continue For
PossibleWords.Add(Word.Trim)
Next
@@ -881,7 +881,10 @@ NextStack:
FileName = "游戏崩溃前的输出.txt"
End Select
If File.Exists(OutputFile) Then
- WriteFile(TempFolder & "Report\" & FileName, SecretFilter(ReadFile(OutputFile), If(FileName = "启动脚本.bat", "F", "*")))
+ Dim FileEncoding As Encoding = GetEncoding(OutputFile)
+ WriteFile(TempFolder & "Report\" & FileName,
+ SecretFilter(ReadFile(OutputFile, FileEncoding), If(FileName = "启动脚本.bat", "F", "*")),
+ Encoding:=FileEncoding)
End If
Next
'导出报告
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
index 10cfdbb..867b417 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
@@ -8,9 +8,13 @@
'''
Public Function DlClientJarGet(Version As McVersion, ReturnNothingOnFileUseable As Boolean) As NetFile
'获取底层继承版本
- Do While Not String.IsNullOrEmpty(Version.InheritVersion)
- Version = New McVersion(Version.InheritVersion)
- Loop
+ Try
+ Do While Not String.IsNullOrEmpty(Version.InheritVersion)
+ Version = New McVersion(Version.InheritVersion)
+ Loop
+ Catch ex As Exception
+ Log(ex, "获取底层继承版本失败")
+ End Try
'检查 Json 是否标准
If Version.JsonObject("downloads") Is Nothing OrElse Version.JsonObject("downloads")("client") Is Nothing OrElse Version.JsonObject("downloads")("client")("url") Is Nothing Then
Throw New Exception("底层版本 " & Version.Name & " 中无 jar 文件下载信息")
@@ -220,7 +224,7 @@
End If
Setup.Set("ToolUpdateSnapshotLast", If(Version, "Nothing"))
Catch ex As Exception
- Throw New Exception("版本列表解析失败", ex)
+ Throw New Exception("Minecraft 官方源版本列表解析失败", ex)
End Try
End Sub
'''
@@ -237,7 +241,7 @@
'返回
Loader.Output = New DlClientListResult With {.IsOfficial = False, .SourceName = "BMCLAPI", .Value = Json}
Catch ex As Exception
- Throw New Exception("版本列表解析失败(" & Json.ToString & ")", ex)
+ Throw New Exception("Minecraft BMCLAPI 版本列表解析失败(" & Json.ToString & ")", ex)
End Try
End Sub
@@ -288,6 +292,7 @@
'''
Public Value As List(Of DlOptiFineListEntry)
End Structure
+
Public Class DlOptiFineListEntry
'''
''' 显示名称,已去除 HD_U 字样,如“1.12.2 C8”。
@@ -359,29 +364,33 @@
Private Sub DlOptiFineListOfficialMain(Loader As LoaderTask(Of Integer, DlOptiFineListResult))
Dim Result As String = NetGetCodeByClient("https://optifine.net/downloads", Encoding.Default)
If Result.Length < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Result & ")")
- '获取所有版本信息
- Dim Forge As List(Of String) = RegexSearch(Result, "(?<=colForge'>)[^<]*")
- Dim ReleaseTime As List(Of String) = RegexSearch(Result, "(?<=colDate'>)[^<]+")
- Dim Name As List(Of String) = RegexSearch(Result, "(?<=OptiFine_)[0-9A-Za-z_.]+(?=.jar"")")
- If Not ReleaseTime.Count = Name.Count Then Throw New Exception("版本与发布时间数据无法对应")
- If Not Forge.Count = Name.Count Then Throw New Exception("版本与 Forge 兼容数据无法对应")
- If ReleaseTime.Count < 10 Then Throw New Exception("获取到的版本数量不足(" & Result & ")")
- '转化为列表输出
- Dim Versions As New List(Of DlOptiFineListEntry)
- For i = 0 To ReleaseTime.Count - 1
- Name(i) = Name(i).Replace("_", " ")
- Dim Entry As New DlOptiFineListEntry With {
- .NameDisplay = Name(i).Replace("HD U ", "").Replace(".0 ", " "),
- .ReleaseTime = Join({ReleaseTime(i).Split(".")(2), ReleaseTime(i).Split(".")(1), ReleaseTime(i).Split(".")(0)}, "/"),
- .IsPreview = Name(i).ContainsF("pre", True),
- .Inherit = Name(i).ToString.Split(" ")(0),
- .NameFile = If(Name(i).ContainsF("pre", True), "preview_", "") & "OptiFine_" & Name(i).Replace(" ", "_") & ".jar",
- .RequiredForgeVersion = Forge(i).Replace("Forge ", "").Replace("#", "")}
- If Entry.RequiredForgeVersion.Contains("N/A") Then Entry.RequiredForgeVersion = Nothing
- Entry.NameVersion = Entry.Inherit & "-OptiFine_" & Name(i).ToString.Replace(" ", "_").Replace(Entry.Inherit & "_", "")
- Versions.Add(Entry)
- Next
- Loader.Output = New DlOptiFineListResult With {.IsOfficial = True, .SourceName = "OptiFine 官方源", .Value = Versions}
+ Try
+ '获取所有版本信息
+ Dim Forge As List(Of String) = RegexSearch(Result, "(?<=colForge'>)[^<]*")
+ Dim ReleaseTime As List(Of String) = RegexSearch(Result, "(?<=colDate'>)[^<]+")
+ Dim Name As List(Of String) = RegexSearch(Result, "(?<=OptiFine_)[0-9A-Za-z_.]+(?=.jar"")")
+ If Not ReleaseTime.Count = Name.Count Then Throw New Exception("版本与发布时间数据无法对应")
+ If Not Forge.Count = Name.Count Then Throw New Exception("版本与 Forge 兼容数据无法对应")
+ If ReleaseTime.Count < 10 Then Throw New Exception("获取到的版本数量不足(" & Result & ")")
+ '转化为列表输出
+ Dim Versions As New List(Of DlOptiFineListEntry)
+ For i = 0 To ReleaseTime.Count - 1
+ Name(i) = Name(i).Replace("_", " ")
+ Dim Entry As New DlOptiFineListEntry With {
+ .NameDisplay = Name(i).Replace("HD U ", "").Replace(".0 ", " "),
+ .ReleaseTime = Join({ReleaseTime(i).Split(".")(2), ReleaseTime(i).Split(".")(1), ReleaseTime(i).Split(".")(0)}, "/"),
+ .IsPreview = Name(i).ContainsF("pre", True),
+ .Inherit = Name(i).ToString.Split(" ")(0),
+ .NameFile = If(Name(i).ContainsF("pre", True), "preview_", "") & "OptiFine_" & Name(i).Replace(" ", "_") & ".jar",
+ .RequiredForgeVersion = Forge(i).Replace("Forge ", "").Replace("#", "")}
+ If Entry.RequiredForgeVersion.Contains("N/A") Then Entry.RequiredForgeVersion = Nothing
+ Entry.NameVersion = Entry.Inherit & "-OptiFine_" & Name(i).ToString.Replace(" ", "_").Replace(Entry.Inherit & "_", "")
+ Versions.Add(Entry)
+ Next
+ Loader.Output = New DlOptiFineListResult With {.IsOfficial = True, .SourceName = "OptiFine 官方源", .Value = Versions}
+ Catch ex As Exception
+ Throw New Exception("OptiFine 官方源版本列表解析失败(" & Result & ")", ex)
+ End Try
End Sub
'''
@@ -407,7 +416,7 @@
Next
Loader.Output = New DlOptiFineListResult With {.IsOfficial = False, .SourceName = "BMCLAPI", .Value = Versions}
Catch ex As Exception
- Throw New Exception("版本列表解析失败(" & Json.ToString & ")", ex)
+ Throw New Exception("OptiFine BMCLAPI 版本列表解析失败(" & Json.ToString & ")", ex)
End Try
End Sub
@@ -485,15 +494,61 @@
#Region "DlForgeVersion | Forge 版本列表"
- Public Class DlForgeVersionEntry
+ Public MustInherit Class DlForgelikeEntry
+ Public IsNeoForge As Boolean
'''
- ''' 完整的版本名,如 “14.22.1.2478”。
+ ''' 加载器名称。Forge 或 NeoForge。
'''
- Public Version As String
+ Public ReadOnly Property LoaderName As String
+ Get
+ Return If(IsNeoForge, "NeoForge", "Forge")
+ End Get
+ End Property
+ '''
+ ''' 文件扩展名。不以小数点开头。
+ '''
+ Public ReadOnly Property FileExtension As String
+ Get
+ If IsNeoForge Then
+ Return "jar"
+ Else
+ Return If(CType(Me, DlForgeVersionEntry).Category = "installer", "jar", "zip")
+ End If
+ End Get
+ End Property
+ '''
+ ''' Forge:MC 版本是否小于 1.13。
+ ''' NeoForge:MC 版本是否为 1.20.1。
+ '''
+ Public ReadOnly Property IsLegacy As Boolean
+ Get
+ '虽然很抽象,但确实可以这样判断
+ 'Forge:1.13+ 的版本号首位都大于 20
+ 'NeoForge:1.20.1 的版本号首位人为规定为 19 开头
+ Return Version.Major < 20
+ End Get
+ End Property
+ '''
+ ''' 标准化后的版本号,仅可用于比较与排序。
+ ''' 格式:Major.Minor.Build.Revision
+ ''' Forge:如 “50.1.9.0”(最后一位固定为 0)、“14.22.1.2478”(Legacy)。
+ ''' NeoForge:如 “20.4.30.0”(最后一位固定为 0)、“19.47.1.99”(Legacy:第一位固定为 19)。
+ '''
+ Public Version As Version
+ '''
+ ''' 可对玩家显示的非格式化版本名。
+ ''' Forge:如 “50.1.9”、“14.22.1.2478”(Legacy)。
+ ''' NeoForge:如 “20.4.30-beta”、“47.1.99”(Legacy)。
+ '''
+ Public VersionName As String
'''
''' 对应的 Minecraft 版本,如“1.12.2”。
'''
Public Inherit As String
+ End Class
+
+ Public Class DlForgeVersionEntry
+ Inherits DlForgelikeEntry
'''
''' 发布时间,格式为“yyyy/MM/dd HH:mm”。
'''
@@ -511,58 +566,21 @@
'''
Public Category As String
'''
- ''' 版本分支。若无分支则为 Nothing。
- '''
- Public Branch As String = Nothing
- '''
- ''' 是否为新版 Forge。(即为 Minecraft 1.13+)
- '''
- Public ReadOnly Property IsNewType As Boolean
- Get
- Return Version.Split(".")(0) >= 20
- End Get
- End Property
- '''
- ''' 构建数。
- '''
- Public ReadOnly Property Build As Integer
- Get
- Dim Version = Me.Version.Split(".")
- If Version(0) < 15 Then
- Return Version(Version.Count - 1)
- Else
- Return Version(Version.Count - 1) + 10000
- End If
- End Get
- End Property
- '''
''' 用于下载的文件版本名。可能在 Version 的基础上添加了分支。
'''
- Public ReadOnly Property FileVersion As String
- Get
- Return Version & If(Branch Is Nothing, "", "-" & Branch)
- End Get
- End Property
- '''
- ''' 即将下载的文件全名。
- '''
- Public ReadOnly Property FileName As String
- Get
- Return "forge-" & Inherit & "-" & FileVersion & "-" & Category & "." & FileSuffix
- End Get
- End Property
- '''
- ''' 文件扩展名。
- '''
- Public ReadOnly Property FileSuffix As String
- Get
- If Category = "installer" Then
- Return "jar"
- Else
- Return "zip"
- End If
- End Get
- End Property
+ Public FileVersion As String
+
+ Public Sub New(Version As String, Branch As String, Inherit As String)
+ '司马版本的特殊处理
+ If Version = "11.15.1.2318" OrElse Version = "11.15.1.1902" OrElse Version = "11.15.1.1890" Then Branch = "1.8.9"
+ If Branch Is Nothing AndAlso Inherit = "1.7.10" AndAlso Version.Split(".")(3) >= 1300 Then Branch = "1.7.10"
+ '为 DlForgelikeEntry 提供所有信息
+ IsNeoForge = False
+ VersionName = Version
+ Me.Version = New Version(Version)
+ Me.Inherit = Inherit
+ FileVersion = Version & If(Branch Is Nothing, "", "-" & Branch)
+ End Sub
End Class
'''
@@ -596,7 +614,9 @@
Public Sub DlForgeVersionOfficialMain(Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)))
Dim Result As String
Try
- Result = NetGetCodeByDownload("https://files.minecraftforge.net/maven/net/minecraftforge/forge/index_" & Loader.Input & ".html", UseBrowserUserAgent:=True)
+ Result = NetGetCodeByDownload("https://files.minecraftforge.net/maven/net/minecraftforge/forge/index_" &
+ Loader.Input.Replace("-", "_") & '兼容 Forge 1.7.10-pre4,#4057
+ ".html", UseBrowserUserAgent:=True)
Catch ex As Exception
If GetExceptionSummary(ex).Contains("(404)") Then
Throw New Exception("没有可用版本")
@@ -620,8 +640,6 @@
'分支获取
Dim Branch As String = RegexSeek(VersionCode, $"(?<=-{Name}-)[^-""]+(?=-[a-z]+.[a-z]{{3}})")
If String.IsNullOrWhiteSpace(Branch) Then Branch = Nothing
- If Name = "11.15.1.2318" OrElse Name = "11.15.1.1902" OrElse Name = "11.15.1.1890" Then Branch = "1.8.9"
- If Branch Is Nothing AndAlso Inherit = "1.7.10" AndAlso Name.Split(".")(3) >= 1300 Then Branch = "1.7.10"
'发布时间获取
Dim ReleaseTimeOriginal = RegexSeek(VersionCode, "(?<=""download-time"" title="")[^""]+")
Dim ReleaseTimeSplit = ReleaseTimeOriginal.Split(" -:".ToCharArray) '原格式:"2021-02-15 03:24:02"
@@ -651,13 +669,13 @@
Continue For
End If
'添加进列表
- Versions.Add(New DlForgeVersionEntry With {.Category = Category, .Version = Name, .IsRecommended = IsRecommended, .Hash = MD5.Trim(vbCr, vbLf), .Inherit = Inherit, .ReleaseTime = ReleaseTime, .Branch = Branch})
+ Versions.Add(New DlForgeVersionEntry(Name, Branch, Inherit) With {.Category = Category, .IsRecommended = IsRecommended, .Hash = MD5.Trim(vbCr, vbLf), .ReleaseTime = ReleaseTime})
Catch ex As Exception
- Throw New Exception("版本信息提取失败(" & VersionCode & ")", ex)
+ Throw New Exception("Forge 官方源版本信息提取失败(" & VersionCode & ")", ex)
End Try
Next
Catch ex As Exception
- Throw New Exception("版本列表解析失败(" & Result & ")", ex)
+ Throw New Exception("Forge 官方源版本列表解析失败(" & Result & ")", ex)
End Try
If Not Versions.Any() Then Throw New Exception("没有可用版本")
Loader.Output = Versions
@@ -667,7 +685,9 @@
''' Forge 版本列表,BMCLAPI。
'''
Public Sub DlForgeVersionBmclapiMain(Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)))
- Dim Json As JArray = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/forge/minecraft/" & Loader.Input, IsJson:=True)
+ Dim Json As JArray = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/forge/minecraft/" &
+ Loader.Input.Replace("-", "_"), '兼容 Forge 1.7.10-pre4,#4057
+ IsJson:=True)
Dim Versions As New List(Of DlForgeVersionEntry)
Try
Dim Recommended As String = McDownloadForgeRecommendedGet(Loader.Input)
@@ -700,20 +720,17 @@
End Select
Next
'获取 Entry
- Dim Inherit As String = Loader.Input
Dim Branch As String = Token("branch")
Dim Name As String = Token("version")
- If Name = "11.15.1.2318" OrElse Name = "11.15.1.1902" OrElse Name = "11.15.1.1890" Then Branch = "1.8.9"
- If Branch Is Nothing AndAlso Inherit = "1.7.10" AndAlso Name.Split(".")(3) >= 1300 Then Branch = "1.7.10"
'基础信息获取
- Dim Entry = New DlForgeVersionEntry With {.Hash = Hash, .Category = Category, .Version = Name, .Branch = Branch, .Inherit = Inherit, .IsRecommended = Recommended = Name}
+ Dim Entry = New DlForgeVersionEntry(Name, Branch, Loader.Input) With {.Hash = Hash, .Category = Category, .IsRecommended = Recommended = Name}
Dim TimeSplit = Token("modified").ToString.Split("-"c, "T"c, ":"c, "."c, " "c, "/"c)
Entry.ReleaseTime = Token("modified").ToObject(Of Date).ToLocalTime.ToString("yyyy'/'MM'/'dd HH':'mm")
'添加项
Versions.Add(Entry)
Next
Catch ex As Exception
- Throw New Exception("版本列表解析失败(" & Json.ToString & ")", ex)
+ Throw New Exception("Forge BMCLAPI 版本列表解析失败(" & Json.ToString & ")", ex)
End Try
If Not Versions.Any() Then Throw New Exception("没有可用版本")
Loader.Output = Versions
@@ -721,6 +738,132 @@
#End Region
+#Region "DlNeoForgeList | NeoForge 版本列表"
+
+ Public Structure DlNeoForgeListResult
+ '''
+ ''' 数据来源名称,如“Official”,“BMCLAPI”。
+ '''
+ Public SourceName As String
+ '''
+ ''' 是否为官方的实时数据。
+ '''
+ Public IsOfficial As Boolean
+ '''
+ ''' 所有版本的列表。已经按从新到老排序。
+ '''
+ Public Value As List(Of DlNeoForgeListEntry)
+ End Structure
+
+ Public Class DlNeoForgeListEntry
+ Inherits DlForgelikeEntry
+ '''
+ ''' 是否是 Beta 版。
+ '''
+ Public IsBeta As Boolean
+ '''
+ ''' API 使用的原始版本字符串,如 “20.4.30-beta”、“1.20.1-47.1.99”(Legacy)。
+ '''
+ Public ApiName As String
+ '''
+ ''' 文件在官网的基础地址,不包含后缀。
+ '''
+ Public ReadOnly Property UrlBase As String
+ Get
+ Dim PackageName As String = If(IsLegacy, "forge", "neoforge")
+ Return $"https://maven.neoforged.net/releases/net/neoforged/{PackageName}/{ApiName}/{PackageName}-{ApiName}"
+ End Get
+ End Property
+
+ Public Sub New(ApiName As String)
+ IsNeoForge = True
+ Me.ApiName = ApiName
+ IsBeta = ApiName.Contains("beta")
+ If ApiName.Contains("1.20.1") Then '1.20.1-47.1.99
+ VersionName = ApiName.Replace("1.20.1-", "")
+ Version = New Version("19." & VersionName)
+ Inherit = "1.20.1"
+ Else '20.4.30-beta
+ VersionName = ApiName
+ Version = New Version(ApiName.Before("-"))
+ Inherit = $"1.{Version.Major}" & If(Version.Minor = 0, "", "." & Version.Minor)
+ End If
+ End Sub
+ End Class
+
+ '''
+ ''' NeoForge 版本列表,主加载器。
+ '''
+ Public DlNeoForgeListLoader As New LoaderTask(Of Integer, DlNeoForgeListResult)("DlNeoForgeList Main", AddressOf DlNeoForgeListMain)
+ Private Sub DlNeoForgeListMain(Loader As LoaderTask(Of Integer, DlNeoForgeListResult))
+ Select Case Setup.Get("ToolDownloadVersion")
+ Case 0
+ DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)) From {
+ New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListBmclapiLoader, 30),
+ New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListOfficialLoader, 60)
+ }, Loader.IsForceRestarting)
+ Case 1
+ DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)) From {
+ New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListOfficialLoader, 5),
+ New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListBmclapiLoader, 35)
+ }, Loader.IsForceRestarting)
+ Case Else
+ DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)) From {
+ New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListOfficialLoader, 60),
+ New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListBmclapiLoader, 60)
+ }, Loader.IsForceRestarting)
+ End Select
+ End Sub
+
+ '''
+ ''' NeoForge 版本列表,官方源。
+ '''
+ Public DlNeoForgeListOfficialLoader As New LoaderTask(Of Integer, DlNeoForgeListResult)("DlNeoForgeList Official", AddressOf DlNeoForgeListOfficialMain)
+ Private Sub DlNeoForgeListOfficialMain(Loader As LoaderTask(Of Integer, DlNeoForgeListResult))
+ '获取版本列表 JSON
+ Dim ResultLatest As String = NetGetCodeByDownload("https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/neoforge", UseBrowserUserAgent:=True, IsJson:=True)
+ Dim ResultLegacy As String = NetGetCodeByDownload("https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/forge", UseBrowserUserAgent:=True, IsJson:=True)
+ If ResultLatest.Length < 100 OrElse ResultLegacy.Length < 100 Then Throw New Exception("获取到的版本列表长度不足(" & ResultLatest & ")")
+ '解析
+ Try
+ Loader.Output = New DlNeoForgeListResult With {.IsOfficial = True, .SourceName = "NeoForge 官方源",
+ .Value = GetNeoForgeEntries(ResultLatest, ResultLegacy)}
+ Catch ex As Exception
+ Throw New Exception("NeoForge 官方源版本列表解析失败(" & ResultLatest & vbCrLf & vbCrLf & ResultLegacy & ")", ex)
+ End Try
+ End Sub
+
+ '''
+ ''' NeoForge 版本列表,BMCLAPI。
+ '''
+ Public DlNeoForgeListBmclapiLoader As New LoaderTask(Of Integer, DlNeoForgeListResult)("DlNeoForgeList Bmclapi", AddressOf DlNeoForgeListBmclapiMain)
+ Public Sub DlNeoForgeListBmclapiMain(Loader As LoaderTask(Of Integer, DlNeoForgeListResult))
+ '获取版本列表 JSON
+ Dim ResultLatest As String = NetGetCodeByDownload("https://bmclapi2.bangbang93.com/neoforge/meta/api/maven/details/releases/net/neoforged/neoforge", UseBrowserUserAgent:=True, IsJson:=True)
+ Dim ResultLegacy As String = NetGetCodeByDownload("https://bmclapi2.bangbang93.com/neoforge/meta/api/maven/details/releases/net/neoforged/forge", UseBrowserUserAgent:=True, IsJson:=True)
+ If ResultLatest.Length < 100 OrElse ResultLegacy.Length < 100 Then Throw New Exception("获取到的版本列表长度不足(" & ResultLatest & ")")
+ '解析
+ Try
+ Loader.Output = New DlNeoForgeListResult With {.IsOfficial = True, .SourceName = "BMCLAPI",
+ .Value = GetNeoForgeEntries(ResultLatest, ResultLegacy)}
+ Catch ex As Exception
+ Throw New Exception("NeoForge BMCLAPI 版本列表解析失败(" & ResultLatest & vbCrLf & vbCrLf & ResultLegacy & ")", ex)
+ End Try
+ End Sub
+
+ Private Function GetNeoForgeEntries(LatestJson As String, LatestLegacyJson As String) As List(Of DlNeoForgeListEntry)
+ Dim VersionNames = RegexSearch(LatestLegacyJson & LatestJson,
+ "(?<="")(1\.20\.1-)?\d+\.\d+\.\d+(-beta)?(?="")") '我寻思直接正则就行.jpg
+ Dim Versions = VersionNames.
+ Where(Function(name) name <> "47.1.82"). '这个版本虽然在版本列表中,但不能下载
+ Select(Function(name) New DlNeoForgeListEntry(name)).ToList
+ If Not Versions.Any() Then Throw New Exception("没有可用版本")
+ Versions = Versions.OrderByDescending(Function(a) a.Version).ToList
+ Return Versions
+ End Function
+
+#End Region
+
#Region "DlLiteLoaderList | LiteLoader 版本列表"
Public Structure DlLiteLoaderListResult
@@ -741,6 +884,7 @@
'''
Public OfficialError As Exception
End Structure
+
Public Class DlLiteLoaderListEntry
'''
''' 实际的文件名,如“liteloader-installer-1.12-00-SNAPSHOT.jar”。
@@ -820,7 +964,7 @@
Next
Loader.Output = New DlLiteLoaderListResult With {.IsOfficial = True, .SourceName = "LiteLoader 官方源", .Value = Versions}
Catch ex As Exception
- Throw New Exception("版本列表解析失败(" & Result.ToString & ")", ex)
+ Throw New Exception("LiteLoader 官方源版本列表解析失败(" & Result.ToString & ")", ex)
End Try
End Sub
@@ -848,7 +992,7 @@
Next
Loader.Output = New DlLiteLoaderListResult With {.IsOfficial = False, .SourceName = "BMCLAPI", .Value = Versions}
Catch ex As Exception
- Throw New Exception("版本列表解析失败(" & Result.ToString & ")", ex)
+ Throw New Exception("LiteLoader BMCLAPI 版本列表解析失败(" & Result.ToString & ")", ex)
End Try
End Sub
@@ -906,7 +1050,7 @@
If Output.Value("game") Is Nothing OrElse Output.Value("loader") Is Nothing OrElse Output.Value("installer") Is Nothing Then Throw New Exception("获取到的列表缺乏必要项")
Loader.Output = Output
Catch ex As Exception
- Throw New Exception("列表解析失败(" & Result.ToString & ")", ex)
+ Throw New Exception("Fabric 官方源版本列表解析失败(" & Result.ToString & ")", ex)
End Try
End Sub
@@ -921,7 +1065,7 @@
If Output.Value("game") Is Nothing OrElse Output.Value("loader") Is Nothing OrElse Output.Value("installer") Is Nothing Then Throw New Exception("获取到的列表缺乏必要项")
Loader.Output = Output
Catch ex As Exception
- Throw New Exception("列表解析失败(" & Result.ToString & ")", ex)
+ Throw New Exception("Fabric BMCLAPI 版本列表解析失败(" & Result.ToString & ")", ex)
End Try
End Sub
@@ -939,30 +1083,121 @@
#End Region
+#Region "DlMod | Mod 镜像源请求"
+
+ '''
+ ''' 对可能涉及 Mod 镜像源的请求进行处理,返回字符串或 JObject。
+ ''' 调用 NetGetCodeByRequestOnce。
+ '''
+ Public Function DlModRequest(Url As String, Optional IsJson As Boolean = False) As Object
+ Dim McimUrl As String = DlSourceModGet(Url)
+ Dim Urls As New List(Of KeyValuePair(Of String, Integer))
+ If McimUrl <> Url Then
+ Select Case Setup.Get("ToolDownloadMod")
+ Case 0
+ Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 30))
+ Urls.Add(New KeyValuePair(Of String, Integer)(Url, 60))
+ Case 1
+ Urls.Add(New KeyValuePair(Of String, Integer)(Url, 5))
+ Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 35))
+ Case Else
+ Urls.Add(New KeyValuePair(Of String, Integer)(Url, 60))
+ Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 60))
+ End Select
+ End If
+ Dim Exs As String = ""
+ For Each Source In Urls
+ Try
+ Return NetGetCodeByRequestOnce(Source.Key, Encode:=Encoding.UTF8, Timeout:=Source.Value * 1000,
+ IsJson:=IsJson, UseBrowserUserAgent:=True)
+ Catch ex As Exception
+ Exs += ex.Message + vbCrLf
+ End Try
+ Next
+ Throw New Exception(Exs)
+ End Function
+
+ '''
+ ''' 对可能涉及 Mod 镜像源的请求进行处理。
+ ''' 调用 NetRequestOnce。
+ '''
+ Public Function DlModRequest(Url As String, Method As String, Data As String, ContentType As String, Optional Headers As Dictionary(Of String, String) = Nothing) As String
+ Dim McimUrl As String = DlSourceModGet(Url)
+ Dim Urls As New List(Of KeyValuePair(Of String, Integer))
+ If McimUrl <> Url Then
+ Select Case Setup.Get("ToolDownloadMod")
+ Case 0
+ Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 30))
+ Urls.Add(New KeyValuePair(Of String, Integer)(Url, 60))
+ Case 1
+ Urls.Add(New KeyValuePair(Of String, Integer)(Url, 5))
+ Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 35))
+ Case Else
+ Urls.Add(New KeyValuePair(Of String, Integer)(Url, 60))
+ Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 60))
+ End Select
+ End If
+ Dim Exs As String = ""
+ For Each Source In Urls
+ Try
+ Return NetRequestOnce(Source.Key, Method, Data, ContentType, Timeout:=Source.Value * 1000, Headers:=Headers)
+ Catch ex As Exception
+ Exs += ex.Message + vbCrLf
+ End Try
+ Next
+ Throw New Exception(Exs)
+ End Function
+
+#End Region
+
#Region "DlSource | 镜像下载源"
- Public Function DlSourceResourceGet(MojangBase As String) As String()
- MojangBase = MojangBase.Replace("http://resources.download.minecraft.net", "https://resources.download.minecraft.net")
+ Public Function DlSourceResourceGet(Original As String) As String()
+ Original = Original.Replace("http://resources.download.minecraft.net", "https://resources.download.minecraft.net")
Return {
- MojangBase.Replace("https://piston-data.mojang.com", "https://bmclapi2.bangbang93.com/assets").Replace("https://piston-meta.mojang.com", "https://bmclapi2.bangbang93.com/assets").Replace("https://resources.download.minecraft.net", "https://bmclapi2.bangbang93.com/assets"),
- MojangBase
- }
+ Original.
+ Replace("https://piston-data.mojang.com", "https://bmclapi2.bangbang93.com/assets").
+ Replace("https://piston-meta.mojang.com", "https://bmclapi2.bangbang93.com/assets").
+ Replace("https://resources.download.minecraft.net", "https://bmclapi2.bangbang93.com/assets"),
+ Original
+ }
End Function
- Public Function DlSourceLibraryGet(MojangBase As String) As String()
+ Public Function DlSourceLibraryGet(Original As String) As String()
Return {
- MojangBase.Replace("https://piston-data.mojang.com", "https://bmclapi2.bangbang93.com/maven").Replace("https://piston-meta.mojang.com", "https://bmclapi2.bangbang93.com/maven").Replace("https://libraries.minecraft.net", "https://bmclapi2.bangbang93.com/maven"),
- MojangBase.Replace("https://piston-data.mojang.com", "https://bmclapi2.bangbang93.com/libraries").Replace("https://piston-meta.mojang.com", "https://bmclapi2.bangbang93.com/libraries").Replace("https://libraries.minecraft.net", "https://bmclapi2.bangbang93.com/libraries"),
- MojangBase
- }
+ Original.
+ Replace("https://piston-data.mojang.com", "https://bmclapi2.bangbang93.com/maven").
+ Replace("https://piston-meta.mojang.com", "https://bmclapi2.bangbang93.com/maven").
+ Replace("https://libraries.minecraft.net", "https://bmclapi2.bangbang93.com/maven"),
+ Original.
+ Replace("https://piston-data.mojang.com", "https://bmclapi2.bangbang93.com/libraries").
+ Replace("https://piston-meta.mojang.com", "https://bmclapi2.bangbang93.com/libraries").
+ Replace("https://libraries.minecraft.net", "https://bmclapi2.bangbang93.com/libraries"),
+ Original
+ }
End Function
- Public Function DlSourceLauncherOrMetaGet(MojangBase As String) As String()
- If MojangBase Is Nothing Then Throw New Exception("无对应的 json 下载地址")
+ Public Function DlSourceModGet(Original As String) As String
+ Return Original.
+ Replace("api.modrinth.com", "mod.mcimirror.top/modrinth").
+ Replace("staging-api.modrinth.com", "mod.mcimirror.top/modrinth").
+ Replace("cdn.modrinth.com", "mod.mcimirror.top").
+ Replace("api.curseforge.com", "mod.mcimirror.top/curseforge").
+ Replace("edge.forgecdn.net", "mod.mcimirror.top").
+ Replace("mediafilez.forgecdn.net", "mod.mcimirror.top").
+ Replace("media.forgecdn.net", "mod.mcimirror.top")
+ End Function
+
+ Public Function DlSourceLauncherOrMetaGet(Original As String) As String()
+ If Original Is Nothing Then Throw New Exception("无对应的 json 下载地址")
Return {
- MojangBase.Replace("https://piston-data.mojang.com", "https://bmclapi2.bangbang93.com").Replace("https://piston-meta.mojang.com", "https://bmclapi2.bangbang93.com").Replace("https://launcher.mojang.com", "https://bmclapi2.bangbang93.com").Replace("https://launchermeta.mojang.com", "https://bmclapi2.bangbang93.com"),
- MojangBase
- }
+ Original.
+ Replace("https://piston-data.mojang.com", "https://bmclapi2.bangbang93.com").
+ Replace("https://piston-meta.mojang.com", "https://bmclapi2.bangbang93.com").
+ Replace("https://launcher.mojang.com", "https://bmclapi2.bangbang93.com").
+ Replace("https://launchermeta.mojang.com", "https://bmclapi2.bangbang93.com"),
+ Original
+ }
End Function
Private Sub DlSourceLoader(Of InputType, OutputType)(MainLoader As LoaderTask(Of InputType, OutputType),
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb
index 7767f6b..5852760 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb
@@ -1,5 +1,5 @@
Public Module ModJava
- Public JavaListCacheVersion As Integer = 6
+ Public JavaListCacheVersion As Integer = 7
'''
''' 目前所有可用的 Java。
@@ -220,6 +220,8 @@
JavaSearchFolder(GetPathFromFullPath(PathMcFolder), JavaPreList, False, True) 'Minecraft 文件夹的父文件夹(如果不是根目录的话)
End If
JavaSearchFolder(PathMcFolder, JavaPreList, False, True) 'Minecraft 文件夹
+ JavaPreList = JavaPreList.Where(Function(j) Not j.Key.Contains(".minecraft\runtime")).
+ ToDictionary(Function(j) j.Key, Function(j) j.Value) '排除官启自带 Java(#4286)
If RelatedVersion IsNot Nothing Then JavaSearchFolder(RelatedVersion.Path, JavaPreList, False, True) '所选版本文件夹
Dim TargetJavaList As New List(Of JavaEntry)
For Each Entry In JavaPreList
@@ -240,21 +242,25 @@
Dim UserJava As JavaEntry = Nothing
'获取版本独立设置中指定的 Java
- If RelatedVersion IsNot Nothing AndAlso Setup.Get("VersionArgumentJavaSelect", Version:=RelatedVersion).ToString.StartsWithF("{") Then
- Try
- UserJava = JavaEntry.FromJson(GetJson(Setup.Get("VersionArgumentJavaSelect", Version:=RelatedVersion)))
- UserJava.Check()
- Catch ex As ThreadInterruptedException
- Throw
- Catch ex As Exception
- UserJava = Nothing
- Setup.Reset("VersionArgumentJavaSelect", Version:=RelatedVersion)
- Log(ex, "版本独立设置中指定的 Java 已无法使用,此设置已重置", LogLevel.Hint)
- End Try
+ Dim VersionSelect As String = ""
+ If RelatedVersion IsNot Nothing Then
+ VersionSelect = Setup.Get("VersionArgumentJavaSelect", Version:=RelatedVersion)
+ If VersionSelect.StartsWithF("{") Then
+ Try
+ UserJava = JavaEntry.FromJson(GetJson(VersionSelect))
+ UserJava.Check()
+ Catch ex As ThreadInterruptedException
+ Throw
+ Catch ex As Exception
+ UserJava = Nothing
+ Setup.Reset("VersionArgumentJavaSelect", Version:=RelatedVersion)
+ Log(ex, "版本独立设置中指定的 Java 已无法使用,此设置已重置", LogLevel.Hint)
+ End Try
+ End If
End If
'获取全局设置中指定的 Java
- If UserJava Is Nothing AndAlso Setup.Get("LaunchArgumentJavaSelect") <> "" Then
+ If UserJava Is Nothing AndAlso VersionSelect <> "" AndAlso Setup.Get("LaunchArgumentJavaSelect") <> "" Then
Try
UserJava = JavaEntry.FromJson(GetJson(Setup.Get("LaunchArgumentJavaSelect")))
UserJava.Check()
@@ -546,7 +552,7 @@ NoUserJava:
'若不全为特殊引用,则清除特殊引用的地址
Dim JavaWithoutInherit As New Dictionary(Of String, Boolean)
For Each Pair In JavaPreList
- If Pair.Key.Contains("javapath_target_") OrElse Pair.Key.Contains("javatmp") Then
+ If Pair.Key.Contains("java8path_target_") OrElse Pair.Key.Contains("javapath_target_") OrElse Pair.Key.Contains("javatmp") Then
Log("[Java] 位于 " & Pair.Key & " 的 Java 包含特殊引用")
Else
Log("[Java] 位于 " & Pair.Key & " 的 Java 不含特殊引用")
@@ -665,34 +671,18 @@ Wait:
'若该目录有 Java,则加入结果
If File.Exists(Path & "javaw.exe") Then Results(Path) = Source
'查找其下的所有文件夹
+ Dim Keywords = {"java", "jdk", "env", "环境", "run", "软件", "jre", "mc", "dragon",
+ "soft", "cache", "temp", "corretto", "roaming", "users", "craft", "program", "世界", "net",
+ "游戏", "oracle", "game", "file", "data", "jvm", "服务", "server", "客户", "client", "整合",
+ "应用", "运行", "前置", "mojang", "官启", "新建文件夹", "eclipse", "microsoft", "hotspot",
+ "runtime", "x86", "x64", "forge", "原版", "optifine", "官方", "启动", "hmcl", "mod", "高清",
+ "download", "launch", "程序", "path", "version", "baka", "pcl", "zulu", "local", "packages",
+ "4297127d64ec6", "国服", "网易", "ext", "netease", "1.", "启动"}
For Each FolderInfo As DirectoryInfo In OriginalPath.EnumerateDirectories
If FolderInfo.Attributes.HasFlag(FileAttributes.ReparsePoint) Then Continue For '跳过符号链接
Dim SearchEntry = GetFolderNameFromPath(FolderInfo.Name).ToLower '用于搜索的字符串
- If IsFullSearch OrElse
- FolderInfo.Parent.Name.ToLower = "users" OrElse
- SearchEntry.Contains("java") OrElse SearchEntry.Contains("jdk") OrElse SearchEntry.Contains("env") OrElse
- SearchEntry.Contains("环境") OrElse SearchEntry.Contains("run") OrElse SearchEntry.Contains("软件") OrElse
- SearchEntry.Contains("jre") OrElse SearchEntry = "bin" OrElse SearchEntry.Contains("mc") OrElse
- SearchEntry.Contains("soft") OrElse SearchEntry.Contains("cache") OrElse SearchEntry.Contains("temp") OrElse
- SearchEntry.Contains("corretto") OrElse SearchEntry.Contains("roaming") OrElse SearchEntry.Contains("users") OrElse
- SearchEntry.Contains("craft") OrElse SearchEntry.Contains("program") OrElse SearchEntry.Contains("世界") OrElse
- SearchEntry.Contains("net") OrElse SearchEntry.Contains("游戏") OrElse SearchEntry.Contains("oracle") OrElse
- SearchEntry.Contains("game") OrElse SearchEntry.Contains("file") OrElse SearchEntry.Contains("data") OrElse
- SearchEntry.Contains("jvm") OrElse SearchEntry.Contains("服务") OrElse SearchEntry.Contains("server") OrElse
- SearchEntry.Contains("客户") OrElse SearchEntry.Contains("client") OrElse SearchEntry.Contains("整合") OrElse
- SearchEntry.Contains("应用") OrElse SearchEntry.Contains("运行") OrElse SearchEntry.Contains("前置") OrElse
- SearchEntry.Contains("mojang") OrElse SearchEntry.Contains("官启") OrElse SearchEntry.Contains("新建文件夹") OrElse
- SearchEntry.Contains("eclipse") OrElse SearchEntry.Contains("microsoft") OrElse SearchEntry.Contains("hotspot") OrElse
- SearchEntry.Contains("runtime") OrElse SearchEntry.Contains("x86") OrElse SearchEntry.Contains("x64") OrElse
- SearchEntry.Contains("forge") OrElse SearchEntry.Contains("原版") OrElse SearchEntry.Contains("optifine") OrElse
- SearchEntry.Contains("官方") OrElse SearchEntry.Contains("启动") OrElse SearchEntry.Contains("hmcl") OrElse
- SearchEntry.Contains("mod") OrElse SearchEntry.Contains("高清") OrElse SearchEntry.Contains("download") OrElse
- SearchEntry.Contains("launch") OrElse SearchEntry.Contains("程序") OrElse SearchEntry.Contains("path") OrElse
- SearchEntry.Contains("version") OrElse SearchEntry.Contains("baka") OrElse SearchEntry.Contains("pcl") OrElse
- SearchEntry.Contains("zulu") OrElse
- SearchEntry.Contains("local") OrElse SearchEntry.Contains("packages") OrElse SearchEntry.Contains("4297127d64ec6") OrElse '官启文件夹
- SearchEntry.Contains("国服") OrElse SearchEntry.Contains("网易") OrElse SearchEntry.Contains("ext") OrElse '网易 Java 文件夹名
- SearchEntry.Contains("netease") OrElse SearchEntry.Contains("1.") OrElse SearchEntry.Contains("启动") Then
+ If IsFullSearch OrElse FolderInfo.Parent.Name.ToLower = "users" OrElse
+ Keywords.Any(Function(w) SearchEntry.Contains(w)) OrElse SearchEntry = "bin" Then
JavaSearchFolder(FolderInfo, Results, Source)
End If
Next
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
index 2067e77..b1731f8 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
@@ -113,10 +113,18 @@ Public Module ModLaunch
New LoaderTask(Of Process, Integer)("等待游戏窗口出现", AddressOf McLaunchWait) With {.ProgressWeight = 1},
New LoaderTask(Of Integer, Integer)("结束处理", AddressOf McLaunchEnd) With {.ProgressWeight = 1}
}
- If Setup.Get("LaunchArgumentRam") Then
- CType(Loaders(2), LoaderCombo(Of String)).Block = False
- Loaders.Insert(3, New LoaderTask(Of Integer, Integer)("内存优化", AddressOf McLaunchMemoryOptimize) With {.ProgressWeight = 30})
- End If
+ '内存优化
+ Select Case Setup.Get("VersionRamOptimize", Version:=McVersionCurrent)
+ Case 0 '全局
+ If Setup.Get("LaunchArgumentRam") Then '使用全局设置
+ CType(Loaders(2), LoaderCombo(Of String)).Block = False
+ Loaders.Insert(3, New LoaderTask(Of Integer, Integer)("内存优化", AddressOf McLaunchMemoryOptimize) With {.ProgressWeight = 30})
+ End If
+ Case 1 '开启
+ CType(Loaders(2), LoaderCombo(Of String)).Block = False
+ Loaders.Insert(3, New LoaderTask(Of Integer, Integer)("内存优化", AddressOf McLaunchMemoryOptimize) With {.ProgressWeight = 30})
+ Case 2 '关闭
+ End Select
Dim LaunchLoader As New LoaderCombo(Of Object)("Minecraft 启动", Loaders) With {.Show = False}
If McLoginLoader.State = LoadState.Finished Then McLoginLoader.State = LoadState.Waiting '要求重启登录主加载器,它会自行决定是否启动副加载器
'等待加载器执行并更新 UI
@@ -217,7 +225,7 @@ NextInner:
"如果觉得 PCL 还算好用的话,也可以考虑赞助一下作者……一点心意也行……" & vbCrLf &
"毕竟一个人开发也不容易(悲)……",
"求赞助啦……", "这就赞助!", "但是我拒绝") = 1 Then
- OpenWebsite("https://afdian.net/a/LTCat")
+ OpenWebsite("https://afdian.com/a/LTCat")
End If
End Select
End Sub, "Donate")
@@ -502,10 +510,8 @@ NextInner:
If Input.OAuthRefreshToken = "" Then
'无 RefreshToken
Relogin:
- Dim OAuthCode As String = MsLoginStep1(Data, ClientId)
- If OAuthCode = "Cancel" Then
- Exit Sub
- End If
+ Dim OAuthCode As String = MsLoginStep1(Data)
+ If OAuthCode = "Cancel" Then Exit Sub
If Data.IsAborted Then Throw New ThreadInterruptedException
Data.Progress = 0.2
OAuthTokens = MsLoginStep2(OAuthCode, False, ClientId)
@@ -802,43 +808,21 @@ LoginFinish:
End Try
End Function
- '微软登录步骤 1:获取 DeviceCode 并显示验证提示
- Private Function MsLoginStep1(Data As LoaderTask(Of McLoginMs, McLoginResult), ClientId As String) As String
- If MyMsgBox("请在打开的网页里输入 PCL2 提供的设备代码(会自动复制到剪贴板)并登录微软账户,然后允许 PCL2 访问相关信息。" & vbCrLf & "设备代码有时效性,若操作时间过长需要重新进行登录流程。", "正版验证确认", "继续", "取消") = 1 Then
- McLaunchLog("开始微软登录步骤 1")
-
- Dim DeviceCode As String
- Dim UserCode As String
- Dim VerifyUri As String
- Dim ExpiresIn As String
- Dim Request As String = "client_id=" & ClientId & "&" & "scope=XboxLive.signin%20offline_access"
- Dim Result As String = NetRequestMulty("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", "POST", Request, "application/x-www-form-urlencoded", 2)
-
- Dim ResultJson As JObject = GetJson(Result)
- DeviceCode = ResultJson("device_code")
- UserCode = ResultJson("user_code")
- VerifyUri = ResultJson("verification_uri")
- ExpiresIn = ResultJson("expires_in")
- ClipboardSet(UserCode)
- OpenWebsite(VerifyUri)
-
- Dim MsgBoxValue As String = ""
- While MsgBoxValue IsNot "1"
- MsgBoxValue = MyMsgBox("本次验证的设备代码为:" & UserCode & vbCrLf & vbCrLf & "你也可以在任意设备上打开下列网址进行验证:" & vbCrLf & VerifyUri & vbCrLf & vbCrLf & "在验证完成后,你可以直接关闭这个弹窗,PCL2 会自动完成接下来的流程。", "正版验证", "关闭", "复制网址", "复制设备代码").ToString
- If MsgBoxValue = "2" Then
- ClipboardSet(VerifyUri)
- Continue While
- ElseIf MsgBoxValue = "3" Then
- ClipboardSet(UserCode)
- Continue While
- ElseIf MsgBoxValue = "1" Then
- Exit While
- End If
- End While
-
- Return DeviceCode
+ '微软登录步骤 1:打开网页认证,获取 OAuth Code
+ Private Function MsLoginStep1(Data As LoaderTask(Of McLoginMs, McLoginResult)) As String
+ McLaunchLog("开始微软登录步骤 1")
+ OpenWebsite(FormLoginOAuth.LoginUrl1)
+ Dim Result As String =
+ MyMsgBoxInput("等待网页登录",
+ "登录完成后,网页会变得完全空白。把那个空白网页的网址复制到下面的框中就行!" & vbCrLf &
+ "如果网络环境不佳,它可能一直加载不出来,那就只能试试用 VPN 或加速器了。",
+ ValidateRules:=New ObjectModel.Collection(Of Validate) From {New ValidateRegex("(?<=code\=)[^&]+", "返回网址应以 https://login.live.com/oauth20_desktop.srf?code= 开头")},
+ HintText:="https://login.live.com/oauth20_desktop.srf?code=XXXXXX")
+ If Result Is Nothing Then
+ McLaunchLog("微软登录已在步骤 1 被取消")
+ Throw New ThreadInterruptedException("$$")
Else
- Return "Cancel"
+ Return RegexSeek(Result, "(?<=code\=)[^&]+")
End If
End Function
@@ -895,19 +879,112 @@ LoginFinish:
Return {"Cancel", ""}
End Function
+
+ ''微软登录步骤 1:获取 DeviceCode 并显示验证提示
+ ''https://learn.microsoft.com/zh-cn/entra/identity-platform/v2-oauth2-device-code
+ 'Private Function MsLoginStep1(Data As LoaderTask(Of McLoginMs, McLoginResult)) As String
+ ' McLaunchLog("开始微软登录步骤 1:获取验证信息")
+ ' Dim PrepareJson As JObject = GetJson(NetRequestMulty("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", "POST",
+ ' $"client_id={OAuthClientId}&scope=XboxLive.signin%20offline_access", "application/x-www-form-urlencoded", 2))
+
+ ' '从这里开始直到步骤 2 结束都没有 Review
+ ' '参考:https://learn.microsoft.com/zh-cn/entra/identity-platform/v2-oauth2-device-code
+ ' If MyMsgBox("请在打开的网页里输入 PCL2 提供的设备代码(会自动复制到剪贴板)。" & vbCrLf &
+ ' "设备代码有时效性,若操作时间过长需要重新进行登录流程。", "正版验证确认", "继续", "取消") <> 1 Then
+ ' Return "Cancel"
+ ' End If
+
+ ' Dim DeviceCode As String = PrepareJson("device_code")
+ ' Dim UserCode As String = PrepareJson("user_code")
+ ' Dim VerifyUri As String = PrepareJson("verification_uri")
+ ' 'ResultJson("expires_in")
+ ' ClipboardSet(UserCode)
+ ' OpenWebsite(VerifyUri)
+
+ ' Dim MsgBoxValue As String = ""
+ ' While MsgBoxValue IsNot "1"
+ ' MsgBoxValue = MyMsgBox("本次验证的设备代码为:" & UserCode & vbCrLf & vbCrLf & "你也可以在任意设备上打开下列网址进行验证:" & vbCrLf & VerifyUri & vbCrLf & vbCrLf & "在验证完成后,你可以直接关闭这个弹窗,PCL2 会自动完成接下来的流程。", "正版验证", "关闭", "复制网址", "复制设备代码").ToString
+ ' If MsgBoxValue = "2" Then
+ ' ClipboardSet(VerifyUri)
+ ' Continue While
+ ' ElseIf MsgBoxValue = "3" Then
+ ' ClipboardSet(UserCode)
+ ' Continue While
+ ' ElseIf MsgBoxValue = "1" Then
+ ' Exit While
+ ' End If
+ ' End While
+
+ ' Return DeviceCode
+ 'End Function
+
+ ''微软登录步骤 2:从 OAuth Code 或 OAuth RefreshToken 获取 {OAuth AccessToken, OAuth RefreshToken}
+ 'Private Function MsLoginStep2(Code As String, IsRefresh As Boolean, Optional ExpiresIn As String = "900") As String()
+ ' McLaunchLog("开始微软登录步骤 2(" & If(IsRefresh, "", "非") & "刷新登录)")
+
+ ' Dim Request As String
+ ' If IsRefresh Then
+ ' Request = "grant_type=refresh_token" & "&" &
+ ' "client_id=" & OAuthClientId & "&" &
+ ' "device_code=" & Code & "&" &
+ ' "refresh_token=" & Uri.EscapeDataString(Code) & "&" &
+ ' "scope=XboxLive.signin%20offline_access"
+ ' Else
+ ' Request = "grant_type=urn:ietf:params:oauth:grant-type:device_code" & "&" &
+ ' "client_id=" & OAuthClientId & "&" &
+ ' "device_code=" & Code & "&" &
+ ' "scope=XboxLive.signin%20offline_access"
+ ' End If
+ ' Dim Result As String
+ ' Dim stopwatch As Stopwatch = Stopwatch.StartNew()
+
+ ' While stopwatch.Elapsed < TimeSpan.FromSeconds(ExpiresIn)
+ ' Try
+ ' Result = NetRequestMulty("https://login.microsoftonline.com/consumers/oauth2/v2.0/token", "POST", Request, "application/x-www-form-urlencoded", 2)
+ ' Catch ex As Exception
+ ' If ex.Message.Contains("must sign in again") OrElse ex.Message.Contains("invalid_grant") Then '#269
+ ' Return {"Relogin", ""}
+ ' ElseIf ex.Message.Contains("authorization_declined") Then
+ ' Hint("你拒绝了 PCL2 的访问权限申请,验证过程被中断!")
+ ' Return {"Cancel", ""}
+ ' ElseIf ex.Message.Contains("expired_token") Then
+ ' Hint("Token 已过期,请尝试重新验证!")
+ ' Exit While
+ ' ElseIf ex.Message.Contains("AADSTS70016") Then
+ ' Continue While
+ ' Else
+ ' Throw
+ ' End If
+ ' End Try
+
+ ' If Result IsNot Nothing Then
+ ' Dim ResultJson As JObject = GetJson(Result)
+ ' Dim AccessToken As String = ResultJson("access_token").ToString
+ ' Dim RefreshToken As String = ResultJson("refresh_token").ToString
+ ' Return {AccessToken, RefreshToken}
+ ' End If
+
+ ' Thread.Sleep(1000)
+ ' End While
+
+ ' Hint("验证超时,请尝试重新验证!")
+ ' Return {"Cancel", ""}
+
+ 'End Function
+
'微软登录步骤 3:从 OAuth AccessToken 获取 XBLToken
Private Function MsLoginStep3(AccessToken As String) As String
McLaunchLog("开始微软登录步骤 3")
Dim Request As String = "{
- ""Properties"": {
- ""AuthMethod"": ""RPS"",
- ""SiteName"": ""user.auth.xboxlive.com"",
- ""RpsTicket"": ""d=" & AccessToken & """
- },
- ""RelyingParty"": ""http://auth.xboxlive.com"",
- ""TokenType"": ""JWT""
- }"
+ ""Properties"": {
+ ""AuthMethod"": ""RPS"",
+ ""SiteName"": ""user.auth.xboxlive.com"",
+ ""RpsTicket"": """ & AccessToken & """
+ },
+ ""RelyingParty"": ""http://auth.xboxlive.com"",
+ ""TokenType"": ""JWT""
+ }" 'TODO: 新版登录改为 ""RpsTicket"": ""d=" & AccessToken & """
Dim Result As String = NetRequestMulty("https://user.auth.xboxlive.com/user/authenticate", "POST", Request, "application/json", 3)
Dim ResultJson As JObject = GetJson(Result)
@@ -1064,7 +1141,7 @@ LoginFinish:
Case 3
'使用正版用户名
Try
- If Not SkinName = "" Then
+ If SkinName <> "" AndAlso McVersionCurrent.Version.McCodeMain < 20 Then '1.20+ 或快照版不能使用该项(#3746)
Log("[Skin] 由于离线皮肤设置,使用正版 UUID:" & SkinName)
Uuid = McLoginMojangUuid(SkinName, False)
End If
@@ -1075,8 +1152,8 @@ LoginFinish:
Case 4
'自定义
Do Until McSkinSex(Uuid) = If(Setup.Get("LaunchSkinSlim"), "Alex", "Steve")
- If Uuid.EndsWithF("FFFFF") Then Uuid = Mid(Uuid, 1, 32 - 5) & "00000"
- Uuid = Mid(Uuid, 1, 32 - 5) & (Long.Parse(Right(Uuid, 5), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X").PadLeft(5, "0")
+ If Uuid.EndsWithF("FFFFF") Then Uuid = Uuid.Substring(0, 27) & "00000"
+ Uuid = Uuid.Substring(0, 27) & (Long.Parse(Uuid.Substring(27), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X").PadLeft(5, "0")
Loop
End Select
Return Uuid
@@ -1194,7 +1271,7 @@ LoginFinish:
'统一通行证检测
If Setup.Get("LoginType") = McLoginType.Nide Then
'至少 Java 8u101
- MinVer = If(New Version(1, 8, 0, 101) > MinVer, New Version(1, 8, 0, 101), MinVer)
+ MinVer = If(New Version(1, 8, 0, 141) > MinVer, New Version(1, 8, 0, 141), MinVer)
End If
SyncLock JavaLock
@@ -1221,12 +1298,12 @@ LoginFinish:
ElseIf MaxVer < New Version(1, 8, 0, 0) Then
JavaCode = 7
If Not JavaDownloadConfirm("Java 7", True) Then Throw New Exception("$$")
- ElseIf MinVer > New Version(1, 8, 0, 100) AndAlso MaxVer < New Version(1, 8, 0, 321) Then
- JavaCode = "8u101"
- If Not JavaDownloadConfirm("Java 8.0.101 ~ 8.0.320", True) Then Throw New Exception("$$")
- ElseIf MinVer > New Version(1, 8, 0, 100) Then
- JavaCode = "8u101"
- If Not JavaDownloadConfirm("Java 8.0.101 或更高版本的 Java 8", True) Then Throw New Exception("$$")
+ ElseIf MinVer > New Version(1, 8, 0, 140) AndAlso MaxVer < New Version(1, 8, 0, 321) Then
+ JavaCode = "8u141"
+ If Not JavaDownloadConfirm("Java 8.0.141 ~ 8.0.320", True) Then Throw New Exception("$$")
+ ElseIf MinVer > New Version(1, 8, 0, 140) Then
+ JavaCode = "8u141"
+ If Not JavaDownloadConfirm("Java 8.0.141 或更高版本的 Java 8", True) Then Throw New Exception("$$")
ElseIf MaxVer < New Version(1, 8, 0, 321) Then
JavaCode = 8
If Not JavaDownloadConfirm("Java 8.0.320 或更低版本的 Java 8") Then Throw New Exception("$$")
@@ -1271,25 +1348,40 @@ LoginFinish:
''' 释放 Java Wrapper 并返回完整文件路径。
'''
Public Function ExtractJavaWrapper() As String
- Dim WrapperPath As String = GetJavaWrapperDir() & "\JavaWrapper.jar"
+ Dim BaseDir As String = GetJavaWrapperDir()
+ Dim WrapperPath As String = BaseDir & "\JavaWrapper.jar"
+ Log("[Java] 选定的 Java Wrapper 路径:" & WrapperPath)
SyncLock ExtractJavaWrapperLock '避免 OptiFine 和 Forge 安装时同时释放 Java Wrapper 导致冲突
- WriteFile(WrapperPath, GetResources("JavaWrapper"))
+ Dim IsWrapperWritten As Boolean = WriteFile(WrapperPath, GetResources("JavaWrapper"))
+ If Not IsWrapperWritten AndAlso File.Exists(WrapperPath) Then
+ '以下为 #4243 的修复,因为未知原因 Java Wrapper 可能变为只读文件
+ Log("[Java] Java Wrapper 文件释放失败,但文件已存在,将在删除后尝试重新生成", LogLevel.Debug)
+ Try
+ File.Delete(WrapperPath)
+ IsWrapperWritten = WriteFile(WrapperPath, GetResources("JavaWrapper"))
+ Catch ex As Exception
+ Log(ex, "Java Wrapper 文件重新释放失败,将尝试更换文件名重新生成")
+ WrapperPath = BaseDir & "\JavaWrapper2.jar"
+ IsWrapperWritten = WriteFile(WrapperPath, GetResources("JavaWrapper"))
+ End Try
+ End If
+ If Not IsWrapperWritten Then Throw New FileNotFoundException("释放 Java Wrapper 失败,请查看 PCL 日志查找详细信息")
End SyncLock
- Log("[Java] 已释放 Java Wrapper:" & WrapperPath)
Return WrapperPath
End Function
Private ExtractJavaWrapperLock As New Object
+
'''
''' 获取 Java Wrapper 所在的文件夹,不以 \ 结尾。
'''
Public Function GetJavaWrapperDir() As String
- If PathAppdata.IsASCII() Then
+ If (Path & "PCL").IsASCII() Then
+ Return Path & "PCL"
+ ElseIf PathAppdata.IsASCII() Then
Return PathAppdata.TrimEnd("\")
ElseIf PathTemp.IsASCII() Then
- Log("[Java] Wrapper:AppData 路径中包含非 ASCII 字符,换用 Temp 目录")
Return PathTemp.TrimEnd("\")
Else
- Log("[Java] Wrapper:AppData 路径与 Temp 路径中均包含非 ASCII 字符,换用 ProgramData 目录")
Return OsDrive & "ProgramData\PCL"
End If
End Function
@@ -1765,7 +1857,6 @@ NextVersion:
{
""authenticationDatabase"": {
""00000111112222233333444445555566"": {
- ""accessToken"": """ & McLoginLoader.Output.AccessToken & """,
""username"": """ & McLoginLoader.Output.Name.Replace("""", "-") & """,
""profiles"": {
""66666555554444433333222221111100"": {
@@ -1796,7 +1887,6 @@ NextVersion:
{
""authenticationDatabase"": {
""00000111112222233333444445555566"": {
- ""accessToken"": """ & McLoginLoader.Output.AccessToken & """,
""username"": """ & McLoginLoader.Output.Name.Replace("""", "-") & """,
""profiles"": {
""66666555554444433333222221111100"": {
@@ -1872,16 +1962,12 @@ NextVersion:
End Try
'离线皮肤 Alex 警告
- Try
- If McVersionCurrent.Version.McCodeMain <= 7 AndAlso McVersionCurrent.Version.McCodeMain >= 2 AndAlso '1.7 ~ 1.2
+ If McVersionCurrent.Version.McCodeMain <= 7 AndAlso McVersionCurrent.Version.McCodeMain >= 2 AndAlso '1.2 ~ 1.7
McLoginLoader.Input.Type = McLoginType.Legacy AndAlso '离线登录
(Setup.Get("LaunchSkinType") = 2 OrElse '强制 Alex
(Setup.Get("LaunchSkinType") = 4 AndAlso Setup.Get("LaunchSkinSlim"))) Then '或选用 Alex 皮肤
- Hint("此 Minecraft 版本尚不支持 Alex 皮肤,你的皮肤可能会显示为 Steve!", HintType.Critical)
- End If
- Catch ex As Exception
- Log(ex, "检查离线皮肤失效失败")
- End Try
+ Hint("此 Minecraft 版本尚不支持 Alex 皮肤,你的皮肤可能会显示为 Steve!", HintType.Critical)
+ End If
'离线皮肤资源包
Try
@@ -2123,6 +2209,8 @@ IgnoreCustomSkin:
StartInfo.EnvironmentVariables("Path") = Join(Paths.Distinct.ToList, ";")
'设置其他参数
+ StartInfo.StandardErrorEncoding = Encoding.UTF8
+ StartInfo.StandardOutputEncoding = Encoding.UTF8
StartInfo.WorkingDirectory = McVersionCurrent.PathIndie
StartInfo.UseShellExecute = False
StartInfo.RedirectStandardOutput = True
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
index 458a42a..abc4a6b 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
@@ -151,7 +151,7 @@ Public Module ModMinecraft
#Region "版本处理"
- Public Const McVersionCacheVersion As Integer = 29
+ Public Const McVersionCacheVersion As Integer = 30
Private _McVersionCurrent As McVersion
Private _McVersionLast = 0 '为 0 以保证与 Nothing 不相同,使得 UI 显示可以正常初始化
@@ -290,7 +290,7 @@ Public Module ModMinecraft
Public ReadOnly Property Modable As Boolean
Get
If Not IsLoaded Then Load()
- Return Version.HasFabric OrElse Version.HasForge OrElse Version.HasLiteLoader OrElse
+ Return Version.HasFabric OrElse Version.HasForge OrElse Version.HasLiteLoader OrElse Version.HasNeoForge OrElse
DisplayType = McVersionCardType.API '#223
End Get
End Property
@@ -345,7 +345,7 @@ Public Module ModMinecraft
End If
Next
End If
- '从 Forge Arguments 中获取版本号
+ '从 Forge / NeoForge Arguments 中获取版本号
If JsonObject("arguments") IsNot Nothing AndAlso JsonObject("arguments")("game") IsNot Nothing Then
Dim Mark As Boolean = False
For Each Argument In JsonObject("arguments")("game")
@@ -565,6 +565,7 @@ Recheck:
Log(ex, "合并版本依赖项 json 失败(" & If(InheritVersion, "null").ToString & ")")
End Try
Catch ex As Exception
+ Log($"[Minecraft] 传入的版本 json 文件内容(共 {Text.Length} 字符,最多输出前 5000 字符):{vbCrLf}{Text.Substring(0, 5000)}")
Throw New Exception("版本 json 不规范(" & If(Name, "null") & ")", ex)
End Try
Try
@@ -665,7 +666,7 @@ Recheck:
Try
Dim JsonObjCheck = JsonObject
Catch ex As Exception
- Log(ex, "版本 json 可用性检查失败(" & Path & ")")
+ Log(ex, "版本 JSON 可用性检查失败(" & Path & ")")
JsonText = ""
JsonObject = Nothing
Info = ex.Message
@@ -715,8 +716,8 @@ Recheck:
'OptiFine
If RealJson.Contains("optifine") Then
State = McVersionState.OptiFine
- Version.OptiFineVersion = If(RegexSeek(RealJson, "(?<=HD_U_)[^"":/]+"), "未知版本")
Version.HasOptiFine = True
+ Version.OptiFineVersion = If(RegexSeek(RealJson, "(?<=HD_U_)[^"":/]+"), "未知版本")
End If
'LiteLoader
If RealJson.Contains("liteloader") Then
@@ -727,14 +728,20 @@ Recheck:
'FUTURE: [Quilt 支持] 确认这里的玩意儿对不对
If RealJson.Contains("net.fabricmc:fabric-loader") OrElse RealJson.Contains("org.quiltmc:quilt-loader") Then
State = McVersionState.Fabric
- Version.FabricVersion = If(RegexSeek(RealJson, "(?<=(net.fabricmc:fabric-loader:)|(org.quiltmc:quilt-loader:))[0-9\.]+(\+build.[0-9]+)?"), "未知版本").Replace("+build", "")
Version.HasFabric = True
- ElseIf RealJson.Contains("minecraftforge") Then
+ Version.FabricVersion = If(RegexSeek(RealJson, "(?<=(net.fabricmc:fabric-loader:)|(org.quiltmc:quilt-loader:))[0-9\.]+(\+build.[0-9]+)?"), "未知版本").Replace("+build", "")
+ ElseIf RealJson.Contains("minecraftforge") AndAlso Not RealJson.Contains("net.neoforge") Then
State = McVersionState.Forge
+ Version.HasForge = True
Version.ForgeVersion = RegexSeek(RealJson, "(?<=forge:[0-9\.]+(_pre[0-9]*)?\-)[0-9\.]+")
If Version.ForgeVersion Is Nothing Then Version.ForgeVersion = RegexSeek(RealJson, "(?<=net\.minecraftforge:minecraftforge:)[0-9\.]+")
If Version.ForgeVersion Is Nothing Then Version.ForgeVersion = If(RegexSeek(RealJson, "(?<=net\.minecraftforge:fmlloader:[0-9\.]+-)[0-9\.]+"), "未知版本")
- Version.HasForge = True
+ ElseIf RealJson.Contains("net.neoforge") Then
+ '1.20.1 JSON 范例:"--fml.forgeVersion", "47.1.99"
+ '1.20.2+ JSON 范例:"--fml.neoForgeVersion", "20.6.119-beta"
+ State = McVersionState.NeoForge
+ Version.HasNeoForge = True
+ Version.NeoForgeVersion = If(RegexSeek(RealJson, "(?<=orgeVersion"",[^""]*?"")[^""]+(?="",)"), "未知版本")
End If
Version.IsApiLoaded = True
End Select
@@ -752,6 +759,8 @@ ExitDataLoad:
Logo = PathImage & "Blocks/CobbleStone.png"
Case McVersionState.Forge
Logo = PathImage & "Blocks/Anvil.png"
+ Case McVersionState.NeoForge
+ Logo = PathImage & "Blocks/NeoForge.png"
Case McVersionState.Fabric
Logo = PathImage & "Blocks/Fabric.png"
Case McVersionState.OptiFine
@@ -780,7 +789,7 @@ ExitDataLoad:
End If
Case McVersionState.Old
Info = "远古版本"
- Case McVersionState.Original, McVersionState.Forge, McVersionState.Fabric, McVersionState.OptiFine, McVersionState.LiteLoader
+ Case McVersionState.Original, McVersionState.Forge, McVersionState.NeoForge, McVersionState.Fabric, McVersionState.OptiFine, McVersionState.LiteLoader
Info = Version.ToString
Case McVersionState.Fool
Info = GetMcFoolName(Version.McName)
@@ -813,6 +822,7 @@ ExitDataLoad:
WriteIni(Path & "PCL\Setup.ini", "VersionOptiFine", Version.OptiFineVersion)
WriteIni(Path & "PCL\Setup.ini", "VersionLiteLoader", Version.HasLiteLoader)
WriteIni(Path & "PCL\Setup.ini", "VersionForge", Version.ForgeVersion)
+ WriteIni(Path & "PCL\Setup.ini", "VersionNeoForge", Version.NeoForgeVersion)
WriteIni(Path & "PCL\Setup.ini", "VersionApiCode", Version.SortCode)
WriteIni(Path & "PCL\Setup.ini", "VersionOriginal", Version.McName)
WriteIni(Path & "PCL\Setup.ini", "VersionOriginalMain", Version.McCodeMain)
@@ -852,6 +862,7 @@ ExitDataLoad:
OptiFine
Old
Forge
+ NeoForge
LiteLoader
Fabric
End Enum
@@ -903,6 +914,17 @@ ExitDataLoad:
'''
Public ForgeVersion As String = ""
+ 'NeoForge
+
+ '''
+ ''' 该版本是否安装了 NeoForge。
+ '''
+ Public HasNeoForge As Boolean = False
+ '''
+ ''' NeoForge 版本号,如 21.0.2-beta、47.1.79。
+ '''
+ Public NeoForgeVersion As String = ""
+
'Fabric
'''
@@ -929,6 +951,7 @@ ExitDataLoad:
Public Overrides Function ToString() As String
ToString = ""
If HasForge Then ToString += ", Forge" & If(ForgeVersion = "未知版本", "", " " & ForgeVersion)
+ If HasNeoForge Then ToString += ", NeoForge" & If(NeoForgeVersion = "未知版本", "", " " & NeoForgeVersion)
If HasFabric Then ToString += ", Fabric" & If(FabricVersion = "未知版本", "", " " & FabricVersion)
If HasOptiFine Then ToString += ", OptiFine" & If(OptiFineVersion = "未知版本", "", " " & OptiFineVersion)
If HasLiteLoader Then ToString += ", LiteLoader"
@@ -955,15 +978,15 @@ ExitDataLoad:
Else
Throw New Exception("无效的 Fabric 版本:" & ForgeVersion)
End If
- ElseIf HasForge Then
- If ForgeVersion = "未知版本" Then Return 0
- Dim SubVersions = ForgeVersion.Split(".")
+ ElseIf HasForge OrElse HasNeoForge Then
+ If ForgeVersion = "未知版本" AndAlso NeoForgeVersion = "未知版本" Then Return 0
+ Dim SubVersions = If(HasForge, ForgeVersion.Split("."), NeoForgeVersion.Split("."))
If SubVersions.Length = 4 Then
_SortCode = Val(SubVersions(0)) * 1000000 + Val(SubVersions(1)) * 10000 + Val(SubVersions(3))
ElseIf SubVersions.Length = 3 Then
_SortCode = Val(SubVersions(0)) * 1000000 + Val(SubVersions(1)) * 10000 + Val(SubVersions(2))
Else
- Throw New Exception("无效的 Forge 版本:" & ForgeVersion)
+ Throw New Exception("无效的 Neo/Forge 版本:" & ForgeVersion)
End If
ElseIf HasOptiFine Then
If OptiFineVersion = "未知版本" Then Return 0
@@ -1175,6 +1198,7 @@ OnLoaded:
Dim VersionInfo As New McVersionInfo With {
.FabricVersion = ReadIni(Version.Path & "PCL\Setup.ini", "VersionFabric", ""),
.ForgeVersion = ReadIni(Version.Path & "PCL\Setup.ini", "VersionForge", ""),
+ .NeoForgeVersion = ReadIni(Version.Path & "PCL\Setup.ini", "VersionNeoForge", ""),
.OptiFineVersion = ReadIni(Version.Path & "PCL\Setup.ini", "VersionOptiFine", ""),
.HasLiteLoader = ReadIni(Version.Path & "PCL\Setup.ini", "VersionLiteLoader", False),
.SortCode = ReadIni(Version.Path & "PCL\Setup.ini", "VersionApiCode", -1),
@@ -1183,9 +1207,10 @@ OnLoaded:
.McCodeSub = ReadIni(Version.Path & "PCL\Setup.ini", "VersionOriginalSub", -1),
.IsApiLoaded = True
}
- VersionInfo.HasFabric = VersionInfo.FabricVersion.Count > 1
- VersionInfo.HasForge = VersionInfo.ForgeVersion.Count > 1
- VersionInfo.HasOptiFine = VersionInfo.OptiFineVersion.Count > 1
+ VersionInfo.HasFabric = VersionInfo.FabricVersion.Any()
+ VersionInfo.HasForge = VersionInfo.ForgeVersion.Any()
+ VersionInfo.HasNeoForge = VersionInfo.NeoForgeVersion.Any()
+ VersionInfo.HasOptiFine = VersionInfo.OptiFineVersion.Any()
Version.Version = VersionInfo
End If
@@ -1273,7 +1298,7 @@ OnLoaded:
McVersionFilter(VersionList, VersionListOriginal, {McVersionState.Fool}, McVersionCardType.Fool)
'筛选 API 版本
- McVersionFilter(VersionList, VersionListOriginal, {McVersionState.Forge, McVersionState.LiteLoader, McVersionState.Fabric}, McVersionCardType.API)
+ McVersionFilter(VersionList, VersionListOriginal, {McVersionState.Forge, McVersionState.NeoForge, McVersionState.LiteLoader, McVersionState.Fabric}, McVersionCardType.API)
'将老版本预先分类入不常用,只剩余原版、快照、OptiFine
Dim VersionUseful As New List(Of McVersion)
@@ -1407,7 +1432,7 @@ OnLoaded:
End Function)
End If
- 'API 版本:优先按版本排序,此后【先放 Fabric,再放 Forge(按版本号从高到低排序),最后放 LiteLoader(按名称排序)】
+ 'API 版本:优先按版本排序,此后【先放 Fabric,再放 Neo/Forge(按版本号从高到低排序),最后放 LiteLoader(按名称排序)】
If ResultVersionList.ContainsKey(McVersionCardType.API) Then
ResultVersionList(McVersionCardType.API) = Sort(ResultVersionList(McVersionCardType.API),
Function(Left As McVersion, Right As McVersion)
@@ -1417,6 +1442,8 @@ OnLoaded:
Else
If Left.Version.HasFabric Xor Right.Version.HasFabric Then
Return Left.Version.HasFabric
+ ElseIf Left.Version.HasNeoForge Xor Right.Version.HasNeoForge Then
+ Return Left.Version.HasNeoForge
ElseIf Left.Version.HasForge Xor Right.Version.HasForge Then
Return Left.Version.HasForge
ElseIf Not Left.Version.SortCode <> Right.Version.SortCode Then
@@ -1649,7 +1676,7 @@ OnLoaded:
Return _Url
End Get
Set(value As String)
- '孤儿 Forge 作者喜欢把没有的 URL 写个空字符串
+ '孤儿 Forge 作者喜欢把没有 URL 的写个空字符串
_Url = If(String.IsNullOrWhiteSpace(value), Nothing, value)
End Set
End Property
@@ -1666,15 +1693,6 @@ OnLoaded:
End Get
End Property
'''
- ''' 原 Json 中 Name 项最后一部分的版本号。
- '''
- Public ReadOnly Property Version As String
- Get
- Dim Splited = OriginalName.Split(":")
- Return Splited(Splited.Count - 1)
- End Get
- End Property
- '''
''' 原 Json 中的 Name 项。
'''
Public OriginalName As String
@@ -1755,7 +1773,7 @@ OnLoaded:
'根据 Inherit 获取最深层版本
Dim OriginalVersion As McVersion = Version
'1.17+ 的 Forge 不寻找 Inherit
- If Not (Version.Version.HasForge AndAlso Version.Version.McCodeMain >= 17) Then
+ If Not ((Version.Version.HasForge OrElse Version.Version.HasNeoForge) AndAlso Version.Version.McCodeMain >= 17) Then
Do Until OriginalVersion.InheritVersion = ""
If OriginalVersion.InheritVersion = OriginalVersion.Name Then Exit Do
OriginalVersion = New McVersion(PathMcFolder & "versions\" & OriginalVersion.InheritVersion & "\")
@@ -1840,13 +1858,14 @@ OnLoaded:
Try
If Library("downloads") IsNot Nothing AndAlso Library("downloads")("artifact") IsNot Nothing Then
BasicArray.Add(New McLibToken With {
- .IsJumpLoader = IsJumpLoader,
- .OriginalName = Library("name"),
- .Url = If(RootUrl, Library("downloads")("artifact")("url")),
- .LocalPath = If(Library("downloads")("artifact")("path") Is Nothing, McLibGet(Library("name"), CustomMcFolder:=CustomMcFolder), CustomMcFolder & "libraries\" & Library("downloads")("artifact")("path").ToString.Replace("/", "\")),
- .Size = Val(Library("downloads")("artifact")("size").ToString),
- .IsNatives = False,
- .SHA1 = Library("downloads")("artifact")("sha1")?.ToString})
+ .IsJumpLoader = IsJumpLoader,
+ .OriginalName = Library("name"),
+ .Url = If(RootUrl, Library("downloads")("artifact")("url")),
+ .LocalPath = If(Library("downloads")("artifact")("path") Is Nothing, McLibGet(Library("name"),
+ CustomMcFolder:=CustomMcFolder), CustomMcFolder & "libraries\" & Library("downloads")("artifact")("path").ToString.Replace("/", "\")),
+ .Size = Val(Library("downloads")("artifact")("size").ToString),
+ .IsNatives = False,
+ .SHA1 = Library("downloads")("artifact")("sha1")?.ToString})
Else
BasicArray.Add(New McLibToken With {.IsJumpLoader = IsJumpLoader, .OriginalName = Library("name"), .Url = RootUrl, .LocalPath = LocalPath, .Size = 0, .IsNatives = False, .SHA1 = Nothing})
End If
@@ -1880,15 +1899,25 @@ OnLoaded:
'去重
Dim ResultArray As New Dictionary(Of String, McLibToken)
+ Dim GetVersion =
+ Function(Token As McLibToken) As String
+ '测试例:
+ 'D:\Minecraft\test\libraries\net\neoforged\mergetool\2.0.0\mergetool-2.0.0-api.jar
+ 'D:\Minecraft\test\libraries\org\apache\commons\commons-collections4\4.2\commons-collections4-4.2.jar
+ 'D:\Minecraft\test\libraries\com\google\guava\guava\31.1-jre\guava-31.1-jre.jar
+ Return GetFolderNameFromPath(GetPathFromFullPath(Token.LocalPath))
+ End Function
For i = 0 To BasicArray.Count - 1
Dim Key As String = BasicArray(i).Name & BasicArray(i).IsNatives.ToString & BasicArray(i).IsJumpLoader.ToString
If ResultArray.ContainsKey(Key) Then
- If BasicArray(i).Version <> ResultArray(Key).Version AndAlso KeepSameNameDifferentVersionResult Then
- Log($"[Minecraft] 发现疑似重复的支持库:{BasicArray(i)} 与 {ResultArray(Key)}")
+ Dim BasicArrayVersion As String = GetVersion(BasicArray(i))
+ Dim ResultArrayVersion As String = GetVersion(ResultArray(Key))
+ If BasicArrayVersion <> ResultArrayVersion AndAlso KeepSameNameDifferentVersionResult Then
+ Log($"[Minecraft] 发现疑似重复的支持库:{BasicArray(i)} ({BasicArrayVersion}) 与 {ResultArray(Key)} ({ResultArrayVersion})")
ResultArray.Add(Key & GetUuid(), BasicArray(i))
Else
- Log($"[Minecraft] 发现重复的支持库:{BasicArray(i)} 与 {ResultArray(Key)},已忽略其中之一")
- If VersionSortBoolean(BasicArray(i).Version, ResultArray(Key).Version) Then
+ Log($"[Minecraft] 发现重复的支持库:{BasicArray(i)} ({BasicArrayVersion}) 与 {ResultArray(Key)} ({ResultArrayVersion}),已忽略其中之一")
+ If VersionSortBoolean(BasicArrayVersion, ResultArrayVersion) Then
ResultArray(Key) = BasicArray(i)
End If
End If
@@ -1948,6 +1977,7 @@ OnLoaded:
End If
End If
End If
+
'Authlib-Injector 文件
If Setup.Get("VersionServerLogin", Version:=Version) = 4 OrElse
(PageLinkHiper.HiperState = LoadState.Finished AndAlso Setup.Get("LoginType") = McLoginType.Legacy) Then 'HiPer 登录转接
@@ -1997,8 +2027,14 @@ OnLoaded:
If Token.Url IsNot Nothing Then
'获取 Url 的真实地址
Urls.Add(Token.Url)
- If Token.Url.Contains("launcher.mojang.com/v1/objects") Then Urls = DlSourceLauncherOrMetaGet(Token.Url).ToList() 'Mappings
- If Token.Url.Contains("maven") Then Urls.Insert(0, Token.Url.Replace(Mid(Token.Url, 1, Token.Url.IndexOfF("maven")), "https://bmclapi2.bangbang93.com/").Replace("maven.fabricmc.net", "maven").Replace("maven.minecraftforge.net", "maven"))
+ If Token.Url.Contains("launcher.mojang.com/v1/objects") OrElse Token.Url.Contains("client.txt") OrElse
+ Token.Url.Contains(".tsrg") Then
+ Urls.AddRange(DlSourceLauncherOrMetaGet(Token.Url).ToList()) 'Mappings(#4425)
+ End If
+ If Token.Url.Contains("maven") Then
+ Urls.Insert(0, Token.Url.Replace(Mid(Token.Url, 1, Token.Url.IndexOfF("maven")), "https://bmclapi2.bangbang93.com/").
+ Replace("maven.fabricmc.net", "maven").Replace("maven.minecraftforge.net", "maven").Replace("maven.neoforged.net/releases", "maven"))
+ End If
End If
If Token.LocalPath.Contains("transformer-discovery-service") Then
'Transformer 文件释放
@@ -2015,7 +2051,7 @@ OnLoaded:
'普通文件
Urls.AddRange(DlSourceLibraryGet("https://libraries.minecraft.net" & Token.LocalPath.Replace(If(Token.IsJumpLoader, JumpLoaderFolder, CustomMcFolder) & "libraries", "").Replace("\", "/")))
End If
- Result.Add(New NetFile(Urls.Distinct.ToArray, Token.LocalPath, Checker))
+ Result.Add(New NetFile(Urls.Distinct, Token.LocalPath, Checker))
Next
'去重并返回
Return Result.Distinct(Function(a, b) a.LocalPath = b.LocalPath)
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb
index 348d3cb..f21c764 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb
@@ -887,7 +887,7 @@ Finished:
ModList.Add(ModEntry)
'读取 Comp 缓存
If ModEntry.State = McMod.McModState.Unavaliable Then Continue For
- Dim CacheKey = ModEntry.ModrinthHash & PageVersionLeft.Version.Version.McName
+ Dim CacheKey = ModEntry.ModrinthHash & PageVersionLeft.Version.Version.McName & GetTargetModLoaders().Join("")
If Cache.ContainsKey(CacheKey) Then
ModEntry.FromJson(Cache(CacheKey))
'如果缓存中的信息在 6 小时以内更新过,则无需重新获取
@@ -923,20 +923,15 @@ Finished:
Throw
End Try
End Sub
-
'联网加载 Mod 详情
- Private Const LocalModCacheVersion As Integer = 4
+ Private Const LocalModCacheVersion As Integer = 6
Public McModDetailLoader As New LoaderTask(Of KeyValuePair(Of List(Of McMod), JObject), Integer)("Mod List Detail Loader", AddressOf McModDetailLoad)
Private Sub McModDetailLoad(Loader As LoaderTask(Of KeyValuePair(Of List(Of McMod), JObject), Integer))
Dim Mods As List(Of McMod) = Loader.Input.Key
Dim Cache As JObject = Loader.Input.Value
'获取作为检查目标的加载器和版本
Dim TargetMcVersion As McVersionInfo = PageVersionLeft.Version.Version
- Dim ModLoaders As New List(Of CompModLoaderType)
- If TargetMcVersion.HasForge Then ModLoaders.Add(CompModLoaderType.Forge)
- If TargetMcVersion.HasFabric Then ModLoaders.Add(CompModLoaderType.Fabric)
- If TargetMcVersion.HasLiteLoader Then ModLoaders.Add(CompModLoaderType.LiteLoader)
- If Not ModLoaders.Any() Then ModLoaders.AddRange({CompModLoaderType.Forge, CompModLoaderType.Fabric, CompModLoaderType.LiteLoader, CompModLoaderType.Quilt})
+ Dim ModLoaders = GetTargetModLoaders()
Dim McVersion = TargetMcVersion.McName
'暂不向下扩展检查的 MC 小版本
'例如:Mod 在更新 1.16.5 后,对早期的 1.16.2 版本发布了修补补丁,这会导致 PCL 将 1.16.5 版本的 Mod 降级到 1.16.2
@@ -957,7 +952,7 @@ Finished:
Try
'步骤 1:获取 Hash 与对应的工程 ID
Dim ModrinthHashes = Mods.Select(Function(m) m.ModrinthHash).ToList()
- Dim ModrinthVersion = CType(GetJson(NetRequestRetry("https://api.modrinth.com/v2/version_files", "POST",
+ Dim ModrinthVersion = CType(GetJson(DlModRequest("https://api.modrinth.com/v2/version_files", "POST",
$"{{""hashes"": [""{ModrinthHashes.Join(""",""")}""], ""algorithm"": ""sha1""}}", "application/json")), JObject)
Log($"[Mod] 从 Modrinth 获取到 {ModrinthVersion.Count} 个本地 Mod 的对应信息")
'步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系
@@ -978,7 +973,7 @@ Finished:
Log($"[Mod] 需要从 Modrinth 获取 {ModrinthMapping.Count} 个本地 Mod 的工程信息")
'步骤 3:获取工程信息
If Not ModrinthMapping.Any() Then Exit Sub
- Dim ModrinthProject = CType(GetJson(NetRequestRetry(
+ Dim ModrinthProject = CType(GetJson(DlModRequest(
$"https://api.modrinth.com/v2/projects?ids=[""{ModrinthMapping.Keys.Join(""",""")}""]",
"GET", "", "application/json")), JArray)
For Each ProjectJson In ModrinthProject
@@ -990,7 +985,7 @@ Finished:
Next
Log($"[Mod] 已从 Modrinth 获取本地 Mod 信息,继续获取更新信息")
'步骤 4:获取更新信息
- Dim ModrinthUpdate = CType(GetJson(NetRequestRetry("https://api.modrinth.com/v2/version_files/update", "POST",
+ Dim ModrinthUpdate = CType(GetJson(DlModRequest("https://api.modrinth.com/v2/version_files/update", "POST",
$"{{""hashes"": [""{ModrinthMapping.SelectMany(Function(l) l.Value.Select(Function(m) m.ModrinthHash)).Join(""",""")}""], ""algorithm"": ""sha1"",
""loaders"": [""{ModLoaders.Join(""",""").ToLower}""],""game_versions"": [""{McVersion}""]}}", "application/json")), JObject)
For Each Entry In Mods
@@ -1027,7 +1022,7 @@ Finished:
CurseForgeHashes.Add(Entry.CurseForgeHash)
If Loader.IsAbortedWithThread(MainThread) Then Exit Sub
Next
- Dim CurseForgeRaw = CType(CType(GetJson(NetRequestRetry("https://api.curseforge.com/v1/fingerprints/432/", "POST",
+ Dim CurseForgeRaw = CType(CType(GetJson(DlModRequest("https://api.curseforge.com/v1/fingerprints/432", "POST",
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")), JObject)("data")("exactMatches"), JContainer)
Log($"[Mod] 从 CurseForge 获取到 {CurseForgeRaw.Count} 个本地 Mod 的对应信息")
'步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系
@@ -1050,12 +1045,12 @@ Finished:
Log($"[Mod] 需要从 CurseForge 获取 {CurseForgeMapping.Count} 个本地 Mod 的工程信息")
'步骤 3:获取工程信息
If Not CurseForgeMapping.Any() Then Exit Sub
- Dim CurseForgeProject = CType(GetJson(NetRequestRetry("https://api.curseforge.com/v1/mods", "POST",
+ Dim CurseForgeProject = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods", "POST",
$"{{""modIds"": [{CurseForgeMapping.Keys.Join(",")}]}}", "application/json")), JObject)("data")
Dim UpdateFileIds As New Dictionary(Of Integer, List(Of McMod)) 'FileId -> 本地 Mod 文件列表
Dim FileIdToProjectSlug As New Dictionary(Of Integer, String)
For Each ProjectJson In CurseForgeProject
- If Not ProjectJson("isAvailable").ToObject(Of Boolean) Then Continue For
+ If ProjectJson("isAvailable") IsNot Nothing AndAlso Not ProjectJson("isAvailable").ToObject(Of Boolean) Then Continue For
'设置 Entry 中的工程信息
Dim Project As New CompProject(ProjectJson)
For Each Entry In CurseForgeMapping(Project.Id) '倒查防止 CurseForge 返回的内容有漏
@@ -1071,7 +1066,8 @@ Finished:
Dim NewestVersion As String = Nothing
Dim NewestFileIds As New List(Of Integer)
For Each IndexEntry In ProjectJson("latestFilesIndexes")
- If ModLoaders.Single <> IndexEntry("modLoader")?.ToObject(Of Integer) Then Continue For 'ModLoader 唯一且匹配
+ If IndexEntry("modLoader") Is Nothing OrElse Not IndexEntry("modLoader").HasValues OrElse '镜像源会返回一个值为 null 的键
+ ModLoaders.Single <> IndexEntry("modLoader").ToObject(Of Integer) Then Continue For 'ModLoader 唯一且匹配
Dim IndexVersion As String = IndexEntry("gameVersion")
If McVersion <> IndexVersion Then Continue For 'MC 版本匹配
'由于 latestFilesIndexes 是按时间从新到老排序的,所以只需取第一个;如果需要检查多个 releaseType 下的文件,将 > -1 改为 = 1,但这应当并不会获取到更新的文件
@@ -1092,7 +1088,7 @@ Finished:
Log($"[Mod] 已从 CurseForge 获取本地 Mod 信息,需要获取 {UpdateFileIds.Count} 个用于检查更新的文件信息")
'步骤 4:获取更新文件信息
If Not UpdateFileIds.Any() Then Exit Sub
- Dim CurseForgeFiles = CType(GetJson(NetRequestRetry("https://api.curseforge.com/v1/mods/files", "POST",
+ Dim CurseForgeFiles = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST",
$"{{""fileIds"": [{UpdateFileIds.Keys.Join(",")}]}}", "application/json")), JObject)("data")
Dim UpdateFiles As New Dictionary(Of McMod, CompFile)
For Each FileJson In CurseForgeFiles
@@ -1136,10 +1132,21 @@ Finished:
If Not Mods.Any() Then Exit Sub
For Each Entry In Mods 'TODO: Bookshelf 的 Logo 会在两个网站间横跳
Entry.CompLoaded = SucceedThreadCount = 2
- Cache(Entry.ModrinthHash & McVersion) = Entry.ToJson()
+ Cache(Entry.ModrinthHash & McVersion & ModLoaders.Join("")) = Entry.ToJson()
Next
WriteFile(PathTemp & "Cache\LocalMod.json", Cache.ToString(If(ModeDebug, Newtonsoft.Json.Formatting.Indented, Newtonsoft.Json.Formatting.None)))
+ '刷新下边栏(#4377)
+ RunInUi(Sub() FrmVersionMod?.RefreshBottomBar())
End Sub
+ Private Function GetTargetModLoaders() As List(Of CompModLoaderType)
+ Dim ModLoaders As New List(Of CompModLoaderType)
+ If PageVersionLeft.Version.Version.HasForge Then ModLoaders.Add(CompModLoaderType.Forge)
+ If PageVersionLeft.Version.Version.HasNeoForge Then ModLoaders.Add(CompModLoaderType.NeoForge)
+ If PageVersionLeft.Version.Version.HasFabric Then ModLoaders.Add(CompModLoaderType.Fabric)
+ If PageVersionLeft.Version.Version.HasLiteLoader Then ModLoaders.Add(CompModLoaderType.LiteLoader)
+ If Not ModLoaders.Any() Then ModLoaders.AddRange({CompModLoaderType.Forge, CompModLoaderType.NeoForge, CompModLoaderType.Fabric, CompModLoaderType.LiteLoader, CompModLoaderType.Quilt})
+ Return ModLoaders
+ End Function
#If DEBUG Then
'''
@@ -1271,4 +1278,4 @@ Finished:
End Function
#End If
-End Module
+End Module
\ No newline at end of file
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb
index bcd878c..27b9f87 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb
@@ -12,9 +12,10 @@ Public Module ModModpack
RunInThread(Sub() ModpackInstall(File))
End Sub
'''
- ''' 安装一个给定的整合包文件,返回是否安装成功。必须在工作线程执行。
+ ''' 安装一个给定的整合包文件,返回启动的安装加载器,如果未成功启动则返回 Nothing。
+ ''' 必须在工作线程执行。
'''
- Public Function ModpackInstall(File As String, Optional VersionName As String = Nothing, Optional ShowHint As Boolean = True, Optional Logo As String = Nothing) As Boolean
+ Public Function ModpackInstall(File As String, Optional VersionName As String = Nothing, Optional ShowHint As Boolean = True, Optional Logo As String = Nothing) As LoaderCombo(Of String)
Log("[ModPack] 整合包安装请求:" & If(File, "null"))
Dim Archive As ZipArchive = Nothing
Dim ArchiveBaseFolder As String = ""
@@ -25,6 +26,7 @@ Public Module ModModpack
Archive = New ZipArchive(New FileStream(File, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
'从根目录判断整合包类型
If Archive.GetEntry("mcbbs.packmeta") IsNot Nothing Then PackType = 3 : Exit Try 'MCBBS 整合包(优先于 manifest.json 判断)
+ If Archive.GetEntry("mmc-pack.json") IsNot Nothing Then PackType = 2 : Exit Try 'MMC 整合包(优先于 manifest.json 判断,#4194)
If Archive.GetEntry("modrinth.index.json") IsNot Nothing Then PackType = 4 : Exit Try 'Modrinth 整合包
If Archive.GetEntry("manifest.json") IsNot Nothing Then
Dim Json As JObject = GetJson(ReadFile(Archive.GetEntry("manifest.json").Open, Encoding.UTF8))
@@ -35,7 +37,6 @@ Public Module ModModpack
End If
End If
If Archive.GetEntry("modpack.json") IsNot Nothing Then PackType = 1 : Exit Try 'HMCL 整合包
- If Archive.GetEntry("mmc-pack.json") IsNot Nothing Then PackType = 2 : Exit Try 'MMC 整合包
'从一级目录判断整合包类型
For Each Entry In Archive.Entries
Dim FullNames As String() = Entry.FullName.Split("/")
@@ -45,6 +46,7 @@ Public Module ModModpack
If FullNames.Count <> 2 Then Continue For
'判断是否为关键文件
If FullNames(1) = "mcbbs.packmeta" Then PackType = 3 : Exit Try 'MCBBS 整合包(优先于 manifest.json 判断)
+ If FullNames(1) = "mmc-pack.json" Then PackType = 2 : Exit Try 'MMC 整合包(优先于 manifest.json 判断,#4194)
If FullNames(1) = "modrinth.index.json" Then PackType = 4 : Exit Try 'Modrinth 整合包
If FullNames(1) = "manifest.json" Then
Dim Json As JObject = GetJson(ReadFile(Entry.Open, Encoding.UTF8))
@@ -55,54 +57,52 @@ Public Module ModModpack
End If
End If
If FullNames(1) = "modpack.json" Then PackType = 1 : Exit Try 'HMCL 整合包
- If FullNames(1) = "mmc-pack.json" Then PackType = 2 : Exit Try 'MMC 整合包
Next
Catch ex As Exception
If GetExceptionDetail(ex, True).Contains("Error.WinIOError") Then
Log(ex, "打开整合包文件失败", If(ShowHint, LogLevel.Hint, LogLevel.Normal))
- Return False
+ Return Nothing
ElseIf File.EndsWithF(".rar", True) Then
Log(ex, "PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试", If(ShowHint, LogLevel.Hint, LogLevel.Normal))
- Return False
+ Return Nothing
Else
Log(ex, "打开整合包文件失败,文件可能损坏或为不支持的压缩包格式", If(ShowHint, LogLevel.Hint, LogLevel.Normal))
- Return False
+ Return Nothing
End If
End Try
'执行对应的安装方法
Select Case PackType
Case 0
Log("[ModPack] 整合包种类:CurseForge")
- InstallPackCurseForge(File, Archive, ArchiveBaseFolder, VersionName, Logo)
+ Return InstallPackCurseForge(File, Archive, ArchiveBaseFolder, VersionName, Logo)
Case 1
Log("[ModPack] 整合包种类:HMCL")
- InstallPackHMCL(File, Archive, ArchiveBaseFolder)
+ Return InstallPackHMCL(File, Archive, ArchiveBaseFolder)
Case 2
Log("[ModPack] 整合包种类:MMC")
- InstallPackMMC(File, Archive, ArchiveBaseFolder)
+ Return InstallPackMMC(File, Archive, ArchiveBaseFolder)
Case 3
Log("[ModPack] 整合包种类:MCBBS")
- InstallPackMCBBS(File, Archive, ArchiveBaseFolder)
+ Return InstallPackMCBBS(File, Archive, ArchiveBaseFolder, VersionName)
Case 4
Log("[ModPack] 整合包种类:Modrinth")
- InstallPackModrinth(File, Archive, ArchiveBaseFolder, VersionName, Logo)
+ Return InstallPackModrinth(File, Archive, ArchiveBaseFolder, VersionName, Logo)
Case 9
Log("[ModPack] 整合包种类:压缩包")
Archive.Dispose()
Archive = Nothing
- InstallPackCompress(File, ArchiveBaseFolder)
+ Return InstallPackCompress(File, ArchiveBaseFolder)
Case Else
If ShowHint Then
Hint("未能识别该整合包的种类,无法安装!", HintType.Critical)
Else
Log("[ModPack] 未能识别该整合包的种类,无法安装!")
End If
- Return False
+ Return Nothing
End Select
- Return True
Catch ex As Exception
Log(ex, "准备安装整合包失败", LogLevel.Feedback)
- Return False
+ Return Nothing
Finally
If Archive IsNot Nothing Then Archive.Dispose()
End Try
@@ -159,7 +159,8 @@ Retry:
#Region "不同类型整合包的安装方法"
'CurseForge
- Private Sub InstallPackCurseForge(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String, Optional VersionName As String = Nothing, Optional Logo As String = Nothing)
+ Private Function InstallPackCurseForge(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String,
+ Optional VersionName As String = Nothing, Optional Logo As String = Nothing) As LoaderCombo(Of String)
'读取 Json 文件
Dim Json As JObject
@@ -167,22 +168,23 @@ Retry:
Json = GetJson(ReadFile(Archive.GetEntry(ArchiveBaseFolder & "manifest.json").Open))
If Json("minecraft") Is Nothing OrElse Json("minecraft")("version") Is Nothing Then Throw New Exception("整合包未提供 Minecraft 版本信息")
Catch ex As Exception
- Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
- Exit Sub
+ Log(ex, "CurseForge 整合包安装信息存在问题", LogLevel.Hint)
+ Return Nothing
End Try
'获取版本名
Dim ShowRibble As Boolean = VersionName Is Nothing
If VersionName Is Nothing Then
- Dim PackName As String = If(Json("name"), "")
+ VersionName = If(Json("name"), "")
Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
- If Validate.Validate(PackName) <> "" Then PackName = ""
- VersionName = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
- If String.IsNullOrEmpty(VersionName) Then Exit Sub
+ If Validate.Validate(VersionName) <> "" Then VersionName = ""
+ If VersionName = "" Then VersionName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
+ If String.IsNullOrEmpty(VersionName) Then Return Nothing
End If
'获取 Mod API 版本信息
Dim ForgeVersion As String = Nothing
+ Dim NeoForgeVersion As String = Nothing
Dim FabricVersion As String = Nothing
For Each Entry In If(Json("minecraft")("modLoaders"), {})
Dim Id As String = If(Entry("id"), "").ToString.ToLower
@@ -190,20 +192,29 @@ Retry:
'Forge 指定
If Id.Contains("recommended") Then
Log("[ModPack] 该整合包版本过老,已不支持进行安装!", LogLevel.Hint)
- Exit Sub
+ Return Nothing
End If
Try
Log("[ModPack] 整合包 Forge 版本:" & Id)
- ForgeVersion = Id.Split("-")(1)
+ ForgeVersion = Id.Replace("forge-", "")
Exit For
Catch ex As Exception
Log(ex, "读取整合包 Forge 版本失败:" & Id)
End Try
+ ElseIf Id.StartsWithF("neoforge-") Then
+ 'NeoForge 指定
+ Try
+ Log("[ModPack] 整合包 NeoForge 版本:" & Id)
+ NeoForgeVersion = Id.Replace("neoforge-", "")
+ Exit For
+ Catch ex As Exception
+ Log(ex, "读取整合包 NeoForge 版本失败:" & Id)
+ End Try
ElseIf Id.StartsWithF("fabric-") Then
'Fabric 指定
Try
Log("[ModPack] 整合包 Fabric 版本:" & Id)
- FabricVersion = Id.Split("-")(1)
+ FabricVersion = Id.Replace("fabric-", "")
Exit For
Catch ex As Exception
Log(ex, "读取整合包 Fabric 版本失败:" & Id)
@@ -271,19 +282,23 @@ Retry:
'建立 CompFile
Dim File As New CompFile(ModJson, CompType.Mod)
If Not File.Available Then Continue For
- '根据 modules 和文件名后缀判断是资源包还是 Mod
- Dim IsResourcePack As Boolean
+ '根据 modules 和文件名后缀判断资源类型
+ Dim TargetFolder As String
If ModJson("modules").Any Then 'modules 可能返回 null(#1006)
Dim ModuleNames = CType(ModJson("modules"), JArray).Select(Function(l) l("name").ToString).ToList
- IsResourcePack =
- (Not ModuleNames.Contains("META-INF")) AndAlso (Not ModuleNames.Contains("mcmod.info")) AndAlso '不包含 META-INF 或 mcmod.info
- ModuleNames.Contains("pack.mcmeta") AndAlso '包含 pack.mcmeta
- (Not File.FileName.EndsWithF(".jar", True)) '文件后缀不是 .jar
+ If ModuleNames.Contains("META-INF") OrElse ModuleNames.Contains("mcmod.info") OrElse
+ File.FileName.EndsWithF(".jar", True) Then
+ TargetFolder = "mods"
+ ElseIf ModuleNames.Contains("pack.mcmeta") Then
+ TargetFolder = "resourcepacks"
+ Else
+ TargetFolder = "shaderpacks"
+ End If
Else
- IsResourcePack = False
+ TargetFolder = "mods"
End If
'实际的添加
- FileList.Add(Id, File.ToNetFile($"{PathMcFolder}versions\{VersionName}\{If(IsResourcePack, "resourcepacks", "mods")}\"))
+ FileList.Add(Id, File.ToNetFile($"{PathMcFolder}versions\{VersionName}\{TargetFolder}\"))
Task.Progress += 1 / (1 + ModList.Count)
Next
Task.Output = FileList.Values.ToList
@@ -301,10 +316,11 @@ Retry:
.TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\",
.MinecraftName = Json("minecraft")("version").ToString,
.ForgeVersion = ForgeVersion,
+ .NeoForgeVersion = NeoForgeVersion,
.FabricVersion = FabricVersion
}
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
- If MergeLoaders Is Nothing Then Exit Sub
+ If MergeLoaders Is Nothing Then Return Nothing
'构造 Libraries 加载器
Dim LoadersLib As New List(Of LoaderBase)
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
@@ -335,14 +351,10 @@ Retry:
'重复任务检查
Dim LoaderName As String = "CurseForge 整合包安装:" & VersionName & " "
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = LoaderName Then
- Hint("该整合包正在安装中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
+ Hint("该整合包正在安装中!", HintType.Critical)
+ Return Nothing
+ End If
'启动
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
@@ -350,11 +362,11 @@ Retry:
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
If ShowRibble Then FrmMain.BtnExtraDownload.Ribble()
-
- End Sub
+ Return Loader
+ End Function
'Modrinth
- Private Sub InstallPackModrinth(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String, Optional VersionName As String = Nothing, Optional Logo As String = Nothing)
+ Private Function InstallPackModrinth(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String, Optional VersionName As String = Nothing, Optional Logo As String = Nothing) As LoaderCombo(Of String)
'读取 Json 文件
Dim Json As JObject
@@ -363,11 +375,12 @@ Retry:
If Json("dependencies") Is Nothing OrElse Json("dependencies")("minecraft") Is Nothing Then Throw New Exception("整合包未提供 Minecraft 版本信息")
Catch ex As Exception
Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
- Exit Sub
+ Return Nothing
End Try
'获取 Mod API 版本信息
Dim MinecraftVersion As String = Nothing
Dim ForgeVersion As String = Nothing
+ Dim NeoForgeVersion As String = Nothing
Dim FabricVersion As String = Nothing
For Each Entry As JProperty In If(Json("dependencies"), {})
Select Case Entry.Name.ToLower
@@ -376,47 +389,50 @@ Retry:
Case "forge" 'eg. 14.23.5.2859 / 1.19-41.1.0
ForgeVersion = Entry.Value.ToString
Log("[ModPack] 整合包 Forge 版本:" & ForgeVersion)
+ Case "neoforge", "neo-forge" 'eg. 20.6.98-beta
+ NeoForgeVersion = Entry.Value.ToString
+ Log("[ModPack] 整合包 NeoForge 版本:" & NeoForgeVersion)
Case "fabric-loader" 'eg. 0.14.14
FabricVersion = Entry.Value.ToString
Log("[ModPack] 整合包 Fabric 版本:" & FabricVersion)
Case "quilt-loader" 'eg. 1.0.0
Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Critical)
- Exit Sub
+ Return Nothing
Case Else
Hint($"无法安装整合包,其中出现了未知的 Mod 加载器 {Entry.Value}!", HintType.Critical)
- Exit Sub
+ Return Nothing
End Select
Next
'获取版本名
Dim ShowRibble As Boolean = VersionName Is Nothing
If VersionName Is Nothing Then
- Dim PackName As String = If(Json("name"), "")
+ VersionName = If(Json("name"), "")
Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
- If Validate.Validate(PackName) <> "" Then PackName = ""
- VersionName = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
- If String.IsNullOrEmpty(VersionName) Then Exit Sub
+ If Validate.Validate(VersionName) <> "" Then VersionName = ""
+ If VersionName = "" Then VersionName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
+ If String.IsNullOrEmpty(VersionName) Then Return Nothing
End If
'解压和配置文件
Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
Dim InstallLoaders As New List(Of LoaderBase)
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
- Sub(Task As LoaderTask(Of String, Integer))
- UnpackFiles(InstallTemp, FileAddress, Task)
- Task.Progress = 0.5
- '复制 overrides 文件夹和 client-overrides 文件夹
- If Directory.Exists(InstallTemp & ArchiveBaseFolder & "overrides") Then
- CopyDirectory(InstallTemp & ArchiveBaseFolder & "overrides", PathMcFolder & "versions\" & VersionName)
- Else
- Log("[ModPack] 整合包中未找到 override 目录,已跳过")
- End If
- Task.Progress = 0.8
- If Directory.Exists(InstallTemp & ArchiveBaseFolder & "client-overrides") Then
- CopyDirectory(InstallTemp & ArchiveBaseFolder & "client-overrides", PathMcFolder & "versions\" & VersionName)
- End If
- Task.Progress = 0.9
- '开启版本隔离
- WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
- End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
+ Sub(Task As LoaderTask(Of String, Integer))
+ UnpackFiles(InstallTemp, FileAddress, Task)
+ Task.Progress = 0.5
+ '复制 overrides 文件夹和 client-overrides 文件夹
+ If Directory.Exists(InstallTemp & ArchiveBaseFolder & "overrides") Then
+ CopyDirectory(InstallTemp & ArchiveBaseFolder & "overrides", PathMcFolder & "versions\" & VersionName)
+ Else
+ Log("[ModPack] 整合包中未找到 override 目录,已跳过")
+ End If
+ Task.Progress = 0.8
+ If Directory.Exists(InstallTemp & ArchiveBaseFolder & "client-overrides") Then
+ CopyDirectory(InstallTemp & ArchiveBaseFolder & "client-overrides", PathMcFolder & "versions\" & VersionName)
+ End If
+ Task.Progress = 0.9
+ '开启版本隔离
+ WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
+ End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
'获取下载文件列表
Dim FileList As New List(Of NetFile)
For Each File In If(Json("files"), {})
@@ -433,8 +449,10 @@ Retry:
End Select
End If
'添加下载文件
- FileList.Add(New NetFile(File("downloads").Select(Function(t) t.ToString.Replace("://edge.forgecdn", "://media.forgecdn")).ToArray, '修复 #2390
- PathMcFolder & "versions\" & VersionName & "\" & File("path").ToString,
+ Dim Urls = File("downloads").Select(Function(t) t.ToString.Replace("://edge.forgecdn", "://media.forgecdn")).ToList
+ Urls.AddRange(Urls.Select(Function(u) DlSourceModGet(u)).ToList)
+ Urls = Urls.Distinct.ToList()
+ FileList.Add(New NetFile(Urls, PathMcFolder & "versions\" & VersionName & "\" & File("path").ToString,
New FileChecker(ActualSize:=File("fileSize").ToObject(Of Long), Hash:=File("hashes")("sha1").ToString), True))
Next
If FileList.Any Then
@@ -447,10 +465,11 @@ Retry:
.TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\",
.MinecraftName = MinecraftVersion,
.ForgeVersion = ForgeVersion,
+ .NeoForgeVersion = NeoForgeVersion,
.FabricVersion = FabricVersion
}
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
- If MergeLoaders Is Nothing Then Exit Sub
+ If MergeLoaders Is Nothing Then Return Nothing
'构造 Libraries 加载器
Dim LoadersLib As New List(Of LoaderBase)
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
@@ -481,14 +500,10 @@ Retry:
'重复任务检查
Dim LoaderName As String = "Modrinth 整合包安装:" & VersionName & " "
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = LoaderName Then
- Hint("该整合包正在安装中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
+ Hint("该整合包正在安装中!", HintType.Critical)
+ Return Nothing
+ End If
'启动
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
@@ -496,25 +511,26 @@ Retry:
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
If ShowRibble Then FrmMain.BtnExtraDownload.Ribble()
+ Return Loader
- End Sub
+ End Function
'HMCL
- Private Sub InstallPackHMCL(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String)
+ Private Function InstallPackHMCL(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String) As LoaderCombo(Of String)
'读取 Json 文件
Dim Json As JObject
Try
Json = GetJson(ReadFile(Archive.GetEntry(ArchiveBaseFolder & "modpack.json").Open, Encoding.UTF8))
Catch ex As Exception
Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
- Exit Sub
+ Return Nothing
End Try
'获取版本名
- Dim PackName As String = If(Json("name"), "")
+ Dim VersionName As String = If(Json("name"), "")
Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
- If Validate.Validate(PackName) <> "" Then PackName = ""
- Dim VersionName As String = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
- If VersionName Is Nothing Then Exit Sub
+ If Validate.Validate(VersionName) <> "" Then VersionName = ""
+ If VersionName = "" Then VersionName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
+ If String.IsNullOrEmpty(VersionName) Then Return Nothing
'解压与配置文件
Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
Dim InstallLoaders As New List(Of LoaderBase)
@@ -535,7 +551,7 @@ Retry:
'构造加载器
If Json("gameVersion") Is Nothing Then
Hint("该整合包未提供游戏版本信息,无法安装!", HintType.Critical)
- Exit Sub
+ Return Nothing
End If
Dim Request As New McInstallRequest With {
.TargetVersionName = VersionName,
@@ -543,7 +559,7 @@ Retry:
.MinecraftName = Json("gameVersion").ToString
}
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
- If MergeLoaders Is Nothing Then Exit Sub
+ If MergeLoaders Is Nothing Then Return Nothing
'构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
Dim LoadersLib As New List(Of LoaderBase)
LoadersLib.Add(New LoaderTask(Of String, String)("重命名版本 Json(副加载器)",
@@ -571,14 +587,10 @@ Retry:
'重复任务检查
Dim LoaderName As String = "HMCL 整合包安装:" & VersionName & " "
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = LoaderName Then
- Hint("该整合包正在安装中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
+ Hint("该整合包正在安装中!", HintType.Critical)
+ Return Nothing
+ End If
'启动
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
@@ -587,10 +599,11 @@ Retry:
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
FrmMain.BtnExtraDownload.Ribble()
- End Sub
+ Return Loader
+ End Function
'MMC
- Private Sub InstallPackMMC(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String)
+ Private Function InstallPackMMC(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String) As LoaderCombo(Of String)
'读取 Json 文件
Dim PackJson As JObject, PackInstance As String
Try
@@ -598,14 +611,14 @@ Retry:
PackInstance = ReadFile(Archive.GetEntry(ArchiveBaseFolder & "instance.cfg").Open, Encoding.UTF8)
Catch ex As Exception
Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
- Exit Sub
+ Return Nothing
End Try
'获取版本名
- Dim PackName As String = If(RegexSeek(PackInstance, "(?<=\nname\=)[^\n]+"), "")
+ Dim VersionName As String = If(RegexSeek(PackInstance, "(?<=\nname\=)[^\n]+"), "")
Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
- If Validate.Validate(PackName) <> "" Then PackName = ""
- Dim VersionName As String = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
- If VersionName Is Nothing Then Exit Sub
+ If Validate.Validate(VersionName) <> "" Then VersionName = ""
+ If VersionName = "" Then VersionName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
+ If String.IsNullOrEmpty(VersionName) Then Return Nothing
'解压、配置设置文件
Dim InstallTemp As String = $"{PathTemp}PackInstall\{RandomInteger(0, 100000)}\"
Dim SetupFile As String = $"{PathMcFolder}versions\{VersionName}\PCL\Setup.ini"
@@ -665,7 +678,7 @@ Retry:
'构造版本安装请求
If PackJson("components") Is Nothing Then
Hint("该整合包未提供游戏版本信息,无法安装!", HintType.Critical)
- Exit Sub
+ Return Nothing
End If
Dim Request As New McInstallRequest With {.TargetVersionName = VersionName, .TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\"}
For Each Component In PackJson("components")
@@ -676,16 +689,18 @@ Retry:
Request.MinecraftName = Component("version")
Case "net.minecraftforge"
Request.ForgeVersion = Component("version")
+ Case "net.neoforged"
+ Request.NeoForgeVersion = Component("version")
Case "net.fabricmc.fabric-loader"
Request.FabricVersion = Component("version")
Case "org.quiltmc.quilt-loader" 'eg. 1.0.0
Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Critical)
- Exit Sub
+ Return Nothing
End Select
Next
'构造加载器
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
- If MergeLoaders Is Nothing Then Exit Sub
+ If MergeLoaders Is Nothing Then Return Nothing
'构造 Libraries 加载器
Dim LoadersLib As New List(Of LoaderBase)
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
@@ -698,14 +713,10 @@ Retry:
'重复任务检查
Dim LoaderName As String = "MMC 整合包安装:" & VersionName & " "
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = LoaderName Then
- Hint("该整合包正在安装中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
+ Hint("该整合包正在安装中!", HintType.Critical)
+ Return Nothing
+ End If
'启动
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
@@ -713,10 +724,12 @@ Retry:
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
FrmMain.BtnExtraDownload.Ribble()
- End Sub
+ Return Loader
+ End Function
'MCBBS
- Private Sub InstallPackMCBBS(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String)
+ Private Function InstallPackMCBBS(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String,
+ Optional VersionName As String = Nothing) As LoaderCombo(Of String)
'读取 Json 文件
Dim Json As JObject
Try
@@ -724,14 +737,17 @@ Retry:
Json = GetJson(ReadFile(Entry.Open, Encoding.UTF8))
Catch ex As Exception
Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
- Exit Sub
+ Return Nothing
End Try
'获取版本名
- Dim PackName As String = If(Json("name"), "")
- Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
- If Validate.Validate(PackName) <> "" Then PackName = ""
- Dim VersionName As String = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
- If VersionName Is Nothing Then Exit Sub
+ Dim ShowRibble As Boolean = VersionName Is Nothing
+ If VersionName Is Nothing Then
+ VersionName = If(Json("name"), "")
+ Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
+ If Validate.Validate(VersionName) <> "" Then VersionName = ""
+ If VersionName = "" Then VersionName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
+ If String.IsNullOrEmpty(VersionName) Then Return Nothing
+ End If
'解压与配置文件
Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
Dim InstallLoaders As New List(Of LoaderBase)
@@ -752,7 +768,7 @@ Retry:
'构造加载器
If Json("addons") Is Nothing Then
Hint("该整合包未提供游戏版本附加信息,无法安装!", HintType.Critical)
- Exit Sub
+ Return Nothing
End If
Dim Addons As New Dictionary(Of String, String)
For Each Entry In Json("addons")
@@ -760,11 +776,11 @@ Retry:
Next
If Not Addons.ContainsKey("game") Then
Hint("该整合包未提供游戏版本信息,无法安装!", HintType.Critical)
- Exit Sub
+ Return Nothing
End If
If Addons.ContainsKey("quilt") Then
Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Critical)
- Exit Sub
+ Return Nothing
End If
Dim Request As New McInstallRequest With {
.TargetVersionName = VersionName,
@@ -772,10 +788,11 @@ Retry:
.MinecraftName = Addons("game"),
.OptiFineVersion = If(Addons.ContainsKey("optifine"), Addons("optifine"), Nothing),
.ForgeVersion = If(Addons.ContainsKey("forge"), Addons("forge"), Nothing),
+ .NeoForgeVersion = If(Addons.ContainsKey("neoforge"), Addons("neoforge"), Nothing),
.FabricVersion = If(Addons.ContainsKey("fabric"), Addons("fabric"), Nothing)
}
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
- If MergeLoaders Is Nothing Then Exit Sub
+ If MergeLoaders Is Nothing Then Return Nothing
'构造 Libraries 加载器
Dim LoadersLib As New List(Of LoaderBase)
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
@@ -788,14 +805,10 @@ Retry:
'重复任务检查
Dim LoaderName As String = "MCBBS 整合包安装:" & VersionName & " "
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = LoaderName Then
- Hint("该整合包正在安装中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
+ Hint("该整合包正在安装中!", HintType.Critical)
+ Return Nothing
+ End If
'启动
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
@@ -803,28 +816,36 @@ Retry:
Loader.Start(Request.TargetVersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
- FrmMain.BtnExtraDownload.Ribble()
- End Sub
+ If ShowRibble Then FrmMain.BtnExtraDownload.Ribble()
+ Return Loader
+ End Function
'普通压缩包
- Private Sub InstallPackCompress(FileAddress As String, ArchiveBaseFolder As String)
+ Private Function InstallPackCompress(FileAddress As String, ArchiveBaseFolder As String) As LoaderCombo(Of String)
MyMsgBox("请在接下来打开的窗口中选择安装目标文件夹,它必须是一个空文件夹。", "安装提示", "继续", ForceWait:=True)
'获取解压路径
Dim TargetFolder As String = SelectFolder("选择安装目标(必须是一个空文件夹)")
- If String.IsNullOrEmpty(TargetFolder) Then Exit Sub
- If TargetFolder.Contains("!") OrElse TargetFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Critical) : Exit Sub
- If Directory.GetFileSystemEntries(TargetFolder).Length > 0 Then Hint("请选择一个空文件夹作为安装目标!", HintType.Critical) : Exit Sub
+ If String.IsNullOrEmpty(TargetFolder) Then Return Nothing
+ If TargetFolder.Contains("!") OrElse TargetFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Critical) : Return Nothing
+ If Directory.GetFileSystemEntries(TargetFolder).Length > 0 Then Hint("请选择一个空文件夹作为安装目标!", HintType.Critical) : Return Nothing
'要求显示名称
Dim NewName As String = MyMsgBoxInput("输入显示名称", "输入该文件夹在左边栏列表中显示的名称。", GetFolderNameFromPath(TargetFolder),
New ObjectModel.Collection(Of Validate) From {New ValidateNullOrWhiteSpace, New ValidateLength(1, 30), New ValidateExcept({">", "|"})})
- If String.IsNullOrWhiteSpace(NewName) Then Exit Sub
+ If String.IsNullOrWhiteSpace(NewName) Then Return Nothing
'解压
- Hint("正在解压压缩包……")
- UnpackFiles(TargetFolder, FileAddress, Nothing)
- '加入文件夹列表
- PageSelectLeft.AddFolder(TargetFolder, NewName, False)
- Hint("已加入游戏文件夹列表:" & NewName, HintType.Finish)
- End Sub
+ Dim Loader As New LoaderCombo(Of String)("安装压缩包", {
+ New LoaderTask(Of String, Integer)("安装压缩包",
+ Sub()
+ UnpackFiles(TargetFolder, FileAddress, Nothing)
+ PageSelectLeft.AddFolder(TargetFolder, NewName, False) '加入文件夹列表
+ End Sub)
+ })
+ Loader.Start()
+ LoaderTaskbarAdd(Loader)
+ FrmMain.BtnExtraDownload.ShowRefresh()
+ FrmMain.BtnExtraDownload.Ribble()
+ Return Loader
+ End Function
#End Region
diff --git a/Plain Craft Launcher 2/Modules/ModEvent.vb b/Plain Craft Launcher 2/Modules/ModEvent.vb
index aa09e79..e5282a9 100644
--- a/Plain Craft Launcher 2/Modules/ModEvent.vb
+++ b/Plain Craft Launcher 2/Modules/ModEvent.vb
@@ -21,28 +21,38 @@
OpenWebsite(Data(0))
Case "打开文件", "打开帮助"
- RunInThread(Sub()
- Try
- '确认实际路径
- Dim ActualPaths = GetEventAbsoluteUrls(Data(0), Type)
- Dim Location = ActualPaths(0), WorkingDir = ActualPaths(1)
- '执行
- If Type = "打开文件" Then
- Dim Info As New ProcessStartInfo With {
- .Arguments = If(Data.Length >= 2, Data(1), ""),
- .FileName = Location,
- .WorkingDirectory = WorkingDir
- }
- Process.Start(Info)
- Else '打开帮助
- PageOtherHelp.EnterHelpPage(Location)
- End If
- Catch ex As Exception
- Log(ex, "执行打开类自定义事件失败", LogLevel.Msgbox)
- End Try
- End Sub)
+ RunInThread(
+ Sub()
+ Try
+ '确认实际路径
+ Dim ActualPaths = GetEventAbsoluteUrls(Data(0), Type)
+ Dim Location = ActualPaths(0), WorkingDir = ActualPaths(1)
+ Log($"[Control] 打开类自定义事件实际路径:{Location},工作目录:{WorkingDir}")
+ '执行
+ If Type = "打开文件" Then
+ Dim Info As New ProcessStartInfo With {
+ .Arguments = If(Data.Length >= 2, Data(1), ""),
+ .FileName = Location,
+ .WorkingDirectory = WorkingDir
+ }
+ Process.Start(Info)
+ Else '打开帮助
+ PageOtherHelp.EnterHelpPage(Location)
+ End If
+ Catch ex As Exception
+ Log(ex, "执行打开类自定义事件失败", LogLevel.Msgbox)
+ End Try
+ End Sub)
Case "启动游戏"
+ If Data(0) = "\current" Then
+ If McVersionCurrent Is Nothing Then
+ Hint("请先选择一个 Minecraft 版本!", HintType.Critical)
+ Exit Sub
+ Else
+ Data(0) = McVersionCurrent.Name
+ End If
+ End If
If McLaunchStart(New McLaunchOptions With
{.ServerIp = If(Data.Length >= 2, Data(1), Nothing), .Version = New McVersion(Data(0))}) Then
Hint("正在启动 " & Data(0) & "……")
diff --git a/Plain Craft Launcher 2/Modules/ModMain.vb b/Plain Craft Launcher 2/Modules/ModMain.vb
index e2b797c..a971886 100644
--- a/Plain Craft Launcher 2/Modules/ModMain.vb
+++ b/Plain Craft Launcher 2/Modules/ModMain.vb
@@ -394,6 +394,7 @@ EndHint:
Public FrmDownloadOptiFine As PageDownloadOptiFine
Public FrmDownloadLiteLoader As PageDownloadLiteLoader
Public FrmDownloadForge As PageDownloadForge
+ Public FrmDownloadNeoForge As PageDownloadNeoForge
Public FrmDownloadFabric As PageDownloadFabric
Public FrmDownloadMod As PageDownloadMod
Public FrmDownloadPack As PageDownloadPack
diff --git a/Plain Craft Launcher 2/Modules/ModMusic.vb b/Plain Craft Launcher 2/Modules/ModMusic.vb
index 8377aef..cc1ace6 100644
--- a/Plain Craft Launcher 2/Modules/ModMusic.vb
+++ b/Plain Craft Launcher 2/Modules/ModMusic.vb
@@ -69,16 +69,25 @@
Else
'有背景音乐
FrmMain.BtnExtraMusic.Show = True
-
- Dim ToolTipText As String = "正在播放:" & GetFileNameWithoutExtentionFromPath(MusicCurrent)
+ Dim ToolTipText As String
If MusicState = MusicStates.Pause Then
FrmMain.BtnExtraMusic.Logo = Logo.IconPlay
FrmMain.BtnExtraMusic.LogoScale = 0.8
- If MusicAllList.Count > 1 Then ToolTipText += vbCrLf & "左键播放,右键播放下一曲。"
+ ToolTipText = "已暂停:" & GetFileNameWithoutExtentionFromPath(MusicCurrent)
+ If MusicAllList.Count > 1 Then
+ ToolTipText += vbCrLf & "左键恢复播放,右键播放下一曲。"
+ Else
+ ToolTipText += vbCrLf & "左键恢复播放,右键重新从头播放。"
+ End If
Else
FrmMain.BtnExtraMusic.Logo = Logo.IconMusic
FrmMain.BtnExtraMusic.LogoScale = 1
- If MusicAllList.Count > 1 Then ToolTipText += vbCrLf & "左键暂停,右键播放下一曲。"
+ ToolTipText = "正在播放:" & GetFileNameWithoutExtentionFromPath(MusicCurrent)
+ If MusicAllList.Count > 1 Then
+ ToolTipText += vbCrLf & "左键暂停,右键播放下一曲。"
+ Else
+ ToolTipText += vbCrLf & "左键暂停,右键重新从头播放。"
+ End If
End If
FrmMain.BtnExtraMusic.ToolTip = ToolTipText
ToolTipService.SetVerticalOffset(FrmMain.BtnExtraMusic, If(ToolTipText.Contains(vbLf), 10, 16))
@@ -115,13 +124,14 @@
'''
Public Sub MusicControlNext()
If MusicAllList.Count = 1 Then
- Hint("播放列表中仅有一首歌曲!")
+ MusicStartPlay(MusicCurrent)
+ Hint("重新播放:" & GetFileNameFromPath(MusicCurrent), HintType.Finish)
Else
Dim Address As String = DequeueNextMusicAddress()
MusicStartPlay(Address)
Hint("正在播放:" & GetFileNameFromPath(Address), HintType.Finish)
- MusicRefreshUI()
End If
+ MusicRefreshUI()
End Sub
#End Region
diff --git a/Plain Craft Launcher 2/Modules/ModSecret.vb b/Plain Craft Launcher 2/Modules/ModSecret.vb
index 3cc2757..593a0e9 100644
--- a/Plain Craft Launcher 2/Modules/ModSecret.vb
+++ b/Plain Craft Launcher 2/Modules/ModSecret.vb
@@ -10,6 +10,8 @@ Friend Module ModSecret
'在开源内容的注册表键与普通内容的注册表键隔离
Public Const RegFolder As String = "PCLDebug"
+ '用于微软登录的 ClientId
+ Public Const OAuthClientId As String = ""
Friend Sub SecretOnApplicationStart()
'提升 UI 线程优先级
@@ -41,9 +43,9 @@ Friend Module ModSecret
Environment.[Exit](Result.Cancel)
End If
'开源版本提示
- MyMsgBox($"该版本中不包含以下特性:
-- 微软账户登录:需要 Client ID(你可以创建并申请一个,然后添加到 McLoginMsStart 方法中)
-- CurseForge 查询:需要 API Key(你可以申请一个,然后添加到 SecretHeadersSign 方法中)
+ MyMsgBox($"该版本中无法使用以下特性:
+- CurseForge API 调用:需要你自行申请 API Key,然后添加到 SecretHeadersSign 方法中
+- 正版登录:需要你自行申请 Client ID,然后添加到 ModSecret.vb 的开头
- 更新与联网通知:避免滥用隐患
- 主题切换:这是需要赞助解锁的纪念性质的功能,别让赞助者太伤心啦……
- 百宝箱:开发早期往里面塞了些开发工具,整理起来太麻烦了", "开源版本说明")
@@ -90,7 +92,6 @@ Friend Module ModSecret
#Region "网络鉴权"
Friend Function SecretCdnSign(UrlWithMark As String)
- '只处理以 {CDN} 结尾的链接
If Not UrlWithMark.EndsWithF("{CDN}") Then Return UrlWithMark
Return UrlWithMark.Replace("{CDN}", "").Replace(" ", "%20")
End Function
@@ -98,26 +99,24 @@ Friend Module ModSecret
''' 设置 Headers 的 UA、Referer。
'''
Friend Sub SecretHeadersSign(Url As String, ByRef Client As CookieWebClient, Optional UseBrowserUserAgent As Boolean = False)
- If ApplicationStartTick < 1 Then Return '禁止在没有运行程序的情况下通过反射调用
If UseBrowserUserAgent Then
Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode & " Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
Else
Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode
End If
- Client.Headers("Referer") = "http://" & VersionCode & ".pcl2.server/"
+ Client.Headers("Referer") = "http://" & VersionCode & ".pcl2.open.server/"
'如果你有 CurseForge API Key,请添加到 Headers 中,以恢复对 CurseForge 的访问
End Sub
'''
''' 设置 Headers 的 UA、Referer。
'''
Friend Sub SecretHeadersSign(Url As String, ByRef Request As HttpWebRequest, Optional UseBrowserUserAgent As Boolean = False)
- If ApplicationStartTick < 1 Then Return '禁止在没有运行程序的情况下通过反射调用
If UseBrowserUserAgent Then
Request.UserAgent = "PCL2/" & VersionStandardCode & " Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
Else
Request.UserAgent = "PCL2/" & VersionStandardCode
End If
- Request.Referer = "http://" & VersionCode & ".pcl2.server/"
+ Request.Referer = "http://" & VersionCode & ".pcl2.open.server/"
'如果你有 CurseForge API Key,请添加到 Headers 中,以恢复对 CurseForge 的访问
End Sub
@@ -253,6 +252,7 @@ Friend Module ModSecret
Return False
End Function
Public Function DonateCodeInput() As Boolean?
+ Return Nothing
End Function
#End Region
diff --git a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
index 885e140..6fc9adb 100644
--- a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
+++ b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
' 方法是按如下所示使用“*”
-
-
+
+
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb b/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
index 3b02dc6..7302f5d 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
@@ -28,15 +28,12 @@ Public Module ModDownloadLib
Dim VersionFolder As String = PathMcFolder & "versions\" & Id & "\"
'重复任务检查
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = "Minecraft " & Id & " 下载" Then
- If Behaviour = NetPreDownloadBehaviour.ExitWhileExistsOrDownloading Then Return LoaderTaskbar(i)
- Hint("该版本正在下载中!", HintType.Critical)
- Return LoaderTaskbar(i)
- End If
- Next
- End SyncLock
+ For Each OngoingLoader In LoaderTaskbar
+ If OngoingLoader.Name <> $"Minecraft {Id} 下载" Then Continue For
+ If Behaviour = NetPreDownloadBehaviour.ExitWhileExistsOrDownloading Then Return OngoingLoader
+ Hint("该版本正在下载中!", HintType.Critical)
+ Return OngoingLoader
+ Next
'已有版本检查
If Behaviour <> NetPreDownloadBehaviour.IgnoreCheck AndAlso File.Exists(VersionFolder & Id & ".json") AndAlso File.Exists(VersionFolder & Id & ".jar") Then
@@ -74,15 +71,12 @@ Public Module ModDownloadLib
VersionFolder = VersionFolder & Id & "\"
'重复任务检查
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = "Minecraft " & Id & " 下载" Then
- If Behaviour = NetPreDownloadBehaviour.ExitWhileExistsOrDownloading Then Exit Sub
- Hint("该版本正在下载中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ For Each OngoingLoader In LoaderTaskbar
+ If OngoingLoader.Name <> $"Minecraft {Id} 下载" Then Continue For
+ If Behaviour = NetPreDownloadBehaviour.ExitWhileExistsOrDownloading Then Exit Sub
+ Hint("该版本正在下载中!", HintType.Critical)
+ Exit Sub
+ Next
Dim Loaders As New List(Of LoaderBase)
'下载版本 Json 文件
@@ -316,46 +310,6 @@ Public Module ModDownloadLib
#Region "OptiFine 下载"
- Public Sub McDownloadOptiFine(DownloadInfo As DlOptiFineListEntry)
- Try
- Dim Id As String = DownloadInfo.NameVersion
- Dim VersionFolder As String = PathMcFolder & "versions\" & Id & "\"
- Dim IsNewVersion As Boolean = Val(DownloadInfo.Inherit.Split(".")(1)) >= 14
- Dim Target As String = If(IsNewVersion,
- PathTemp & "Cache\Code\" & DownloadInfo.NameVersion & "_" & GetUuid(),
- PathMcFolder & "libraries\optifine\OptiFine\" & DownloadInfo.NameFile.Replace("OptiFine_", "").Replace(".jar", "").Replace("preview_", "") & "\" & DownloadInfo.NameFile.Replace("OptiFine_", "OptiFine-").Replace("preview_", ""))
-
- '重复任务检查
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = "OptiFine " & DownloadInfo.NameDisplay & " 下载" Then
- Hint("该版本正在下载中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
-
- '已有版本检查
- If File.Exists(VersionFolder & Id & ".json") Then
- If MyMsgBox("版本 " & Id & " 已存在,是否重新下载?" & vbCrLf & "这会覆盖版本的 json 和 jar 文件,但不会影响版本隔离的文件。", "版本已存在", "继续", "取消") = 1 Then
- File.Delete(VersionFolder & Id & ".jar")
- File.Delete(VersionFolder & Id & ".json")
- Else
- Exit Sub
- End If
- End If
-
- '启动
- Dim Loader As New LoaderCombo(Of String)("OptiFine " & DownloadInfo.NameDisplay & " 下载", McDownloadOptiFineLoader(DownloadInfo)) With {.OnStateChanged = AddressOf McInstallState}
- Loader.Start(VersionFolder)
- LoaderTaskbarAdd(Loader)
- FrmMain.BtnExtraDownload.ShowRefresh()
- FrmMain.BtnExtraDownload.Ribble()
-
- Catch ex As Exception
- Log(ex, "开始 OptiFine 下载失败", LogLevel.Feedback)
- End Try
- End Sub
Private Sub McDownloadOptiFineSave(DownloadInfo As DlOptiFineListEntry)
Try
Dim Id As String = DownloadInfo.NameVersion
@@ -363,14 +317,11 @@ Public Module ModDownloadLib
If Not Target.Contains("\") Then Exit Sub
'重复任务检查
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = "OptiFine " & DownloadInfo.NameDisplay & " 下载" Then
- Hint("该版本正在下载中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ For Each OngoingLoader In LoaderTaskbar
+ If OngoingLoader.Name <> $"OptiFine {DownloadInfo.NameDisplay} 下载" Then Continue For
+ Hint("该版本正在下载中!", HintType.Critical)
+ Exit Sub
+ Next
Dim Loader As New LoaderCombo(Of DlOptiFineListEntry)("OptiFine " & DownloadInfo.NameDisplay & " 下载", McDownloadOptiFineSaveLoader(DownloadInfo, Target)) With {.OnStateChanged = AddressOf DownloadStateSave}
Loader.Start(DownloadInfo)
@@ -793,14 +744,11 @@ Retry:
Dim VersionFolder As String = PathMcFolder & "versions\" & VersionName & "\"
'重复任务检查
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = "LiteLoader " & Id & " 下载" Then
- Hint("该版本正在下载中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ For Each OngoingLoader In LoaderTaskbar
+ If OngoingLoader.Name <> $"LiteLoader {Id} 下载" Then Continue For
+ Hint("该版本正在下载中!", HintType.Critical)
+ Exit Sub
+ Next
'已有版本检查
If File.Exists(VersionFolder & VersionName & ".json") Then
@@ -830,14 +778,11 @@ Retry:
If Not Target.Contains("\") Then Exit Sub
'重复任务检查
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = "LiteLoader " & Id & " 下载" Then
- Hint("该版本正在下载中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ For Each OngoingLoader In LoaderTaskbar
+ If OngoingLoader.Name <> $"LiteLoader {Id} 下载" Then Continue For
+ Hint("该版本正在下载中!", HintType.Critical)
+ Exit Sub
+ Next
'构造步骤加载器
Dim Loaders As New List(Of LoaderBase)
@@ -1005,114 +950,57 @@ Retry:
#End Region
-#Region "Forge 下载"
+#Region "Forgelike 下载"
- Public Sub McDownloadForge(DownloadInfo As DlForgeVersionEntry)
- '老版本提示
- If DownloadInfo.Category = "client" Then
- If MyMsgBox("该 Forge 版本过于古老,PCL 暂不支持该版本的自动安装。" & vbCrLf &
- "若你仍然希望继续,PCL 将把安装程序下载到你指定的位置,但不会进行安装。",
- "版本过老", "继续", "取消") = 1 Then
- McDownloadForgeSave(DownloadInfo)
- End If
- Exit Sub
- End If
- If DownloadInfo.Category = "universal" OrElse DownloadInfo.Inherit.StartsWithF("1.5") Then '对该版本自动安装的支持将在之后加入
- If MyMsgBox("该 Forge 版本过于古老,PCL 暂不支持该版本的自动安装。" & vbCrLf &
- "若你仍然希望继续,PCL 将把安装程序下载到你指定的位置,但不会进行安装。",
- "版本过老", "继续", "取消") = 1 Then
- McDownloadForgeSave(DownloadInfo)
- End If
- Exit Sub
- End If
- '初始化参数
- Dim Id As String = DownloadInfo.Inherit & "-forge-" & DownloadInfo.Version
- Dim Target As String = PathTemp & "Cache\Code\ForgeInstall-" & DownloadInfo.Version & "_" & GetUuid() & "." & DownloadInfo.FileSuffix
- Dim VersionFolder As String = PathMcFolder & "versions\" & Id & "\"
- Dim DisplayName As String = "Forge " & DownloadInfo.Inherit & " - " & DownloadInfo.Version
+ Public Sub McDownloadForgelikeSave(Info As DlForgelikeEntry)
Try
-
- '重复任务检查
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = DisplayName & " 下载" Then
- Hint("该版本正在下载中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
-
- '已有版本检查
- If File.Exists(VersionFolder & Id & ".json") Then
- If MyMsgBox("版本 " & Id & " 已存在,是否重新下载?" & vbCrLf & "这会覆盖版本的 json 和 jar 文件,但不会影响版本隔离的文件。", "版本已存在", "继续", "取消") = 1 Then
- File.Delete(VersionFolder & Id & ".jar")
- File.Delete(VersionFolder & Id & ".json")
- Else
- Exit Sub
- End If
- End If
-
- '启动
- Dim Loader As New LoaderCombo(Of String)(DisplayName & " 下载", McDownloadForgeLoader(DownloadInfo.Version, DownloadInfo.Inherit, DownloadInfo)) With {.OnStateChanged = AddressOf McInstallState}
- Loader.Start(VersionFolder)
- LoaderTaskbarAdd(Loader)
- FrmMain.BtnExtraDownload.ShowRefresh()
- FrmMain.BtnExtraDownload.Ribble()
-
- Catch ex As Exception
- Log(ex, "开始 Forge 下载失败", LogLevel.Feedback)
- Finally
- '删除安装包
- Try
- If File.Exists(Target) Then File.Delete(Target)
- Catch
- End Try
- End Try
- End Sub
- Public Sub McDownloadForgeSave(DownloadInfo As DlForgeVersionEntry)
- Try
- Dim Target As String = SelectAs("选择保存位置", DownloadInfo.FileName, "Forge 文件 (*." & DownloadInfo.FileSuffix & ")|*." & DownloadInfo.FileSuffix)
- Dim DisplayName As String = "Forge " & DownloadInfo.Inherit & " - " & DownloadInfo.Version
+ Dim Target As String = SelectAs("选择保存位置", $"{Info.LoaderName}-{Info.Inherit}-{Info.VersionName}.{Info.FileExtension}",
+ $"{Info.LoaderName} 安装器 (*.{Info.FileExtension})|*.{Info.FileExtension}")
+ Dim DisplayName As String = $"{Info.LoaderName} {Info.Inherit} - {Info.VersionName}"
If Not Target.Contains("\") Then Exit Sub
'重复任务检查
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = DisplayName & " 下载" Then
- Hint("该版本正在下载中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ For Each OngoingLoader In LoaderTaskbar
+ If OngoingLoader.Name <> $"{DisplayName} 下载" Then Continue For
+ Hint("该版本正在下载中!", HintType.Critical)
+ Exit Sub
+ Next
- '构造步骤加载器
- Dim Loaders As New List(Of LoaderBase)
'获取下载地址
- Loaders.Add(New LoaderTask(Of DlForgeVersionEntry, List(Of NetFile))("获取下载地址",
- Sub(Task As LoaderTask(Of DlForgeVersionEntry, List(Of NetFile)))
- Dim Files As New List(Of NetFile)
+ Dim Files As New List(Of NetFile)
+ If Info.IsNeoForge Then
+ 'NeoForge
+ Dim Neo As DlNeoForgeListEntry = Info
+ Dim Url As String = Neo.UrlBase & "-installer.jar"
Files.Add(New NetFile({
- "https://bmclapi2.bangbang93.com/maven/net/minecraftforge/forge/" & DownloadInfo.Inherit & "-" & DownloadInfo.FileVersion & "/" & DownloadInfo.FileName,
- "https://files.minecraftforge.net/maven/net/minecraftforge/forge/" & DownloadInfo.Inherit & "-" & DownloadInfo.FileVersion & "/" & DownloadInfo.FileName
- }, Target, New FileChecker(MinSize:=64 * 1024, Hash:=DownloadInfo.Hash)))
- Task.Output = Files
- End Sub) With {.ProgressWeight = 0.1, .Show = False})
- '下载
- Loaders.Add(New LoaderDownload("下载主文件", New List(Of NetFile)) With {.ProgressWeight = 6})
+ Url.Replace("maven.neoforged.net/releases", "bmclapi2.bangbang93.com/maven"), Url
+ }, Target, New FileChecker(MinSize:=64 * 1024)))
+ Else
+ 'Forge
+ Dim Forge As DlForgeVersionEntry = Info
+ Files.Add(New NetFile({
+ $"https://bmclapi2.bangbang93.com/maven/net/minecraftforge/forge/{Forge.Inherit}-{Forge.FileVersion}/forge-{Forge.Inherit}-{Forge.FileVersion}-{Forge.Category}.{Forge.FileExtension}",
+ $"https://files.minecraftforge.net/maven/net/minecraftforge/forge/{Forge.Inherit}-{Forge.FileVersion}/forge-{Forge.Inherit}-{Forge.FileVersion}-{Forge.Category}.{Forge.FileExtension}"
+ }, Target, New FileChecker(MinSize:=64 * 1024, Hash:=Forge.Hash)))
+ End If
+
+ '构造加载器
+ Dim Loaders As New List(Of LoaderBase)
+ Loaders.Add(New LoaderDownload("下载主文件", Files) With {.ProgressWeight = 6})
'启动
- Dim Loader As New LoaderCombo(Of DlForgeVersionEntry)(DisplayName & " 下载", Loaders) With {.OnStateChanged = AddressOf DownloadStateSave}
- Loader.Start(DownloadInfo)
+ Dim Loader = New LoaderCombo(Of DlForgelikeEntry)(DisplayName & " 下载", Loaders) With {.OnStateChanged = AddressOf DownloadStateSave}
+ Loader.Start(Info)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
FrmMain.BtnExtraDownload.Ribble()
Catch ex As Exception
- Log(ex, "开始 Forge 下载失败", LogLevel.Feedback)
+ Log(ex, $"开始 {Info.LoaderName} 安装器下载失败", LogLevel.Feedback)
End Try
End Sub
- Private Sub ForgeInjector(Target As String, Task As LoaderTask(Of Boolean, Boolean), McFolder As String, UseJavaWrapper As Boolean)
+ Private Sub ForgelikeInjector(Target As String, Task As LoaderTask(Of Boolean, Boolean), McFolder As String, UseJavaWrapper As Boolean, IsNeoForge As Boolean)
'选择 Java
Dim Java As JavaEntry
SyncLock JavaLock
@@ -1153,7 +1041,8 @@ Retry:
.RedirectStandardError = True,
.RedirectStandardOutput = True
}
- Log("[Download] 开始安装 Forge:" & Arguments)
+ Dim LoaderName As String = If(IsNeoForge, "NeoForge", "Forge")
+ Log($"[Download] 开始安装 {LoaderName}:" & Arguments)
Dim process As New Process With {.StartInfo = Info}
Dim LastResults As New Queue(Of String)
Using outputWaitHandle As New AutoResetEvent(False)
@@ -1166,15 +1055,15 @@ Retry:
Else
LastResults.Enqueue(e.Data)
If LastResults.Count > 100 Then LastResults.Dequeue()
- ForgeInjectorLine(e.Data, Task)
+ ForgelikeInjectorLine(e.Data, Task)
End If
Catch ex As ObjectDisposedException
Catch ex As Exception
- Log(ex, "读取 Forge 安装器信息失败")
+ Log(ex, $"读取 {LoaderName} 安装器信息失败")
End Try
Try
If Task.State = LoadState.Aborted AndAlso Not process.HasExited Then
- Log("[Installer] 由于任务取消,已中止 Forge 安装")
+ Log($"[Installer] 由于任务取消,已中止 {LoaderName} 安装")
process.Kill()
End If
Catch
@@ -1189,15 +1078,15 @@ Retry:
Else
LastResults.Enqueue(e.Data)
If LastResults.Count > 100 Then LastResults.Dequeue()
- ForgeInjectorLine(e.Data, Task)
+ ForgelikeInjectorLine(e.Data, Task)
End If
Catch ex As ObjectDisposedException
Catch ex As Exception
- Log(ex, "读取 Forge 安装器错误信息失败")
+ Log(ex, $"读取 {LoaderName} 安装器错误信息失败")
End Try
Try
If Task.State = LoadState.Aborted AndAlso Not process.HasExited Then
- Log("[Installer] 由于任务取消,已中止 Forge 安装")
+ Log($"[Installer] 由于任务取消,已中止 {LoaderName} 安装")
process.Kill()
End If
Catch
@@ -1222,116 +1111,135 @@ Retry:
For i As Integer = Math.Max(0, LastResults.Count - 5) To LastResults.Count - 1 '最后 5 行
LastLines &= vbCrLf & LastResults(i)
Next
- Throw New Exception("Forge 安装器出错,日志结束部分为:" & LastLines)
+ Throw New Exception($"{LoaderName} 安装器出错,日志结束部分为:" & LastLines)
End Using
End Using
End SyncLock
End Sub
- Private Sub ForgeInjectorLine(Content As String, Task As LoaderTask(Of Boolean, Boolean))
- If Content.StartsWithF(" Data") OrElse Content.StartsWithF(" Slim") Then
- If ModeDebug Then Log("[Installer] " & Content)
- ElseIf Content.StartsWithF(" Reading patch ") Then
- If ModeDebug Then Log("[Installer] " & Content)
- Task.Progress = 0.86
- Else
- Select Case Content
- Case "Extracting json"
- Log("[Installer] " & Content)
- Task.Progress = 0.07
- Case "Downloading libraries"
- Log("[Installer] " & Content)
- Task.Progress = 0.08
- Case " File exists: Checksum validated."
- If ModeDebug Then Log("[Installer] " & Content)
- Task.Progress += 0.003
- Case "Building Processors"
- Task.Progress = 0.38
- Case "Task: DOWNLOAD_MOJMAPS" 'B
- Task.Progress = 0.4
- Case "Task: MERGE_MAPPING" 'B
- Task.Progress = 0.6
- Case "Splitting: "
- Task.Progress = 0.62
- Case "Parameter Annotations" 'B
- Task.Progress = 0.66
- Case "Processing Complete" 'B
- Task.Progress = 0.7
- Case "Remapping final jar" 'A
- Task.Progress = 0.72
- Case "Remapping jar... 50%" 'A
- Task.Progress = 0.76
- Case "Remapping jar... 100%" 'A
- Task.Progress = 0.81
- Case "Injecting profile"
- Task.Progress = 0.91
- Case Else
- If ModeDebug Then Log("[Installer] " & Content)
- Exit Sub
- End Select
- Log("[Installer] " & Content)
- End If
+ Private Sub ForgelikeInjectorLine(Content As String, Task As LoaderTask(Of Boolean, Boolean))
+ Select Case Content
+ Case "Extracting json"
+ Log("[Installer] " & Content)
+ Task.Progress = 0.07
+ Case "Downloading libraries"
+ Log("[Installer] " & Content)
+ Task.Progress = 0.08
+ Case " File exists: Checksum validated."
+ If ModeDebug Then Log("[Installer] " & Content)
+ Task.Progress += 0.003
+ Case "Building Processors"
+ Task.Progress = 0.18
+ Case "Task: DOWNLOAD_MOJMAPS" 'B
+ Task.Progress = 0.2
+ Case "Task: MERGE_MAPPING" 'B
+ Task.Progress = 0.3
+ Case "Splitting: "
+ Task.Progress = 0.35
+ Case "Parameter Annotations" 'B
+ Task.Progress = 0.4
+ Case "Processing Complete" 'B
+ Task.Progress = 0.5
+ Case "log: null" 'new
+ Task.Progress = 0.5
+ Case "Sorting" 'new
+ Task.Progress = 0.65
+ Case "Remapping final jar" 'A
+ Task.Progress = 0.72
+ Case "Remapping jar... 50%" 'A
+ Task.Progress = 0.76
+ Case "Remapping jar... 100%" 'A
+ Task.Progress = 0.81
+ Case "Injecting profile"
+ Task.Progress = 0.91
+ Case Else
+ If ModeDebug Then Log("[Installer] " & Content)
+ Exit Sub
+ End Select
+ Log("[Installer] " & Content)
End Sub
'''
- ''' 获取下载某个 Forge 版本的加载器列表。
+ ''' 获取下载某个 Forgelike 版本的加载器列表。
'''
- Private Function McDownloadForgeLoader(Version As String, Inherit As String, Optional DownloadInfo As DlForgeVersionEntry = Nothing, Optional McFolder As String = Nothing, Optional ClientDownloadLoader As LoaderCombo(Of String) = Nothing, Optional ClientFolder As String = Nothing, Optional FixLibrary As Boolean = True) As List(Of LoaderBase)
+ Private Function McDownloadForgelikeLoader(IsNeoForge As Boolean, LoaderVersion As String, TargetVersion As String, Inherit As String, Optional Info As DlForgelikeEntry = Nothing, Optional McFolder As String = Nothing, Optional ClientDownloadLoader As LoaderCombo(Of String) = Nothing, Optional ClientFolder As String = Nothing) As List(Of LoaderBase)
'参数初始化
McFolder = If(McFolder, PathMcFolder)
- If Version.StartsWithF("1.") AndAlso Version.Contains("-") Then
- '类似 1.19.3-41.2.8 格式,优先使用 Version 中要求的版本而非 Inherit(例如 1.19.3 却使用了 1.19 的 Forge)
- Inherit = Version.Before("-")
- Version = Version.After("-")
+ If IsNeoForge AndAlso Info Is Nothing Then
+ '需要传入 API Name,但整合包版本可能不以 1.20.1- 开头,所以需要进行特别处理
+ If Inherit = "1.20.1" AndAlso Not LoaderVersion.StartsWithF("1.20.1-") Then
+ Info = New DlNeoForgeListEntry("1.20.1-" & LoaderVersion)
+ Else
+ Info = New DlNeoForgeListEntry(LoaderVersion)
+ End If
End If
+ If Not IsNeoForge AndAlso LoaderVersion.StartsWithF("1.") AndAlso LoaderVersion.Contains("-") Then
+ '类似 1.19.3-41.2.8 格式,优先使用 Version 中要求的版本而非 Inherit(例如 1.19.3 却使用了 1.19 的 Forge)
+ Inherit = LoaderVersion.Before("-")
+ LoaderVersion = LoaderVersion.After("-")
+ End If
+ Dim LoaderName As String = If(IsNeoForge, "NeoForge", "Forge")
Dim IsCustomFolder As Boolean = McFolder <> PathMcFolder
- Dim Id As String = Inherit & "-forge-" & Version
- Dim InstallerAddress As String = PathTemp & "Cache\Code\ForgeInstall-" & Version & "_" & RandomInteger(0, 100000)
- Dim VersionFolder As String = McFolder & "versions\" & Id & "\"
- Dim DisplayName As String = "Forge " & Inherit & " - " & Version
+ Dim InstallerAddress As String = $"{PathTemp}Cache\Code\{LoaderName}Install-{LoaderVersion}_{RandomInteger(0, 100000)}"
+ Dim VersionFolder As String = $"{McFolder}versions\{TargetVersion}\"
+ Dim DisplayName As String = $"{LoaderName} {Inherit} - {LoaderVersion}"
Dim Loaders As New List(Of LoaderBase)
- Dim LibVersionFolder As String = PathMcFolder & "versions\" & Id & "\" '作为 Lib 文件目标的版本文件夹
+ Dim LibVersionFolder As String = $"{PathMcFolder}versions\{TargetVersion}\" '作为 Lib 文件目标的版本文件夹
- '获取下载信息
- If DownloadInfo Is Nothing Then
- Loaders.Add(New LoaderTask(Of String, String)("获取 Mod 加载器详细信息",
+ '获取 Forge 下载信息
+ If Info Is Nothing Then
+ Loaders.Add(New LoaderTask(Of String, String)($"获取 {LoaderName} 详细信息",
Sub(Task As LoaderTask(Of String, String))
- '获取 Forge 版本列表
+ '获取 Forge 对应 MC 版本列表
Dim ForgeLoader = New LoaderTask(Of String, List(Of DlForgeVersionEntry))("McDownloadForgeLoader " & Inherit, AddressOf DlForgeVersionMain)
ForgeLoader.WaitForExit(Inherit)
Task.Progress = 0.8
'查找对应版本
For Each ForgeVersion In ForgeLoader.Output
- If ForgeVersion.Version = Version Then
- DownloadInfo = ForgeVersion
+ If VersionSortInteger(ForgeVersion.Version.ToString, LoaderVersion) = 0 Then
+ Info = ForgeVersion
Exit Sub
End If
Next
- Throw New Exception("未能找到 Forge " & Inherit & "-" & Version & " 的详细信息!")
+ Throw New Exception($"未能找到 {LoaderName} " & Inherit & "-" & LoaderVersion & " 的详细信息!")
End Sub) With {.ProgressWeight = 3})
End If
- '下载 Forge 主文件
- Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("准备 Mod 加载器下载",
- Sub(Task As LoaderTask(Of String, List(Of NetFile)))
- '启动依赖版本的下载
- If ClientDownloadLoader Is Nothing Then
- If IsCustomFolder Then Throw New Exception("如果没有指定原版下载器,则不能指定 MC 安装文件夹")
- ClientDownloadLoader = McDownloadClient(NetPreDownloadBehaviour.ExitWhileExistsOrDownloading, Inherit)
- End If
- '添加主文件
- Dim Files As New List(Of NetFile) From {New NetFile({
- "https://bmclapi2.bangbang93.com/maven/net/minecraftforge/forge/" & Inherit & "-" & DownloadInfo.FileVersion & "/" & DownloadInfo.FileName,
- "https://files.minecraftforge.net/maven/net/minecraftforge/forge/" & Inherit & "-" & DownloadInfo.FileVersion & "/" & DownloadInfo.FileName
- }, InstallerAddress, New FileChecker(MinSize:=64 * 1024, Hash:=DownloadInfo.Hash))}
- Task.Output = Files
- End Sub) With {.ProgressWeight = 0.5, .Show = False})
- Loaders.Add(New LoaderDownload("下载 Mod 加载器主文件", New List(Of NetFile)) With {.ProgressWeight = 9})
+ '下载 Forgelike 主文件
+ Loaders.Add(New LoaderTask(Of String, List(Of NetFile))($"准备下载 {LoaderName}",
+ Sub(Task As LoaderTask(Of String, List(Of NetFile)))
+ '启动依赖版本的下载
+ If ClientDownloadLoader Is Nothing Then
+ If IsCustomFolder Then Throw New Exception("如果没有指定原版下载器,则不能指定 MC 安装文件夹")
+ ClientDownloadLoader = McDownloadClient(NetPreDownloadBehaviour.ExitWhileExistsOrDownloading, Inherit)
+ End If
+ '添加主文件下载
+ Dim Files As New List(Of NetFile)
+ If Info.IsNeoForge Then
+ 'NeoForge
+ Dim Neo As DlNeoForgeListEntry = Info
+ Dim Url As String = Neo.UrlBase & "-installer.jar"
+ Files.Add(New NetFile({
+ Url.Replace("maven.neoforged.net/releases", "bmclapi2.bangbang93.com/maven"), Url
+ }, InstallerAddress, New FileChecker(MinSize:=64 * 1024)))
+ Else
+ 'Forge
+ Dim Forge As DlForgeVersionEntry = Info
+ Dim FileName As String =
+ $"{Forge.Inherit.Replace("-", "_")}-{Forge.FileVersion}/forge-{Forge.Inherit.Replace("-", "_")}-{Forge.FileVersion}-{Forge.Category}.{Forge.FileExtension}"
+ Files.Add(New NetFile({
+ $"https://bmclapi2.bangbang93.com/maven/net/minecraftforge/forge/{FileName}",
+ $"https://files.minecraftforge.net/maven/net/minecraftforge/forge/{FileName}"
+ }, InstallerAddress, New FileChecker(MinSize:=64 * 1024, Hash:=Forge.Hash)))
+ End If
+ Task.Output = Files
+ End Sub) With {.ProgressWeight = 0.5, .Show = False})
+ Loaders.Add(New LoaderDownload($"下载 {LoaderName} 主文件", New List(Of NetFile)) With {.ProgressWeight = 9})
'安装(仅在新版安装时需要原版 Jar)
- If Version.Before(".") >= 20 Then
- Log("[Download] 检测为新版 Forge:" & Version)
+ If IsNeoForge OrElse LoaderVersion.Before(".") >= 20 Then
+ Log($"[Download] 检测为{If(IsNeoForge, " Neo", "新版 ")}Forge:" & LoaderVersion)
Dim Libs As List(Of McLibToken) = Nothing
- Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("分析 Mod 加载器支持库文件",
+ Loaders.Add(New LoaderTask(Of String, List(Of NetFile))($"分析 {LoaderName} 支持库文件",
Sub(Task As LoaderTask(Of String, List(Of NetFile)))
Task.Output = New List(Of NetFile)
Dim Installer As ZipArchive = Nothing
@@ -1352,32 +1260,34 @@ Retry:
'[net.minecraft:client:1.17.1-20210706.113038:mappings@txt] 或 @tsrg]
Dim OriginalName As String = Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).Before("@")
Dim Address = McLibGet(OriginalName).Replace(".jar", "-mappings." & Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).Split("@")(1))
- Libs.Add(New McLibToken With {.IsJumpLoader = False, .IsNatives = False, .LocalPath = Address, .OriginalName = OriginalName,
- .Url = RawJson("downloads")("client_mappings")("url"), .Size = RawJson("downloads")("client_mappings")("size"), .SHA1 = RawJson("downloads")("client_mappings")("sha1")})
- Log("[Download] 需要下载 Mappings:" & Address)
+ Dim ClientMappings As JToken = RawJson("downloads")("client_mappings")
+ Libs.Add(New McLibToken With {
+ .IsJumpLoader = False, .IsNatives = False, .LocalPath = Address, .OriginalName = OriginalName,
+ .Url = ClientMappings("url"), .Size = ClientMappings("size"), .SHA1 = ClientMappings("sha1")})
+ Log($"[Download] 需要下载 Mappings:{ClientMappings("url")} (SHA1: {ClientMappings("sha1")})")
End If
Task.Progress = 0.8
- '去除其中的原始 Forge 项
+ '去除其中的原始 Forgelike 项
For i = 0 To Libs.Count - 1
- If Libs(i).LocalPath.EndsWithF("forge-" & Inherit & "-" & Version & ".jar") OrElse
- Libs(i).LocalPath.EndsWithF("forge-" & Inherit & "-" & Version & "-client.jar") Then
- Log("[Download] 已从待下载 Forge 支持库中移除:" & Libs(i).LocalPath, LogLevel.Debug)
+ If Libs(i).LocalPath.EndsWithF($"{LoaderName.ToLower}-{Inherit}-{LoaderVersion}.jar") OrElse
+Libs(i).LocalPath.EndsWithF($"{LoaderName.ToLower}-{Inherit}-{LoaderVersion}-client.jar") Then
+ Log($"[Download] 已从待下载 {LoaderName} 支持库中移除:" & Libs(i).LocalPath, LogLevel.Debug)
Libs.RemoveAt(i)
Exit For
End If
Next
Task.Output = McLibFixFromLibToken(Libs, PathMcFolder)
Catch ex As Exception
- Throw New Exception("获取新版 Forge 支持库列表失败", ex)
+ Throw New Exception($"获取{If(IsNeoForge, " Neo", "新版 ")}Forge 支持库列表失败", ex)
Finally
'释放文件
If Installer IsNot Nothing Then Installer.Dispose()
End Try
End Sub) With {.ProgressWeight = 2})
- Loaders.Add(New LoaderDownload("下载 Mod 加载器支持库文件", New List(Of NetFile)) With {.ProgressWeight = 12})
- Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("获取 Mod 下载器支持库文件",
+ Loaders.Add(New LoaderDownload($"下载 {LoaderName} 支持库文件", New List(Of NetFile)) With {.ProgressWeight = 12})
+ Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)($"获取 {LoaderName} 支持库文件",
Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
-#Region "Forge 文件"
+#Region "Forgelike 文件"
If IsCustomFolder Then
For Each LibFile As McLibToken In Libs
Dim RealPath As String = LibFile.LocalPath.Replace(PathMcFolder, McFolder)
@@ -1385,7 +1295,7 @@ Retry:
Directory.CreateDirectory(IO.Path.GetDirectoryName(RealPath))
CopyFile(LibFile.LocalPath, RealPath)
End If
- If ModeDebug Then Log("[Download] 复制的 Forge 支持库文件:" & LibFile.LocalPath)
+ If ModeDebug Then Log($"[Download] 复制的 {LoaderName} 支持库文件:" & LibFile.LocalPath)
Next
End If
#End Region
@@ -1393,9 +1303,9 @@ Retry:
'等待原版文件下载完成
If ClientDownloadLoader Is Nothing Then Exit Sub
Dim TargetLoaders As List(Of LoaderBase) =
- ClientDownloadLoader.GetLoaderList.Where(Function(l) l.Name = McDownloadClientLibName OrElse l.Name = McDownloadClientJsonName).
- Where(Function(l) l.State <> LoadState.Finished).ToList
- If TargetLoaders.Any Then Log("[Download] Forge 安装正在等待原版文件下载完成")
+ ClientDownloadLoader.GetLoaderList.Where(Function(l) l.Name = McDownloadClientLibName OrElse l.Name = McDownloadClientJsonName).
+ Where(Function(l) l.State <> LoadState.Finished).ToList()
+ If TargetLoaders.Any Then Log($"[Download] {LoaderName} 安装正在等待原版文件下载完成")
Do While TargetLoaders.Any AndAlso Not Task.IsAborted
TargetLoaders = TargetLoaders.Where(Function(l) l.State <> LoadState.Finished).ToList
Thread.Sleep(50)
@@ -1415,14 +1325,13 @@ Retry:
End SyncLock
#End Region
End Sub) With {.ProgressWeight = 0.1, .Show = False})
- Loaders.Add(New LoaderTask(Of Boolean, Boolean)("安装 Mod 加载器(方式 A)",
+ Loaders.Add(New LoaderTask(Of Boolean, Boolean)(If(IsNeoForge, "安装 NeoForge", "安装 Forge(方式 A)"),
Sub(Task As LoaderTask(Of Boolean, Boolean))
Dim Installer As ZipArchive = Nothing
Try
- Log("[Download] 开始进行新版方式 Forge 安装:" & InstallerAddress)
+ Log($"[Download] 开始进行 Forgelike 安装:" & InstallerAddress)
'记录当前文件夹列表(在新建目标文件夹之前)
- Dim OldList = New DirectoryInfo(McFolder & "versions\").EnumerateDirectories.
- Select(Function(i) i.FullName).ToList()
+ Dim OldList = New DirectoryInfo(McFolder & "versions\").EnumerateDirectories.Select(Function(i) i.FullName).ToList()
'解压并获取信息
Installer = New ZipArchive(New FileStream(InstallerAddress, FileMode.Open))
Dim Json As JObject = GetJson(ReadFile(Installer.GetEntry("install_profile.json").Open))
@@ -1440,15 +1349,15 @@ Retry:
WriteFile(PathTemp & "Cache\forge_installer.jar", GetResources("ForgeInstaller"))
Task.Progress = 0.06
'运行注入器
- ForgeInjector(InstallerAddress, Task, McFolder, UseJavaWrapper)
+ ForgelikeInjector(InstallerAddress, Task, McFolder, UseJavaWrapper, IsNeoForge)
Task.Progress = 0.97
Catch ex As Exception
If UseJavaWrapper Then
- Log(ex, "使用 JavaWrapper 安装 Forge 失败,将不使用 JavaWrapper 并重试")
+ Log(ex, $"使用 JavaWrapper 安装 {LoaderName} 失败,将不使用 JavaWrapper 并重试")
UseJavaWrapper = False
GoTo Retry
Else
- Throw New Exception("运行 Forge 安装器失败", ex)
+ Throw New Exception($"运行 {LoaderName} 安装器失败", ex)
End If
End Try
'拷贝新增的版本 Json
@@ -1457,86 +1366,90 @@ Retry:
If DeltaList.Count > 1 Then
'它可能和 OptiFine 安装同时运行,导致增加的文件不止一个(这导致了 #151)
'也可能是因为 Forge 安装器的 Bug,生成了一个名字错误的文件夹,所以需要检查文件夹是否为空
- DeltaList = DeltaList.Where(Function(l) l.Name.Contains("forge") AndAlso l.EnumerateFiles.Any).ToList
+ DeltaList = DeltaList.Where(Function(l) l.Name.ContainsF("forge", True) AndAlso l.EnumerateFiles.Any).ToList
End If
- If DeltaList.Count = 1 Then '如果没有新增文件夹,那么预测的文件夹名就是正确的
+ If DeltaList.Count = 1 Then
+ '如果没有新增文件夹,那么预测的文件夹名就是正确的
+ '如果只新增 1 个文件夹,那么拷贝 json 文件
Dim JsonFile As FileInfo = DeltaList(0).EnumerateFiles.First()
- WriteFile(VersionFolder & Id & ".json", ReadFile(JsonFile.FullName))
+ WriteFile(VersionFolder & TargetVersion & ".json", ReadFile(JsonFile.FullName))
+ Log($"[Download] 已拷贝新增的版本 JSON 文件:{JsonFile.FullName} -> {VersionFolder}{TargetVersion}.json")
+ ElseIf DeltaList.Count > 1 Then
+ '新增了多个文件夹
+ Log($"[Download] 有多个疑似的新增版本,无法确定:{DeltaList.Select(Function(d) d.Name).Join(";")}")
+ Else
+ '没有新增文件夹
+ Log("[Download] 未找到新增的版本文件夹")
End If
'新建 mods 文件夹
Directory.CreateDirectory(New McVersion(VersionFolder).GetPathIndie(True) & "mods\")
Catch ex As Exception
- Throw New Exception("安装新 Forge 版本失败", ex)
+ Throw New Exception($"安装新 {LoaderName} 版本失败", ex)
Finally
'清理文件
Try
If Installer IsNot Nothing Then Installer.Dispose()
If File.Exists(InstallerAddress) Then File.Delete(InstallerAddress)
Catch ex As Exception
- Log(ex, "安装 Forge 清理文件时出错")
+ Log(ex, $"安装 {LoaderName} 清理文件时出错")
End Try
End Try
End Sub) With {.ProgressWeight = 10})
Else
- Log("[Download] 检测为非新版 Forge:" & Version)
- Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("安装 Mod 加载器(方式 B)",
- Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
- Dim Installer As ZipArchive = Nothing
- Try
- '解压并获取信息
- Installer = New ZipArchive(New FileStream(InstallerAddress, FileMode.Open))
- Task.Progress = 0.2
- Dim Json As JObject = GetJson(ReadFile(Installer.GetEntry("install_profile.json").Open))
- Task.Progress = 0.4
- '新建版本文件夹
- Directory.CreateDirectory(VersionFolder)
- Task.Progress = 0.5
- If Json("install") Is Nothing Then
- '中版格式
- Log("[Download] 进行中版方式安装:" & InstallerAddress)
- '建立 Json 文件
- Dim JsonVersion As JObject = GetJson(ReadFile(Installer.GetEntry(Json("json").ToString.TrimStart("/")).Open))
- JsonVersion("id") = Id
- WriteFile(VersionFolder & Id & ".json", JsonVersion.ToString)
- Task.Progress = 0.6
- '解压支持库文件
- Installer.Dispose()
- ExtractFile(InstallerAddress, InstallerAddress & "_unrar\")
- CopyDirectory(InstallerAddress & "_unrar\maven\", McFolder & "libraries\")
- DeleteDirectory(InstallerAddress & "_unrar\")
- Else
- '旧版格式
- Log("[Download] 进行旧版方式安装:" & InstallerAddress)
- '解压 Jar 文件
- Dim JarAddress As String = McLibGet(Json("install")("path"), CustomMcFolder:=McFolder)
- If File.Exists(JarAddress) Then File.Delete(JarAddress)
- WriteFile(JarAddress, Installer.GetEntry(Json("install")("filePath")).Open)
- Task.Progress = 0.9
- '建立 Json 文件
- Json("versionInfo")("id") = Id
- If Json("versionInfo")("inheritsFrom") Is Nothing Then CType(Json("versionInfo"), JObject).Add("inheritsFrom", Inherit)
- WriteFile(VersionFolder & Id & ".json", Json("versionInfo").ToString)
- End If
- '新建 mods 文件夹
- Directory.CreateDirectory(New McVersion(VersionFolder).GetPathIndie(True) & "mods\")
- Catch ex As Exception
- Throw New Exception("非新版方式安装 Forge 失败", ex)
- Finally
- Try
- '清理文件
- If Installer IsNot Nothing Then Installer.Dispose()
- If File.Exists(InstallerAddress) Then File.Delete(InstallerAddress)
- If Directory.Exists(InstallerAddress & "_unrar\") Then DeleteDirectory(InstallerAddress & "_unrar\")
- Catch ex As Exception
+ Log("[Download] 检测为非新版 Forge:" & LoaderVersion)
+ Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)($"安装 {LoaderName}(方式 B)",
+Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
+ Dim Installer As ZipArchive = Nothing
+ Try
+ '解压并获取信息
+ Installer = New ZipArchive(New FileStream(InstallerAddress, FileMode.Open))
+ Task.Progress = 0.2
+ Dim Json As JObject = GetJson(ReadFile(Installer.GetEntry("install_profile.json").Open))
+ Task.Progress = 0.4
+ '新建版本文件夹
+ Directory.CreateDirectory(VersionFolder)
+ Task.Progress = 0.5
+ If Json("install") Is Nothing Then
+ '中版:Legacy 方式 1
+ Log("[Download] 开始进行 Forge 安装,Legacy 方式 1:" & InstallerAddress)
+ '建立 Json 文件
+ Dim JsonVersion As JObject = GetJson(ReadFile(Installer.GetEntry(Json("json").ToString.TrimStart("/")).Open))
+ JsonVersion("id") = TargetVersion
+ WriteFile(VersionFolder & TargetVersion & ".json", JsonVersion.ToString)
+ Task.Progress = 0.6
+ '解压支持库文件
+ Installer.Dispose()
+ ExtractFile(InstallerAddress, InstallerAddress & "_unrar\")
+ CopyDirectory(InstallerAddress & "_unrar\maven\", McFolder & "libraries\")
+ DeleteDirectory(InstallerAddress & "_unrar\")
+ Else
+ '旧版:Legacy 方式 2
+ Log("[Download] 开始进行 Forge 安装,Legacy 方式 2:" & InstallerAddress)
+ '解压 Jar 文件
+ Dim JarAddress As String = McLibGet(Json("install")("path"), CustomMcFolder:=McFolder)
+ If File.Exists(JarAddress) Then File.Delete(JarAddress)
+ WriteFile(JarAddress, Installer.GetEntry(Json("install")("filePath")).Open)
+ Task.Progress = 0.9
+ '建立 Json 文件
+ Json("versionInfo")("id") = TargetVersion
+ If Json("versionInfo")("inheritsFrom") Is Nothing Then CType(Json("versionInfo"), JObject).Add("inheritsFrom", Inherit)
+ WriteFile(VersionFolder & TargetVersion & ".json", Json("versionInfo").ToString)
+ End If
+ '新建 mods 文件夹
+ Directory.CreateDirectory(New McVersion(VersionFolder).GetPathIndie(True) & "mods\")
+ Catch ex As Exception
+ Throw New Exception("非新版方式安装 Forge 失败", ex)
+ Finally
+ Try
+ '清理文件
+ If Installer IsNot Nothing Then Installer.Dispose()
+ If File.Exists(InstallerAddress) Then File.Delete(InstallerAddress)
+ If Directory.Exists(InstallerAddress & "_unrar\") Then DeleteDirectory(InstallerAddress & "_unrar\")
+ Catch ex As Exception
Log(ex, "非新版方式安装 Forge 清理文件时出错")
End Try
End Try
End Sub) With {.ProgressWeight = 1})
- If FixLibrary Then
- If IsCustomFolder Then Throw New Exception("若需要补全支持库,就不能自定义 MC 文件夹")
- Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("分析 Mod 加载器支持库文件", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionFolder))) With {.ProgressWeight = 1, .Show = False})
- Loaders.Add(New LoaderDownload("下载 Mod 加载器支持库文件", New List(Of NetFile)) With {.ProgressWeight = 11})
- End If
End If
Return Loaders
@@ -1546,16 +1459,16 @@ Retry:
#Region "Forge 下载菜单"
- Public Sub ForgeDownloadListItemPreload(Stack As StackPanel, Entrys As List(Of DlForgeVersionEntry), OnClick As MyListItem.ClickEventHandler, IsSaveOnly As Boolean)
+ Public Sub ForgeDownloadListItemPreload(Stack As StackPanel, Entries As List(Of DlForgeVersionEntry), OnClick As MyListItem.ClickEventHandler, IsSaveOnly As Boolean)
'获取推荐版本与最新版本
Dim FreshVersion As DlForgeVersionEntry = Nothing
- If Entrys.Any Then
- FreshVersion = Entrys(0)
+ If Entries.Any Then
+ FreshVersion = Entries(0)
Else
Log("[System] 未找到可用的 Forge 版本", LogLevel.Debug)
End If
Dim RecommendedVersion As DlForgeVersionEntry = Nothing
- For Each Entry In Entrys
+ For Each Entry In Entries
If Entry.IsRecommended Then RecommendedVersion = Entry
Next
'若推荐版本与最新版本为同一版本,则仅显示推荐版本
@@ -1572,15 +1485,14 @@ Retry:
Stack.Children.Add(Fresh)
End If
'添加间隔
- Stack.Children.Add(New TextBlock With {.Text = "全部版本 (" & Entrys.Count & ")", .HorizontalAlignment = HorizontalAlignment.Left, .Margin = New Thickness(6, 13, 0, 4)})
+ Stack.Children.Add(New TextBlock With {.Text = "全部版本 (" & Entries.Count & ")", .HorizontalAlignment = HorizontalAlignment.Left, .Margin = New Thickness(6, 13, 0, 4)})
End Sub
Public Function ForgeDownloadListItem(Entry As DlForgeVersionEntry, OnClick As MyListItem.ClickEventHandler, IsSaveOnly As Boolean) As MyListItem
'建立控件
Dim NewItem As New MyListItem With {
- .Title = Entry.Version, .SnapsToDevicePixels = True, .Height = 42, .Type = MyListItem.CheckType.Clickable, .Tag = Entry,
- .Info = If(Entry.ReleaseTime = "",
- If(ModeDebug, "种类:" & Entry.Category & If(Entry.Branch Is Nothing, "", ",开发分支:" & Entry.Branch), ""),
- "发布于 " & Entry.ReleaseTime & If(ModeDebug, ",种类:" & Entry.Category & If(Entry.Branch Is Nothing, "", ",开发分支:" & Entry.Branch), "")),
+ .Title = Entry.VersionName, .SnapsToDevicePixels = True, .Height = 42, .Type = MyListItem.CheckType.Clickable, .Tag = Entry,
+ .Info = {If(Entry.ReleaseTime = "", "", "发布于 " & Entry.ReleaseTime), If(ModeDebug, "种类:" & Entry.Category, "")}.
+ Where(Function(d) d <> "").Join(","),
.Logo = PathImage & "Blocks/Anvil.png"
}
AddHandler NewItem.Click, OnClick
@@ -1623,7 +1535,7 @@ Retry:
Else
Version = sender.Parent.Parent.Tag
End If
- OpenWebsite("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" & Version.Inherit & "-" & Version.Version & "/forge-" & Version.Inherit & "-" & Version.Version & "-changelog.txt")
+ OpenWebsite($"https://files.minecraftforge.net/maven/net/minecraftforge/forge/{Version.Inherit}-{Version.VersionName}/forge-{Version.Inherit}-{Version.VersionName}-changelog.txt")
End Sub
Public Sub ForgeSave_Click(sender As Object, e As RoutedEventArgs)
Dim Version As DlForgeVersionEntry
@@ -1634,7 +1546,7 @@ Retry:
Else
Version = sender.Parent.Parent.Tag
End If
- McDownloadForgeSave(Version)
+ McDownloadForgelikeSave(Version)
End Sub
#End Region
@@ -1696,6 +1608,101 @@ Retry:
#End Region
+#Region "NeoForge 下载菜单"
+
+ Public Sub NeoForgeDownloadListItemPreload(Stack As StackPanel, Entries As List(Of DlNeoForgeListEntry), OnClick As MyListItem.ClickEventHandler, IsSaveOnly As Boolean)
+ '获取最新稳定版和测试版
+ Dim FreshStableVersion As DlNeoForgeListEntry = Nothing
+ Dim FreshBetaVersion As DlNeoForgeListEntry = Nothing
+ If Entries.Any() Then
+ For Each Entry In Entries.ToList()
+ If Entry.IsBeta Then
+ If FreshBetaVersion Is Nothing Then FreshBetaVersion = Entry
+ Else
+ FreshStableVersion = Entry
+ Exit For
+ End If
+ Next
+ Else
+ Log("[System] 未找到可用的 NeoForge 版本", LogLevel.Debug)
+ End If
+ '显示各个版本
+ If FreshStableVersion IsNot Nothing Then
+ Dim Fresh = NeoForgeDownloadListItem(FreshStableVersion, OnClick, IsSaveOnly)
+ Fresh.Info = If(Fresh.Info = "", "最新稳定版", "最新" & Fresh.Info)
+ Stack.Children.Add(Fresh)
+ End If
+ If FreshBetaVersion IsNot Nothing Then
+ Dim Fresh = NeoForgeDownloadListItem(FreshBetaVersion, OnClick, IsSaveOnly)
+ Fresh.Info = If(Fresh.Info = "", "最新测试版", "最新" & Fresh.Info)
+ Stack.Children.Add(Fresh)
+ End If
+ '添加间隔
+ Stack.Children.Add(New TextBlock With {.Text = "全部版本 (" & Entries.Count & ")", .HorizontalAlignment = HorizontalAlignment.Left, .Margin = New Thickness(6, 13, 0, 4)})
+ End Sub
+ Public Function NeoForgeDownloadListItem(Info As DlNeoForgeListEntry, OnClick As MyListItem.ClickEventHandler, IsSaveOnly As Boolean) As MyListItem
+ '建立控件
+ Dim NewItem As New MyListItem With {
+ .Title = Info.VersionName, .SnapsToDevicePixels = True, .Height = 42, .Type = MyListItem.CheckType.Clickable, .Tag = Info,
+ .Info = If(Info.IsBeta, "测试版", "稳定版"),
+ .Logo = PathImage & "Blocks/NeoForge.png"
+ }
+ AddHandler NewItem.Click, OnClick
+ '建立菜单
+ If IsSaveOnly Then
+ NewItem.ContentHandler = AddressOf NeoForgeSaveContMenuBuild
+ Else
+ NewItem.ContentHandler = AddressOf NeoForgeContMenuBuild
+ End If
+ '结束
+ Return NewItem
+ End Function
+ Private Sub NeoForgeContMenuBuild(sender As MyListItem, e As EventArgs)
+ Dim BtnSave As New MyIconButton With {.Logo = Logo.IconButtonSave, .ToolTip = "另存为"}
+ ToolTipService.SetPlacement(BtnSave, Primitives.PlacementMode.Center)
+ ToolTipService.SetVerticalOffset(BtnSave, 30)
+ ToolTipService.SetHorizontalOffset(BtnSave, 2)
+ AddHandler BtnSave.Click, AddressOf NeoForgeSave_Click
+ Dim BtnInfo As New MyIconButton With {.LogoScale = 1.05, .Logo = Logo.IconButtonInfo, .ToolTip = "更新日志"}
+ ToolTipService.SetPlacement(BtnInfo, Primitives.PlacementMode.Center)
+ ToolTipService.SetVerticalOffset(BtnInfo, 30)
+ ToolTipService.SetHorizontalOffset(BtnInfo, 2)
+ AddHandler BtnInfo.Click, AddressOf NeoForgeLog_Click
+ sender.Buttons = {BtnSave, BtnInfo}
+ End Sub
+ Private Sub NeoForgeSaveContMenuBuild(sender As MyListItem, e As EventArgs)
+ Dim BtnInfo As New MyIconButton With {.LogoScale = 1.05, .Logo = Logo.IconButtonInfo, .ToolTip = "更新日志"}
+ ToolTipService.SetPlacement(BtnInfo, Primitives.PlacementMode.Center)
+ ToolTipService.SetVerticalOffset(BtnInfo, 30)
+ ToolTipService.SetHorizontalOffset(BtnInfo, 2)
+ AddHandler BtnInfo.Click, AddressOf NeoForgeLog_Click
+ sender.Buttons = {BtnInfo}
+ End Sub
+ Private Sub NeoForgeLog_Click(sender As Object, e As RoutedEventArgs)
+ Dim Info As DlNeoForgeListEntry
+ If sender.Tag IsNot Nothing Then
+ Info = sender.Tag
+ ElseIf sender.Parent.Tag IsNot Nothing Then
+ Info = sender.Parent.Tag
+ Else
+ Info = sender.Parent.Parent.Tag
+ End If
+ OpenWebsite(Info.UrlBase & "-changelog.txt")
+ End Sub
+ Public Sub NeoForgeSave_Click(sender As Object, e As RoutedEventArgs)
+ Dim Info As DlNeoForgeListEntry
+ If sender.Tag IsNot Nothing Then
+ Info = sender.Tag
+ ElseIf sender.Parent.Tag IsNot Nothing Then
+ Info = sender.Parent.Tag
+ Else
+ Info = sender.Parent.Parent.Tag
+ End If
+ McDownloadForgelikeSave(Info)
+ End Sub
+
+#End Region
+
#Region "Fabric 下载"
Public Sub McDownloadFabricLoaderSave(DownloadInfo As JObject)
@@ -1707,14 +1714,11 @@ Retry:
If Not Target.Contains("\") Then Exit Sub
'重复任务检查
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = "Fabric " & Version & " 安装器下载" Then
- Hint("该版本正在下载中!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ For Each OngoingLoader In LoaderTaskbar
+ If OngoingLoader.Name <> $"Fabric {Version} 安装器下载" Then Continue For
+ Hint("该版本正在下载中!", HintType.Critical)
+ Exit Sub
+ Next
'构造步骤加载器
Dim Loaders As New List(Of LoaderBase)
@@ -1750,26 +1754,26 @@ Retry:
'下载 Json
MinecraftName = MinecraftName.Replace("∞", "infinite") '放在 ID 后面避免影响版本文件夹名称
Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("获取 Fabric 主文件下载地址",
- Sub(Task As LoaderTask(Of String, List(Of NetFile)))
- '启动依赖版本的下载
- If FixLibrary Then
- McDownloadClient(NetPreDownloadBehaviour.ExitWhileExistsOrDownloading, MinecraftName)
- End If
- Task.Progress = 0.5
- '构造文件请求
- Task.Output = New List(Of NetFile) From {New NetFile({
- "https://bmclapi2.bangbang93.com/fabric-meta/v2/versions/loader/" & MinecraftName & "/" & FabricVersion & "/profile/json",
- "https://meta.fabricmc.net/v2/versions/loader/" & MinecraftName & "/" & FabricVersion & "/profile/json"
- }, VersionFolder & Id & ".json", New FileChecker(IsJson:=True))}
- '新建 mods 文件夹
- Directory.CreateDirectory(New McVersion(VersionFolder).GetPathIndie(True) & "mods\")
- End Sub) With {.ProgressWeight = 0.5})
+ Sub(Task As LoaderTask(Of String, List(Of NetFile)))
+ '启动依赖版本的下载
+ If FixLibrary Then
+ McDownloadClient(NetPreDownloadBehaviour.ExitWhileExistsOrDownloading, MinecraftName)
+ End If
+ Task.Progress = 0.5
+ '构造文件请求
+ Task.Output = New List(Of NetFile) From {New NetFile({
+ "https://bmclapi2.bangbang93.com/fabric-meta/v2/versions/loader/" & MinecraftName & "/" & FabricVersion & "/profile/json",
+ "https://meta.fabricmc.net/v2/versions/loader/" & MinecraftName & "/" & FabricVersion & "/profile/json"
+ }, VersionFolder & Id & ".json", New FileChecker(IsJson:=True))}
+ '新建 mods 文件夹
+ Directory.CreateDirectory(New McVersion(VersionFolder).GetPathIndie(True) & "mods\")
+ End Sub) With {.ProgressWeight = 0.5})
Loaders.Add(New LoaderDownload("下载 Fabric 主文件", New List(Of NetFile)) With {.ProgressWeight = 2.5})
'下载支持库
If FixLibrary Then
Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("分析 Fabric 支持库文件",
- Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionFolder))) With {.ProgressWeight = 1, .Show = False})
+ Sub(Task) Task.Output = McLibFix(New McVersion(VersionFolder))) With {.ProgressWeight = 1, .Show = False})
Loaders.Add(New LoaderDownload("下载 Fabric 支持库文件", New List(Of NetFile)) With {.ProgressWeight = 8})
End If
@@ -1861,6 +1865,16 @@ Retry:
'''
Public ForgeEntry As DlForgeVersionEntry = Nothing
+ '若要下载 NeoForge,则需要在下面两项中完成至少一项
+ '''
+ ''' 欲下载的 NeoForge 版本名。
+ '''
+ Public NeoForgeVersion As String = Nothing
+ '''
+ ''' 欲下载的 NeoForge。
+ '''
+ Public NeoForgeEntry As DlNeoForgeListEntry = Nothing
+
'''
''' 欲下载的 Fabric Loader 版本名。
'''
@@ -1961,7 +1975,7 @@ Retry:
Public Function McInstallLoader(Request As McInstallRequest, Optional DontFixLibraries As Boolean = False) As List(Of LoaderBase)
'获取缓存目录
Dim PathInstallTemp As String
- If PathTemp.Contains(" ") AndAlso Request.ForgeEntry IsNot Nothing Then
+ If PathTemp.Contains(" ") AndAlso (Request.OptiFineEntry IsNot Nothing OrElse Request.ForgeEntry IsNot Nothing OrElse Request.NeoForgeEntry IsNot Nothing) Then
PathInstallTemp = OsDrive & "ProgramData\PCL\Install\"
Else
PathInstallTemp = PathTemp & "Install\"
@@ -1996,16 +2010,21 @@ Retry:
End If
If Request.OptiFineEntry IsNot Nothing Then OptiFineFolder = TempMcFolder & "versions\" & Request.OptiFineEntry.NameVersion
Dim ForgeFolder As String = Nothing
- If Request.ForgeEntry IsNot Nothing Then Request.ForgeVersion = If(Request.ForgeVersion, Request.ForgeEntry.Version)
- If Request.ForgeVersion IsNot Nothing Then ForgeFolder = TempMcFolder & "versions\" & Request.MinecraftName & "-forge-" & Request.ForgeVersion
+ If Request.ForgeEntry IsNot Nothing Then Request.ForgeVersion = If(Request.ForgeVersion, Request.ForgeEntry.VersionName)
+ If Request.ForgeVersion IsNot Nothing Then ForgeFolder = TempMcFolder & "versions\forge-" & Request.ForgeVersion
+ Dim NeoForgeFolder As String = Nothing
+ If Request.NeoForgeEntry IsNot Nothing Then Request.NeoForgeVersion = If(Request.NeoForgeVersion, Request.NeoForgeEntry.VersionName)
+ If Request.NeoForgeVersion IsNot Nothing Then NeoForgeFolder = TempMcFolder & "versions\neoforge-" & Request.NeoForgeVersion
Dim FabricFolder As String = Nothing
If Request.FabricVersion IsNot Nothing Then FabricFolder = TempMcFolder & "versions\fabric-loader-" & Request.FabricVersion & "-" & Request.MinecraftName
Dim LiteLoaderFolder As String = Nothing
If Request.LiteLoaderEntry IsNot Nothing Then LiteLoaderFolder = TempMcFolder & "versions\" & Request.MinecraftName & "-LiteLoader"
- 'OptiFine 是否作为 Mod 进行下载
- Dim OptiFineAsMod As Boolean =
- (Request.OptiFineEntry IsNot Nothing OrElse Request.OptiFineVersion IsNot Nothing) AndAlso Request.FabricVersion IsNot Nothing
+ '判断 OptiFine 是否作为 Mod 进行下载
+ Dim MinecraftCode As Integer = If(Request.MinecraftName.Contains("."), Request.MinecraftName.Split(".")(1), 99)
+ Dim OptiFineAsMod As Boolean = Request.OptiFineEntry IsNot Nothing AndAlso '1. 选择了 OptiFine
+ (Request.FabricVersion IsNot Nothing OrElse '2. 选择了 Fabric...
+ (Request.ForgeEntry IsNot Nothing AndAlso MinecraftCode >= 14 AndAlso MinecraftCode <= 15)) '...或者 Forge 1.14~15(#4134)
If OptiFineAsMod Then
Log("[Download] OptiFine 将作为 Mod 进行下载")
OptiFineFolder = New McVersion(OutputFolder).GetPathIndie(True) & "mods\"
@@ -2014,6 +2033,7 @@ Retry:
'记录日志
If OptiFineFolder IsNot Nothing Then Log("[Download] OptiFine 缓存:" & OptiFineFolder)
If ForgeFolder IsNot Nothing Then Log("[Download] Forge 缓存:" & ForgeFolder)
+ If NeoForgeFolder IsNot Nothing Then Log("[Download] NeoForge 缓存:" & NeoForgeFolder)
If FabricFolder IsNot Nothing Then Log("[Download] Fabric 缓存:" & FabricFolder)
If LiteLoaderFolder IsNot Nothing Then Log("[Download] LiteLoader 缓存:" & LiteLoaderFolder)
Log("[Download] 对应的原版版本:" & Request.MinecraftName)
@@ -2048,7 +2068,11 @@ Retry:
End If
'Forge
If Request.ForgeVersion IsNot Nothing Then
- LoaderList.Add(New LoaderCombo(Of String)("下载 Forge " & Request.ForgeVersion, McDownloadForgeLoader(Request.ForgeVersion, Request.MinecraftName, Request.ForgeEntry, TempMcFolder, ClientLoader, Request.TargetVersionFolder, False)) With {.Show = False, .ProgressWeight = 25, .Block = Request.FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing})
+ LoaderList.Add(New LoaderCombo(Of String)("下载 Forge " & Request.ForgeVersion, McDownloadForgelikeLoader(False, Request.ForgeVersion, "forge-" & Request.ForgeVersion, Request.MinecraftName, Request.ForgeEntry, TempMcFolder, ClientLoader, Request.TargetVersionFolder)) With {.Show = False, .ProgressWeight = 25, .Block = Request.FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing AndAlso Request.NeoForgeEntry Is Nothing})
+ End If
+ 'NeoForge
+ If Request.NeoForgeVersion IsNot Nothing Then
+ LoaderList.Add(New LoaderCombo(Of String)("下载 NeoForge " & Request.NeoForgeVersion, McDownloadForgelikeLoader(True, Request.NeoForgeVersion, "neoforge-" & Request.NeoForgeVersion, Request.MinecraftName, Request.NeoForgeEntry, TempMcFolder, ClientLoader, Request.TargetVersionFolder)) With {.Show = False, .ProgressWeight = 25, .Block = Request.ForgeEntry Is Nothing AndAlso Request.FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing})
End If
'LiteLoader
If Request.LiteLoaderEntry IsNot Nothing Then
@@ -2061,14 +2085,14 @@ Retry:
'合并安装
LoaderList.Add(New LoaderTask(Of String, String)("安装游戏",
Sub(Task As LoaderTask(Of String, String))
- InstallMerge(OutputFolder, OutputFolder, OptiFineFolder, OptiFineAsMod, ForgeFolder, Request.ForgeVersion, FabricFolder, LiteLoaderFolder)
+ InstallMerge(OutputFolder, OutputFolder, OptiFineFolder, OptiFineAsMod, ForgeFolder, Request.ForgeVersion, NeoForgeFolder, Request.NeoForgeVersion, FabricFolder, LiteLoaderFolder)
Task.Progress = 0.3
If Directory.Exists(TempMcFolder & "libraries") Then CopyDirectory(TempMcFolder & "libraries", PathMcFolder & "libraries")
If Directory.Exists(TempMcFolder & "mods") Then CopyDirectory(TempMcFolder & "mods", PathMcFolder & "mods")
End Sub) With {.ProgressWeight = 2, .Block = True})
'补全文件
If Not DontFixLibraries AndAlso
- (Request.OptiFineEntry IsNot Nothing OrElse (Request.ForgeVersion IsNot Nothing AndAlso Request.ForgeVersion.Before(".") >= 20) OrElse Request.FabricVersion IsNot Nothing OrElse Request.LiteLoaderEntry IsNot Nothing) Then
+ (Request.OptiFineEntry IsNot Nothing OrElse (Request.ForgeVersion IsNot Nothing AndAlso Request.ForgeVersion.Before(".") >= 20) OrElse Request.NeoForgeVersion IsNot Nothing OrElse Request.FabricVersion IsNot Nothing OrElse Request.LiteLoaderEntry IsNot Nothing) Then
Dim LoadersLib As New List(Of LoaderBase)
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(OutputFolder))) With {.ProgressWeight = 1, .Show = False})
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
@@ -2084,17 +2108,18 @@ Retry:
'''
''' 将多个版本 Json 进行合并,如果目标已存在则直接覆盖。失败会抛出异常。
'''
- Private Sub InstallMerge(OutputFolder As String, MinecraftFolder As String, Optional OptiFineFolder As String = Nothing, Optional OptiFineAsMod As Boolean = False, Optional ForgeFolder As String = Nothing, Optional ForgeVersion As String = Nothing, Optional FabricFolder As String = Nothing, Optional LiteLoaderFolder As String = Nothing)
+ Private Sub InstallMerge(OutputFolder As String, MinecraftFolder As String, Optional OptiFineFolder As String = Nothing, Optional OptiFineAsMod As Boolean = False, Optional ForgeFolder As String = Nothing, Optional ForgeVersion As String = Nothing, Optional NeoForgeFolder As String = Nothing, Optional NeoForgeVersion As String = Nothing, Optional FabricFolder As String = Nothing, Optional LiteLoaderFolder As String = Nothing)
Log("[Download] 开始进行版本合并,输出:" & OutputFolder & ",Minecraft:" & MinecraftFolder &
If(OptiFineFolder IsNot Nothing, ",OptiFine:" & OptiFineFolder, "") &
If(ForgeFolder IsNot Nothing, ",Forge:" & ForgeFolder, "") &
+ If(NeoForgeFolder IsNot Nothing, ",NeoForge:" & NeoForgeFolder, "") &
If(LiteLoaderFolder IsNot Nothing, ",LiteLoader:" & LiteLoaderFolder, "") &
If(FabricFolder IsNot Nothing, ",Fabric:" & FabricFolder, ""))
Directory.CreateDirectory(OutputFolder)
- Dim HasOptiFine As Boolean = OptiFineFolder IsNot Nothing AndAlso Not OptiFineAsMod, HasForge As Boolean = ForgeFolder IsNot Nothing, HasLiteLoader As Boolean = LiteLoaderFolder IsNot Nothing, HasFabric As Boolean = FabricFolder IsNot Nothing
- Dim OutputName As String, MinecraftName As String, OptiFineName As String, ForgeName As String, LiteLoaderName As String, FabricName As String
- Dim OutputJsonPath As String, MinecraftJsonPath As String, OptiFineJsonPath As String = Nothing, ForgeJsonPath As String = Nothing, LiteLoaderJsonPath As String = Nothing, FabricJsonPath As String = Nothing
+ Dim HasOptiFine As Boolean = OptiFineFolder IsNot Nothing AndAlso Not OptiFineAsMod, HasForge As Boolean = ForgeFolder IsNot Nothing, HasNeoForge As Boolean = NeoForgeFolder IsNot Nothing, HasLiteLoader As Boolean = LiteLoaderFolder IsNot Nothing, HasFabric As Boolean = FabricFolder IsNot Nothing
+ Dim OutputName As String, MinecraftName As String, OptiFineName As String, ForgeName As String, NeoForgeName As String, LiteLoaderName As String, FabricName As String
+ Dim OutputJsonPath As String, MinecraftJsonPath As String, OptiFineJsonPath As String = Nothing, ForgeJsonPath As String = Nothing, NeoForgeJsonPath As String = Nothing, LiteLoaderJsonPath As String = Nothing, FabricJsonPath As String = Nothing
Dim OutputJar As String, MinecraftJar As String
#Region "初始化路径信息"
If Not OutputFolder.EndsWithF("\") Then OutputFolder += "\"
@@ -2119,6 +2144,12 @@ Retry:
ForgeJsonPath = ForgeFolder & ForgeName & ".json"
End If
+ If HasNeoForge Then
+ If Not NeoForgeFolder.EndsWithF("\") Then NeoForgeFolder += "\"
+ NeoForgeName = GetFolderNameFromPath(NeoForgeFolder)
+ NeoForgeJsonPath = NeoForgeFolder & NeoForgeName & ".json"
+ End If
+
If HasLiteLoader Then
If Not LiteLoaderFolder.EndsWithF("\") Then LiteLoaderFolder += "\"
LiteLoaderName = GetFolderNameFromPath(LiteLoaderFolder)
@@ -2132,7 +2163,7 @@ Retry:
End If
#End Region
- Dim OutputJson As JObject, MinecraftJson As JObject, OptiFineJson As JObject = Nothing, ForgeJson As JObject = Nothing, LiteLoaderJson As JObject = Nothing, FabricJson As JObject = Nothing
+ Dim OutputJson As JObject, MinecraftJson As JObject, OptiFineJson As JObject = Nothing, ForgeJson As JObject = Nothing, NeoForgeJson As JObject = Nothing, LiteLoaderJson As JObject = Nothing, FabricJson As JObject = Nothing
#Region "读取文件并检查文件是否合规"
Dim MinecraftJsonText As String = ReadFile(MinecraftJsonPath)
If Not MinecraftJsonText.StartsWithF("{") Then Throw New Exception("Minecraft json 有误,地址:" & MinecraftJsonPath & ",前段内容:" & MinecraftJsonText.Substring(0, Math.Min(MinecraftJsonText.Length, 1000)))
@@ -2150,6 +2181,12 @@ Retry:
ForgeJson = GetJson(ForgeJsonText)
End If
+ If HasNeoForge Then
+ Dim NeoForgeJsonText As String = ReadFile(NeoForgeJsonPath)
+ If Not NeoForgeJsonText.StartsWithF("{") Then Throw New Exception("NeoForge json 有误,地址:" & NeoForgeJsonPath & ",前段内容:" & NeoForgeJsonText.Substring(0, Math.Min(NeoForgeJsonText.Length, 1000)))
+ NeoForgeJson = GetJson(NeoForgeJsonText)
+ End If
+
If HasLiteLoader Then
Dim LiteLoaderJsonText As String = ReadFile(LiteLoaderJsonPath)
If Not LiteLoaderJsonText.StartsWithF("{") Then Throw New Exception("LiteLoader json 有误,地址:" & LiteLoaderJsonPath & ",前段内容:" & LiteLoaderJsonText.Substring(0, Math.Min(LiteLoaderJsonText.Length, 1000)))
@@ -2163,12 +2200,13 @@ Retry:
End If
#End Region
-#Region "处理 Json 文件"
+#Region "处理 JSON 文件"
'获取 minecraftArguments
Dim AllArguments As String =
If(MinecraftJson("minecraftArguments"), " ").ToString & " " &
If(OptiFineJson IsNot Nothing, If(OptiFineJson("minecraftArguments"), " ").ToString, " ") & " " &
If(ForgeJson IsNot Nothing, If(ForgeJson("minecraftArguments"), " ").ToString, " ") & " " &
+ If(NeoForgeJson IsNot Nothing, If(NeoForgeJson("minecraftArguments"), " ").ToString, " ") & " " &
If(LiteLoaderJson IsNot Nothing, If(LiteLoaderJson("minecraftArguments"), " ").ToString, " ")
'分割参数字符串
Dim RawArguments As List(Of String) = AllArguments.Split(" ").Where(Function(l) l <> "").Select(Function(l) l.Trim).ToList
@@ -2198,6 +2236,12 @@ Retry:
ForgeJson.Remove("time")
OutputJson.Merge(ForgeJson)
End If
+ If HasNeoForge Then
+ '合并 NeoForge
+ NeoForgeJson.Remove("releaseTime")
+ NeoForgeJson.Remove("time")
+ OutputJson.Merge(NeoForgeJson)
+ End If
If HasLiteLoader Then
'合并 LiteLoader
LiteLoaderJson.Remove("releaseTime")
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadClient.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadClient.xaml.vb
index 519b862..5c041d1 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadClient.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadClient.xaml.vb
@@ -43,6 +43,12 @@
Type = "愚人节版"
Version("type") = "special"
Version.Add("lore", GetMcFoolName(Version("id")))
+ Case Else '4/1 自动视作愚人节版
+ Dim ReleaseDate = Version("releaseTime").Value(Of Date).ToUniversalTime().AddHours(2)
+ If ReleaseDate.Month = 4 AndAlso ReleaseDate.Day = 1 Then
+ Type = "愚人节版"
+ Version("type") = "special"
+ End If
End Select
Case "special"
'已被处理的愚人节版
@@ -56,7 +62,7 @@
'排序
For i = 0 To Dict.Keys.Count - 1
Dict(Dict.Keys(i)) = Sort(Dict.Values(i),
- Function(a, b) a("releaseTime").Value(Of Date) > b("releaseTime").Value(Of Date))
+ Function(a, b) a("releaseTime").Value(Of Date) > b("releaseTime").Value(Of Date))
Next
'清空当前
PanMain.Children.Clear()
@@ -87,7 +93,7 @@
PanMain.Children.Add(NewCard)
Next
Catch ex As Exception
- Log(ex, "可视化版本列表出错", LogLevel.Feedback)
+ Log(ex, "可视化 MC 版本列表出错", LogLevel.Feedback)
End Try
End Sub
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb
index 1fa91e3..60f54bd 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb
@@ -170,24 +170,25 @@
Dim LogoFileAddress As String = PathTemp & "CompLogo\" & GetHash(CompItem.Logo) & ".png"
Loaders.Add(New LoaderDownload("下载整合包文件", New List(Of NetFile) From {File.ToNetFile(Target)}) With {.ProgressWeight = 10, .Block = True})
Loaders.Add(New LoaderTask(Of Integer, Integer)("准备安装整合包",
- Sub()
- If Not ModpackInstall(Target, VersionName, Logo:=If(IO.File.Exists(LogoFileAddress), LogoFileAddress, Nothing)) Then
- Throw New Exception("整合包安装出现异常!")
- End If
- End Sub) With {.ProgressWeight = 0.1})
+ Sub()
+ If ModpackInstall(Target, VersionName, Logo:=If(IO.File.Exists(LogoFileAddress), LogoFileAddress, Nothing)) Is Nothing Then
+ Throw New Exception("整合包安装出现异常!")
+ End If
+ End Sub) With {.ProgressWeight = 0.1})
'启动
- Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = Sub(MyLoader)
- Select Case MyLoader.State
- Case LoadState.Failed
- Hint(MyLoader.Name & "失败:" & GetExceptionSummary(MyLoader.Error), HintType.Critical)
- Case LoadState.Aborted
- Hint(MyLoader.Name & "已取消!", HintType.Info)
- Case LoadState.Loading
- Exit Sub '不重新加载版本列表
- End Select
- McInstallFailedClearFolder(MyLoader)
- End Sub}
+ Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged =
+ Sub(MyLoader)
+ Select Case MyLoader.State
+ Case LoadState.Failed
+ Hint(MyLoader.Name & "失败:" & GetExceptionSummary(MyLoader.Error), HintType.Critical)
+ Case LoadState.Aborted
+ Hint(MyLoader.Name & "已取消!", HintType.Info)
+ Case LoadState.Loading
+ Exit Sub '不重新加载版本列表
+ End Select
+ McInstallFailedClearFolder(MyLoader)
+ End Sub}
Loader.Start(PathMcFolder & "versions\" & VersionName & "\")
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
@@ -197,7 +198,7 @@
Log(ex, "下载资源整合包失败", LogLevel.Feedback)
End Try
End Sub
- 'Mod 下载;整合包另存为
+ 'Mod、资源包下载;整合包另存为
Public Shared CachedFolder As String = Nothing '仅在本次缓存的下载文件夹
Public Sub Save_Click(sender As Object, e As EventArgs)
Dim File As CompFile = If(TypeOf sender Is MyListItem, sender, sender.Parent).Tag
@@ -211,10 +212,10 @@
'获取 Mod 所需的加载器种类
Dim AllowForge As Boolean? = Nothing, AllowFabric As Boolean? = Nothing
If File.ModLoaders.Any Then '从文件中获取
- AllowForge = File.ModLoaders.Contains(CompModLoaderType.Forge)
+ AllowForge = File.ModLoaders.Contains(CompModLoaderType.Forge) OrElse File.ModLoaders.Contains(CompModLoaderType.NeoForge)
AllowFabric = File.ModLoaders.Contains(CompModLoaderType.Fabric)
ElseIf Project.ModLoaders.Any Then '从工程中获取
- AllowForge = Project.ModLoaders.Contains(CompModLoaderType.Forge)
+ AllowForge = Project.ModLoaders.Contains(CompModLoaderType.Forge) OrElse File.ModLoaders.Contains(CompModLoaderType.NeoForge)
AllowFabric = Project.ModLoaders.Contains(CompModLoaderType.Fabric)
End If
If AllowForge IsNot Nothing AndAlso Not AllowForge AndAlso
@@ -230,7 +231,7 @@
If File.GameVersions.Any(Function(v) v.Contains(".")) AndAlso
Not File.GameVersions.Any(Function(v) v.Contains(".") AndAlso v.Split(".")(1) = Version.Version.McCodeMain.ToString) Then Return False
If AllowForge Is Nothing OrElse AllowFabric Is Nothing Then Return True
- If AllowForge AndAlso Version.Version.HasForge Then Return True
+ If AllowForge AndAlso (Version.Version.HasForge OrElse Version.Version.HasNeoForge) Then Return True
If AllowFabric AndAlso Version.Version.HasFabric Then Return True
Return False
End Function
@@ -260,10 +261,11 @@
Log("[Comp] 由于当前版本不兼容,使用当前的 MC 文件夹作为默认下载位置")
End If
Else '选择 Mod 数量最多的版本
- Dim SelectedVersion = SuitableVersions.OrderBy(Function(v)
- Dim Info As New DirectoryInfo(v.PathIndie & "mods\")
- Return If(Info.Exists, Info.GetFiles().Length, -1)
- End Function).LastOrDefault()
+ Dim SelectedVersion = SuitableVersions.OrderBy(
+ Function(v)
+ Dim Info As New DirectoryInfo(v.PathIndie & "mods\")
+ Return If(Info.Exists, Info.GetFiles().Length, -1)
+ End Function).LastOrDefault()
DefaultFolder = SelectedVersion.PathIndie & "mods\"
Directory.CreateDirectory(DefaultFolder)
Log("[Comp] 使用适合的游戏版本作为默认下载位置(" & SelectedVersion.Name & ")")
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadForge.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadForge.xaml.vb
index 78541a0..354fe86 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadForge.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadForge.xaml.vb
@@ -33,7 +33,7 @@
' PanMain.Children.Insert(0, CardWarn)
'End If
Catch ex As Exception
- Log(ex, "可视化版本列表出错", LogLevel.Feedback)
+ Log(ex, "可视化 Forge 版本列表出错", LogLevel.Feedback)
End Try
End Sub
@@ -55,10 +55,6 @@
Card.StackInstall()
End Sub
- Public Sub DownloadStart(sender As MyListItem, e As Object)
- McDownloadForge(sender.Tag)
- End Sub
-
'介绍栏
Private Sub BtnWeb_Click(sender As Object, e As EventArgs) Handles BtnWeb.Click
OpenWebsite("https://files.minecraftforge.net")
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml
index b6b6dc5..6c7a800 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml
@@ -20,6 +20,7 @@
+
@@ -79,6 +80,24 @@
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -178,6 +197,7 @@
+
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb
index d7ef0bc..2230ba6 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb
@@ -10,6 +10,7 @@
DlOptiFineListLoader.Start()
DlLiteLoaderListLoader.Start()
DlFabricListLoader.Start()
+ DlNeoForgeListLoader.Start()
'重载预览
TextSelectName.ValidateRules = New ObjectModel.Collection(Of Validate) From {New ValidateFolderName(PathMcFolder & "versions")}
@@ -26,6 +27,7 @@
LoadLiteLoader.State = DlLiteLoaderListLoader
LoadFabric.State = DlFabricListLoader
LoadFabricApi.State = DlFabricApiLoader
+ LoadNeoForge.State = DlNeoForgeListLoader
LoadOptiFabric.State = DlOptiFabricLoader
End Sub
@@ -51,6 +53,7 @@
CardOptiFine.IsSwaped = True
CardLiteLoader.IsSwaped = True
CardForge.IsSwaped = True
+ CardNeoForge.IsSwaped = True
CardFabric.IsSwaped = True
CardFabricApi.IsSwaped = True
CardOptiFabric.IsSwaped = True
@@ -80,32 +83,36 @@
AniStart({
AaOpacity(PanMinecraft, -PanMinecraft.Opacity, 100, 10),
AaTranslateX(PanMinecraft, -50 - CType(PanMinecraft.RenderTransform, TranslateTransform).X, 110, 10),
- AaCode(Sub()
- PanBack.ScrollToHome()
- TextSelectName.Validate()
- OptiFine_Loaded()
- LiteLoader_Loaded()
- Forge_Loaded()
- Fabric_Loaded()
- FabricApi_Loaded()
- OptiFabric_Loaded()
- SelectReload()
- End Sub, After:=True),
+ AaCode(
+ Sub()
+ PanBack.ScrollToHome()
+ TextSelectName.Validate()
+ OptiFine_Loaded()
+ LiteLoader_Loaded()
+ Forge_Loaded()
+ NeoForge_Loaded()
+ Fabric_Loaded()
+ FabricApi_Loaded()
+ OptiFabric_Loaded()
+ SelectReload()
+ End Sub, After:=True),
AaOpacity(PanSelect, 1 - PanSelect.Opacity, 250, 150),
AaTranslateX(PanSelect, -CType(PanSelect.RenderTransform, TranslateTransform).X, 500, 150, Ease:=New AniEaseOutBack(AniEasePower.Weak)),
- AaCode(Sub()
- PanMinecraft.Visibility = Visibility.Collapsed
- PanBack.IsHitTestVisible = True
- '初始化 Binding
- If IsFirstLoaded Then Exit Sub
- IsFirstLoaded = True
- BtnOptiFineClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardOptiFine.MainTextBlock, .Mode = BindingMode.OneWay})
- BtnLiteLoaderClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardLiteLoader.MainTextBlock, .Mode = BindingMode.OneWay})
- BtnForgeClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardForge.MainTextBlock, .Mode = BindingMode.OneWay})
- BtnFabricClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardFabric.MainTextBlock, .Mode = BindingMode.OneWay})
- BtnFabricApiClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardFabricApi.MainTextBlock, .Mode = BindingMode.OneWay})
- BtnOptiFabricClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardOptiFabric.MainTextBlock, .Mode = BindingMode.OneWay})
- End Sub,, True)
+ AaCode(
+ Sub()
+ PanMinecraft.Visibility = Visibility.Collapsed
+ PanBack.IsHitTestVisible = True
+ '初始化 Binding
+ If IsFirstLoaded Then Exit Sub
+ IsFirstLoaded = True
+ BtnOptiFineClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardOptiFine.MainTextBlock, .Mode = BindingMode.OneWay})
+ BtnLiteLoaderClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardLiteLoader.MainTextBlock, .Mode = BindingMode.OneWay})
+ BtnForgeClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardForge.MainTextBlock, .Mode = BindingMode.OneWay})
+ BtnNeoForgeClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardNeoForge.MainTextBlock, .Mode = BindingMode.OneWay})
+ BtnFabricClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardFabric.MainTextBlock, .Mode = BindingMode.OneWay})
+ BtnFabricApiClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardFabricApi.MainTextBlock, .Mode = BindingMode.OneWay})
+ BtnOptiFabricClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardOptiFabric.MainTextBlock, .Mode = BindingMode.OneWay})
+ End Sub,, True)
}, "FrmDownloadInstall SelectPageSwitch", True)
End Sub
Public Sub ExitSelectPage()
@@ -213,6 +220,26 @@
End If
End Sub
+ 'NeoForge
+ Private SelectedNeoForge As DlNeoForgeListEntry = Nothing
+ Private Sub SetNeoForgeInfoShow(IsShow As String)
+ If PanNeoForgeInfo.Tag = IsShow Then Exit Sub
+ PanNeoForgeInfo.Tag = IsShow
+ If IsShow = "True" Then
+ '显示信息栏
+ AniStart({
+ AaTranslateY(PanNeoForgeInfo, -CType(PanNeoForgeInfo.RenderTransform, TranslateTransform).Y, 270, 100, Ease:=New AniEaseOutBack),
+ AaOpacity(PanNeoForgeInfo, 1 - PanNeoForgeInfo.Opacity, 100, 90)
+ }, "SetNeoForgeInfoShow")
+ Else
+ '隐藏信息栏
+ AniStart({
+ AaTranslateY(PanNeoForgeInfo, 6 - CType(PanNeoForgeInfo.RenderTransform, TranslateTransform).Y, 200),
+ AaOpacity(PanNeoForgeInfo, -PanNeoForgeInfo.Opacity, 100)
+ }, "SetNeoForgeInfoShow")
+ End If
+ End Sub
+
'Fabric
Private SelectedFabric As String = Nothing
Private Sub SetFabricInfoShow(IsShow As String)
@@ -277,7 +304,7 @@
'''
''' 重载已选择的项目的显示。
'''
- Private Sub SelectReload() Handles CardOptiFine.Swap, LoadOptiFine.StateChanged, CardForge.Swap, LoadForge.StateChanged, CardFabric.Swap, LoadFabric.StateChanged, CardFabricApi.Swap, LoadFabricApi.StateChanged, CardOptiFabric.Swap, LoadOptiFabric.StateChanged, CardLiteLoader.Swap, LoadLiteLoader.StateChanged
+ Private Sub SelectReload() Handles CardOptiFine.Swap, LoadOptiFine.StateChanged, CardForge.Swap, LoadForge.StateChanged, CardNeoForge.Swap, LoadNeoForge.StateChanged, CardFabric.Swap, LoadFabric.StateChanged, CardFabricApi.Swap, LoadFabricApi.StateChanged, CardOptiFabric.Swap, LoadOptiFabric.StateChanged, CardLiteLoader.Swap, LoadLiteLoader.StateChanged
If SelectedMinecraftId Is Nothing OrElse IsReloading Then Exit Sub
IsReloading = True
'主预览
@@ -338,9 +365,30 @@
Else
BtnForgeClear.Visibility = Visibility.Visible
ImgForge.Visibility = Visibility.Visible
- LabForge.Text = SelectedForge.Version
+ LabForge.Text = SelectedForge.VersionName
LabForge.Foreground = ColorGray1
End If
+ 'NeoForge
+ If Not SelectedMinecraftId.Contains("1.") OrElse Val(SelectedMinecraftId.Split(".")(1)) <= 19 Then
+ CardNeoForge.Visibility = Visibility.Collapsed
+ Else
+ CardNeoForge.Visibility = Visibility.Visible
+ Dim NeoForgeError As String = LoadNeoForgeGetError()
+ CardNeoForge.MainSwap.Visibility = If(NeoForgeError Is Nothing, Visibility.Visible, Visibility.Collapsed)
+ If NeoForgeError IsNot Nothing Then CardNeoForge.IsSwaped = True
+ SetNeoForgeInfoShow(CardNeoForge.IsSwaped)
+ If SelectedNeoForge Is Nothing Then
+ BtnNeoForgeClear.Visibility = Visibility.Collapsed
+ ImgNeoForge.Visibility = Visibility.Collapsed
+ LabNeoForge.Text = If(NeoForgeError, "点击选择")
+ LabNeoForge.Foreground = ColorGray4
+ Else
+ BtnNeoForgeClear.Visibility = Visibility.Visible
+ ImgNeoForge.Visibility = Visibility.Visible
+ LabNeoForge.Text = SelectedNeoForge.VersionName
+ LabNeoForge.Foreground = ColorGray1
+ End If
+ End If
'Fabric
If SelectedMinecraftId.Contains("1.") AndAlso Val(SelectedMinecraftId.Split(".")(1)) <= 13 Then
CardFabric.Visibility = Visibility.Collapsed
@@ -411,9 +459,16 @@
HintFabricAPI.Visibility = Visibility.Collapsed
End If
If SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing AndAlso SelectedOptiFabric Is Nothing Then
- HintOptiFabric.Visibility = Visibility.Visible
+ If SelectedMinecraftId.StartsWith("1.14") OrElse SelectedMinecraftId.StartsWith("1.15") Then
+ HintOptiFabric.Visibility = Visibility.Collapsed
+ HintOptiFabricOld.Visibility = Visibility.Visible
+ Else
+ HintOptiFabric.Visibility = Visibility.Visible
+ HintOptiFabricOld.Visibility = Visibility.Collapsed
+ End If
Else
HintOptiFabric.Visibility = Visibility.Collapsed
+ HintOptiFabricOld.Visibility = Visibility.Collapsed
End If
If SelectedMinecraftId.Contains("1.") AndAlso Val(SelectedMinecraftId.Split(".")(1)) >= 16 AndAlso SelectedOptiFine IsNot Nothing AndAlso
(SelectedForge IsNot Nothing OrElse SelectedFabric IsNot Nothing) Then
@@ -434,6 +489,7 @@
SelectedOptiFine = Nothing
SelectedLiteLoader = Nothing
SelectedForge = Nothing
+ SelectedNeoForge = Nothing
SelectedFabric = Nothing
SelectedFabricApi = Nothing
SelectedOptiFabric = Nothing
@@ -449,7 +505,10 @@
Name += "-Fabric " & SelectedFabric.Replace("+build", "")
End If
If SelectedForge IsNot Nothing Then
- Name += "-Forge_" & SelectedForge.Version
+ Name += "-Forge_" & SelectedForge.VersionName
+ End If
+ If SelectedNeoForge IsNot Nothing Then
+ Name += "-NeoForge_" & SelectedNeoForge.VersionName
End If
If SelectedLiteLoader IsNot Nothing Then
Name += "-LiteLoader"
@@ -468,7 +527,10 @@
Info += ", Fabric " & SelectedFabric.Replace("+build", "")
End If
If SelectedForge IsNot Nothing Then
- Info += ", Forge " & SelectedForge.Version
+ Info += ", Forge " & SelectedForge.VersionName
+ End If
+ If SelectedNeoForge IsNot Nothing Then
+ Info += ", NeoForge " & SelectedNeoForge.VersionName
End If
If SelectedLiteLoader IsNot Nothing Then
Info += ", LiteLoader"
@@ -487,6 +549,8 @@
Return "pack://application:,,,/images/Blocks/Fabric.png"
ElseIf SelectedForge IsNot Nothing Then
Return "pack://application:,,,/images/Blocks/Anvil.png"
+ ElseIf SelectedNeoForge IsNot Nothing Then
+ Return "pack://application:,,,/images/Blocks/NeoForge.png"
ElseIf SelectedLiteLoader IsNot Nothing Then
Return "pack://application:,,,/images/Blocks/Egg.png"
ElseIf SelectedOptiFine IsNot Nothing Then
@@ -554,6 +618,12 @@
Type = "愚人节版"
Version("type") = "special"
Version.Add("lore", GetMcFoolName(Version("id")))
+ Case Else '4/1 自动视作愚人节版
+ Dim ReleaseDate = Version("releaseTime").Value(Of Date).ToUniversalTime().AddHours(2)
+ If ReleaseDate.Month = 4 AndAlso ReleaseDate.Day = 1 Then
+ Type = "愚人节版"
+ Version("type") = "special"
+ End If
End Select
Case "special"
'已被处理的愚人节版
@@ -624,6 +694,7 @@
''' 获取 OptiFine 的加载异常信息。若正常则返回 Nothing。
'''
Private Function LoadOptiFineGetError() As String
+ If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
If LoadOptiFine Is Nothing OrElse LoadOptiFine.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "正在获取版本列表……"
If LoadOptiFine.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadOptiFine.State, Object).Error.Message
'检查 Forge 1.13 - 1.14.3:全部不兼容
@@ -659,10 +730,12 @@
Private Function IsOptiFineSuitForForge(OptiFine As DlOptiFineListEntry, Forge As DlForgeVersionEntry)
If Forge.Inherit <> OptiFine.Inherit Then Return False '不是同一个大版本
If OptiFine.RequiredForgeVersion Is Nothing Then Return False '不兼容 Forge
- Return (OptiFine.RequiredForgeVersion.Contains(".") AndAlso 'XX.X.XXX
- VersionSortInteger(Forge.Version, OptiFine.RequiredForgeVersion) >= 0) OrElse
- (Not OptiFine.RequiredForgeVersion.Contains(".") AndAlso '#XXXX
- Forge.Version.After(".") >= OptiFine.RequiredForgeVersion)
+ If String.IsNullOrWhiteSpace(OptiFine.RequiredForgeVersion) Then Return True '#4183
+ If OptiFine.RequiredForgeVersion.Contains(".") Then 'XX.X.XXX
+ Return VersionSortInteger(Forge.Version.ToString, OptiFine.RequiredForgeVersion) >= 0
+ Else 'XXXX
+ Return Forge.Version.Revision >= OptiFine.RequiredForgeVersion
+ End If
End Function
'限制展开
@@ -685,11 +758,12 @@
Next
If Not Versions.Any() Then Exit Sub
'排序
- Versions = Sort(Versions, Function(Left As DlOptiFineListEntry, Right As DlOptiFineListEntry) As Boolean
- If Not Left.IsPreview AndAlso Right.IsPreview Then Return True
- If Left.IsPreview AndAlso Not Right.IsPreview Then Return False
- Return VersionSortBoolean(Left.NameDisplay, Right.NameDisplay)
- End Function)
+ Versions = Sort(Versions,
+ Function(Left As DlOptiFineListEntry, Right As DlOptiFineListEntry) As Boolean
+ If Not Left.IsPreview AndAlso Right.IsPreview Then Return True
+ If Left.IsPreview AndAlso Not Right.IsPreview Then Return False
+ Return VersionSortBoolean(Left.NameDisplay, Right.NameDisplay)
+ End Function)
'可视化
PanOptiFine.Children.Clear()
For Each Version In Versions
@@ -706,6 +780,7 @@
If SelectedForge IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, SelectedForge) Then SelectedForge = Nothing
OptiFabric_Loaded()
Forge_Loaded()
+ NeoForge_Loaded()
CardOptiFine.IsSwaped = True
SelectReload()
End Sub
@@ -715,6 +790,7 @@
CardOptiFine.IsSwaped = True
e.Handled = True
Forge_Loaded()
+ NeoForge_Loaded()
SelectReload()
End Sub
@@ -800,6 +876,7 @@
Dim NotSuitForOptiFine As Boolean = False
For Each Version In Loader.Output
If Version.Category = "universal" OrElse Version.Category = "client" Then Continue For '跳过无法自动安装的版本
+ If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
If SelectedOptiFine IsNot Nothing AndAlso
VersionSortInteger(SelectedMinecraftId, "1.13") >= 0 AndAlso VersionSortInteger("1.14.3", SelectedMinecraftId) >= 0 Then
@@ -829,16 +906,15 @@
If SelectedMinecraftId <> Loader.Input Then Exit Sub
If Loader.State <> LoadState.Finished Then Exit Sub
'获取要显示的版本
- Dim Versions As New List(Of DlForgeVersionEntry)
- Versions.AddRange(Loader.Output) '复制数组,以免 Output 在实例化后变空
+ Dim Versions = Loader.Output.ToList '复制数组,以免 Output 在实例化后变空
If Not Loader.Output.Any() Then Exit Sub
PanForge.Children.Clear()
- Versions = Sort(Versions, Function(a, b) New Version(a.Version) > New Version(b.Version)).
- Where(Function(v)
- If v.Category = "universal" OrElse v.Category = "client" Then Return False '跳过无法自动安装的版本
- If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, v) Then Return False
- Return True
- End Function).ToList
+ Versions = Sort(Versions, Function(a, b) a.Version > b.Version).Where(
+ Function(v)
+ If v.Category = "universal" OrElse v.Category = "client" Then Return False '跳过无法自动安装的版本
+ If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, v) Then Return False
+ Return True
+ End Function).ToList()
ForgeDownloadListItemPreload(PanForge, Versions, AddressOf Forge_Selected, False)
For Each Version In Versions
PanForge.Children.Add(ForgeDownloadListItem(Version, AddressOf Forge_Selected, False))
@@ -866,6 +942,67 @@
#End Region
+#Region "NeoForge 列表"
+
+ '''
+ ''' 获取 NeoForge 的加载异常信息。若正常则返回 Nothing。
+ '''
+ Private Function LoadNeoForgeGetError() As String
+ If Not SelectedMinecraftId.StartsWith("1.") Then Return "没有可用版本"
+ If SelectedOptiFine IsNot Nothing Then Return "与 OptiFine 不兼容"
+ If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
+ If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
+ If LoadNeoForge Is Nothing OrElse LoadNeoForge.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "正在获取版本列表……"
+ If LoadNeoForge.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadNeoForge.State, Object).Error.Message
+ If DlNeoForgeListLoader.Output.Value.Any(Function(v) v.Inherit = SelectedMinecraftId) Then
+ Return Nothing
+ Else
+ Return "没有可用版本"
+ End If
+ End Function
+
+ '限制展开
+ Private Sub CardNeoForge_PreviewSwap(sender As Object, e As RouteEventArgs) Handles CardNeoForge.PreviewSwap
+ If LoadNeoForgeGetError() IsNot Nothing Then e.Handled = True
+ End Sub
+
+ '''
+ ''' 尝试重新可视化 NeoForge 版本列表。
+ '''
+ Private Sub NeoForge_Loaded() Handles LoadNeoForge.StateChanged
+ Try
+ '获取版本列表
+ If DlNeoForgeListLoader.State <> LoadState.Finished Then Exit Sub
+ Dim Versions = DlNeoForgeListLoader.Output.Value.Where(Function(v) v.Inherit = SelectedMinecraftId).ToList
+ If Not Versions.Any() Then Exit Sub
+ '可视化
+ PanNeoForge.Children.Clear()
+ NeoForgeDownloadListItemPreload(PanNeoForge, Versions, AddressOf NeoForge_Selected, False)
+ For Each Version In Versions
+ PanNeoForge.Children.Add(NeoForgeDownloadListItem(Version, AddressOf NeoForge_Selected, False))
+ Next
+ Catch ex As Exception
+ Log(ex, "可视化 NeoForge 安装版本列表出错", LogLevel.Feedback)
+ End Try
+ End Sub
+
+ '选择与清除
+ Private Sub NeoForge_Selected(sender As MyListItem, e As EventArgs)
+ SelectedNeoForge = sender.Tag
+ CardNeoForge.IsSwaped = True
+ OptiFine_Loaded()
+ SelectReload()
+ End Sub
+ Private Sub NeoForge_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnNeoForgeClear.MouseLeftButtonUp
+ SelectedNeoForge = Nothing
+ CardNeoForge.IsSwaped = True
+ e.Handled = True
+ OptiFine_Loaded()
+ SelectReload()
+ End Sub
+
+#End Region
+
#Region "Fabric 列表"
'''
@@ -877,7 +1014,7 @@
For Each Version As JObject In DlFabricListLoader.Output.Value("game")
If Version("version").ToString = SelectedMinecraftId.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3") Then
If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
- 'If SelectedOptiFine IsNot Nothing Then Return "与 OptiFine 不兼容"
+ If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
Return Nothing
End If
Next
@@ -1064,6 +1201,7 @@
''' 获取 OptiFabric 的加载异常信息。若正常则返回 Nothing。
'''
Private Function LoadOptiFabricGetError() As String
+ If SelectedMinecraftId.StartsWith("1.14") OrElse SelectedMinecraftId.StartsWith("1.15") Then Return "不兼容老版本 Fabric,请手动下载 OptiFabric Origins"
If LoadOptiFabric Is Nothing OrElse LoadOptiFabric.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "正在获取版本列表……"
If LoadOptiFabric.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadOptiFabric.State, Object).Error.Message
If DlOptiFabricLoader.Output Is Nothing Then
@@ -1109,7 +1247,8 @@
PanOptiFabric.Children.Add(OptiFabricDownloadListItem(Version, AddressOf OptiFabric_Selected))
Next
'自动选择 OptiFabric
- If Not AutoSelectedOptiFabric Then
+ If Not AutoSelectedOptiFabric AndAlso
+ Not (SelectedMinecraftId.StartsWith("1.14") OrElse SelectedMinecraftId.StartsWith("1.15")) Then '1.14~15 不自动选择
AutoSelectedOptiFabric = True
Log($"[Download] 已自动选择 OptiFabric:{CType(PanOptiFabric.Children(0), MyListItem).Title}")
OptiFabric_Selected(PanOptiFabric.Children(0), Nothing)
@@ -1141,7 +1280,7 @@
End Sub
Private Sub BtnSelectStart_Click() Handles BtnSelectStart.Click
'确认版本隔离
- If (SelectedForge IsNot Nothing OrElse SelectedFabric IsNot Nothing) AndAlso
+ If (SelectedForge IsNot Nothing OrElse SelectedNeoForge IsNot Nothing OrElse SelectedFabric IsNot Nothing) AndAlso
(Setup.Get("LaunchArgumentIndie") = 0 OrElse Setup.Get("LaunchArgumentIndie") = 2) Then
If MyMsgBox("你尚未开启版本隔离,这会导致多个 MC 共用同一个 Mod 文件夹。" & vbCrLf &
"因此在切换 MC 版本时,MC 会因为读取到与当前版本不符的 Mod 而崩溃。" & vbCrLf &
@@ -1157,6 +1296,7 @@
.MinecraftName = SelectedMinecraftId,
.OptiFineEntry = SelectedOptiFine,
.ForgeEntry = SelectedForge,
+ .NeoForgeEntry = SelectedNeoForge,
.FabricVersion = SelectedFabric,
.FabricApi = SelectedFabricApi,
.OptiFabric = SelectedOptiFabric,
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml
index da78a28..8a64667 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml
@@ -43,39 +43,47 @@
-
+
-
+
-
-
+
-
+
-
+
+
+
+
+
+
+
+
+
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml.vb
index da173ad..2658c33 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml.vb
@@ -10,7 +10,7 @@
'''
''' 勾选事件改变页面。
'''
- Private Sub PageCheck(sender As MyListItem, e As RouteEventArgs) Handles ItemInstall.Check, ItemClient.Check, ItemOptiFine.Check, ItemForge.Check, ItemLiteLoader.Check, ItemMod.Check, ItemFabric.Check, ItemPack.Check
+ Private Sub PageCheck(sender As MyListItem, e As RouteEventArgs) Handles ItemInstall.Check, ItemClient.Check, ItemOptiFine.Check, ItemForge.Check, ItemNeoForge.Check, ItemLiteLoader.Check, ItemMod.Check, ItemFabric.Check, ItemPack.Check
'尚未初始化控件属性时,sender.Tag 为 Nothing,会导致切换到页面 0
'若使用 IsLoaded,则会导致模拟点击不被执行(模拟点击切换页面时,控件的 IsLoaded 为 False)
If sender.Tag IsNot Nothing Then PageChange(Val(sender.Tag))
@@ -31,6 +31,9 @@
Case FormMain.PageSubType.DownloadForge
If FrmDownloadForge Is Nothing Then FrmDownloadForge = New PageDownloadForge
Return FrmDownloadForge
+ Case FormMain.PageSubType.DownloadNeoForge
+ If FrmDownloadNeoForge Is Nothing Then FrmDownloadNeoForge = New PageDownloadNeoForge
+ Return FrmDownloadNeoForge
Case FormMain.PageSubType.DownloadLiteLoader
If FrmDownloadLiteLoader Is Nothing Then FrmDownloadLiteLoader = New PageDownloadLiteLoader
Return FrmDownloadLiteLoader
@@ -69,17 +72,19 @@
FrmMain.PageRight = Target
CType(FrmMain.PanMainRight.Child, MyPageRight).PageOnExit()
AniStart({
- AaCode(Sub()
- CType(FrmMain.PanMainRight.Child, MyPageRight).PageOnForceExit()
- FrmMain.PanMainRight.Child = FrmMain.PageRight
- FrmMain.PageRight.Opacity = 0
- End Sub, 130),
- AaCode(Sub()
- '延迟触发页面通用动画,以使得在 Loaded 事件中加载的控件得以处理
- FrmMain.PageRight.Opacity = 1
- FrmMain.PageRight.PageOnEnter()
- End Sub, 30, True)
- }, "PageLeft PageChange")
+ AaCode(
+ Sub()
+ CType(FrmMain.PanMainRight.Child, MyPageRight).PageOnForceExit()
+ FrmMain.PanMainRight.Child = FrmMain.PageRight
+ FrmMain.PageRight.Opacity = 0
+ End Sub, 130),
+ AaCode(
+ Sub()
+ '延迟触发页面通用动画,以使得在 Loaded 事件中加载的控件得以处理
+ FrmMain.PageRight.Opacity = 1
+ FrmMain.PageRight.PageOnEnter()
+ End Sub, 30, True)
+ }, "PageLeft PageChange")
End Sub
#End Region
@@ -91,6 +96,7 @@
DlClientListLoader.Start(IsForceRestart:=True)
DlOptiFineListLoader.Start(IsForceRestart:=True)
DlForgeListLoader.Start(IsForceRestart:=True)
+ DlNeoForgeListLoader.Start(IsForceRestart:=True)
DlLiteLoaderListLoader.Start(IsForceRestart:=True)
DlFabricListLoader.Start(IsForceRestart:=True)
DlFabricApiLoader.Start(IsForceRestart:=True)
@@ -117,6 +123,9 @@
Case FormMain.PageSubType.DownloadForge
DlForgeListLoader.Start(IsForceRestart:=True)
ItemForge.Checked = True
+ Case FormMain.PageSubType.DownloadNeoForge
+ DlNeoForgeListLoader.Start(IsForceRestart:=True)
+ ItemNeoForge.Checked = True
Case FormMain.PageSubType.DownloadLiteLoader
DlLiteLoaderListLoader.Start(IsForceRestart:=True)
ItemLiteLoader.Checked = True
@@ -154,12 +163,14 @@
ItemOptiFine.Visibility = Visibility.Visible
ItemFabric.Visibility = Visibility.Visible
ItemForge.Visibility = Visibility.Visible
+ ItemNeoForge.Visibility = Visibility.Visible
ItemLiteLoader.Visibility = Visibility.Visible
- RunInThread(Sub()
- Thread.Sleep(20)
- RunInUiWait(Sub() ItemClient.SetChecked(True, True, True))
- AniControlEnabled -= 1
- End Sub)
+ RunInThread(
+ Sub()
+ Thread.Sleep(20)
+ RunInUiWait(Sub() ItemClient.SetChecked(True, True, True))
+ AniControlEnabled -= 1
+ End Sub)
End Sub
'折叠手动安装
Private Sub LabHand_Click(sender As Object, e As MouseButtonEventArgs) Handles LabHand.MouseLeftButtonUp
@@ -170,14 +181,16 @@
LabHand.Visibility = Visibility.Collapsed
ItemClient.Visibility = Visibility.Collapsed
ItemOptiFine.Visibility = Visibility.Collapsed
+ ItemNeoForge.Visibility = Visibility.Collapsed
ItemFabric.Visibility = Visibility.Collapsed
ItemForge.Visibility = Visibility.Collapsed
ItemLiteLoader.Visibility = Visibility.Collapsed
- RunInThread(Sub()
- Thread.Sleep(20)
- RunInUiWait(Sub() ItemInstall.SetChecked(True, True, True))
- AniControlEnabled -= 1
- End Sub)
+ RunInThread(
+ Sub()
+ Thread.Sleep(20)
+ RunInUiWait(Sub() ItemInstall.SetChecked(True, True, True))
+ AniControlEnabled -= 1
+ End Sub)
End Sub
End Class
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLiteLoader.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLiteLoader.xaml.vb
index 9a73bbe..ac18c47 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLiteLoader.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLiteLoader.xaml.vb
@@ -38,7 +38,7 @@
PanMain.Children.Add(NewCard)
Next
Catch ex As Exception
- Log(ex, "可视化版本列表出错", LogLevel.Feedback)
+ Log(ex, "可视化 LiteLoader 版本列表出错", LogLevel.Feedback)
End Try
End Sub
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml
index 814d1c8..978b37d 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml
@@ -33,6 +33,8 @@
+
+
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb
index b77199a..db3f168 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb
@@ -40,12 +40,14 @@
Visibility.Visible, Visibility.Collapsed)
LabPage.Text = Page + 1
BtnPageFirst.IsEnabled = Page > 1
- BtnPageFirst.Opacity = If(BtnPageFirst.IsEnabled, 1, 0.2)
+ BtnPageFirst.Opacity = If(Page > 1, 1, 0.2)
BtnPageLeft.IsEnabled = Page > 0
- BtnPageLeft.Opacity = If(BtnPageLeft.IsEnabled, 1, 0.2)
- BtnPageRight.IsEnabled = Storage.Results.Count > PageSize * (Page + 1) OrElse
- Storage.CurseForgeOffset < Storage.CurseForgeTotal OrElse Storage.ModrinthOffset < Storage.ModrinthTotal
- BtnPageRight.Opacity = If(BtnPageRight.IsEnabled, 1, 0.2)
+ BtnPageLeft.Opacity = If(Page > 0, 1, 0.2)
+ Dim IsRightEnabled As Boolean = '由于 WPF 的未知 bug,读取到的 IsEnabled 可能是错误的值(#3319)
+ Storage.Results.Count > PageSize * (Page + 1) OrElse
+ Storage.CurseForgeOffset < Storage.CurseForgeTotal OrElse Storage.ModrinthOffset < Storage.ModrinthTotal
+ BtnPageRight.IsEnabled = IsRightEnabled
+ BtnPageRight.Opacity = If(IsRightEnabled, 1, 0.2)
'错误信息
If Storage.ErrorMessage Is Nothing Then
HintError.Visibility = Visibility.Collapsed
@@ -89,11 +91,12 @@
Page = NewPage
FrmMain.BackToTop()
Log($"[Download] Mod 切换到第 {Page + 1} 页")
- RunInThread(Sub()
- Thread.Sleep(100) '等待向上滚的动画结束
- RunInUi(Sub() CardPages.IsEnabled = True)
- Loader.Start()
- End Sub)
+ RunInThread(
+ Sub()
+ Thread.Sleep(100) '等待向上滚的动画结束
+ RunInUi(Sub() CardPages.IsEnabled = True)
+ Loader.Start()
+ End Sub)
End Sub
#Region "搜索"
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadNeoForge.xaml b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadNeoForge.xaml
new file mode 100644
index 0000000..f9b7bc3
--- /dev/null
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadNeoForge.xaml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadNeoForge.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadNeoForge.xaml.vb
new file mode 100644
index 0000000..064dda5
--- /dev/null
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadNeoForge.xaml.vb
@@ -0,0 +1,34 @@
+Public Class PageDownloadNeoForge
+
+ Private Sub LoaderInit() Handles Me.Initialized
+ PageLoaderInit(Load, PanLoad, PanMain, CardTip, DlNeoForgeListLoader, AddressOf Load_OnFinish)
+ End Sub
+ Private Sub Init() Handles Me.Loaded
+ PanBack.ScrollToHome()
+ End Sub
+
+ Private Sub Load_OnFinish()
+ '结果数据化
+ Try
+ '归类
+ Dim Dict = DlNeoForgeListLoader.Output.Value.GroupBy(Function(d) d.Inherit).OrderByDescending(Function(g) g.Key).
+ ToDictionary(Function(g) g.Key, Function(g) g.ToList())
+ '清空当前
+ PanMain.Children.Clear()
+ '转化为 UI
+ For Each Pair As KeyValuePair(Of String, List(Of DlNeoForgeListEntry)) In Dict
+ If Not Pair.Value.Any() Then Continue For
+ '增加卡片
+ Dim NewCard As New MyCard With {.Title = Pair.Key & " (" & Pair.Value.Count & ")", .Margin = New Thickness(0, 0, 0, 15), .SwapType = 13}
+ Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Pair.Value}
+ NewCard.Children.Add(NewStack)
+ NewCard.SwapControl = NewStack
+ NewCard.IsSwaped = True
+ PanMain.Children.Add(NewCard)
+ Next
+ Catch ex As Exception
+ Log(ex, "可视化 NeoForge 版本列表出错", LogLevel.Feedback)
+ End Try
+ End Sub
+
+End Class
\ No newline at end of file
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadOptiFine.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadOptiFine.xaml.vb
index 0fc791c..27c2fd4 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadOptiFine.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadOptiFine.xaml.vb
@@ -13,7 +13,7 @@
'归类
Dim Dict As New Dictionary(Of String, List(Of DlOptiFineListEntry))
Dict.Add("快照版本", New List(Of DlOptiFineListEntry))
- For VersionCode As Integer = 30 To 0 Step -1
+ For VersionCode As Integer = 50 To 0 Step -1
Dict.Add("1." & VersionCode, New List(Of DlOptiFineListEntry))
Next
For Each Version As DlOptiFineListEntry In DlOptiFineListLoader.Output.Value
@@ -42,14 +42,10 @@
PanMain.Children.Add(NewCard)
Next
Catch ex As Exception
- Log(ex, "可视化版本列表出错", LogLevel.Feedback)
+ Log(ex, "可视化 OptiFine 版本列表出错", LogLevel.Feedback)
End Try
End Sub
- Public Sub DownloadStart(sender As MyListItem, e As Object)
- McDownloadOptiFine(sender.Tag)
- End Sub
-
Private Sub BtnWeb_Click(sender As Object, e As EventArgs) Handles BtnWeb.Click
OpenWebsite("https://www.optifine.net/")
End Sub
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml
index a59954f..dae0342 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml
@@ -32,6 +32,8 @@
+
+
@@ -59,7 +61,7 @@
-
+
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml.vb
index d9cbd06..6ec8a31 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml.vb
@@ -39,12 +39,14 @@
Visibility.Visible, Visibility.Collapsed)
LabPage.Text = Page + 1
BtnPageFirst.IsEnabled = Page > 1
- BtnPageFirst.Opacity = If(BtnPageFirst.IsEnabled, 1, 0.2)
+ BtnPageFirst.Opacity = If(Page > 1, 1, 0.2)
BtnPageLeft.IsEnabled = Page > 0
- BtnPageLeft.Opacity = If(BtnPageLeft.IsEnabled, 1, 0.2)
- BtnPageRight.IsEnabled = Storage.Results.Count > PageSize * (Page + 1) OrElse
- Storage.CurseForgeOffset < Storage.CurseForgeTotal OrElse Storage.ModrinthOffset < Storage.ModrinthTotal
- BtnPageRight.Opacity = If(BtnPageRight.IsEnabled, 1, 0.2)
+ BtnPageLeft.Opacity = If(Page > 0, 1, 0.2)
+ Dim IsRightEnabled As Boolean = '由于 WPF 的未知 bug,读取到的 IsEnabled 可能是错误的值(#3319)
+ Storage.Results.Count > PageSize * (Page + 1) OrElse
+ Storage.CurseForgeOffset < Storage.CurseForgeTotal OrElse Storage.ModrinthOffset < Storage.ModrinthTotal
+ BtnPageRight.IsEnabled = IsRightEnabled
+ BtnPageRight.Opacity = If(IsRightEnabled, 1, 0.2)
'错误信息
If Storage.ErrorMessage Is Nothing Then
HintError.Visibility = Visibility.Collapsed
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb
index 692bf17..068a40a 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb
@@ -241,7 +241,8 @@ Retry:
{"Translator-Chinese", "Crowdin 中文翻译者披风"}, {"Translator", "Crowdin 翻译者披风"}, {"Cobalt", "Cobalt 披风"},
{"Vanilla", "原版披风"}, {"Minecon2011", "Minecon 2011 参与者披风"}, {"Minecon2012", "Minecon 2012 参与者披风"},
{"Minecon2013", "Minecon 2013 参与者披风"}, {"Minecon2015", "Minecon 2015 参与者披风"}, {"Minecon2016", "Minecon 2016 参与者披风"},
- {"Cherry Blossom", "樱花披风"}, {"15th Anniversary", "15 周年纪念披风"}, {"Purple Heart", "紫色心形披风"}
+ {"Cherry Blossom", "樱花披风"}, {"15th Anniversary", "15 周年纪念披风"}, {"Purple Heart", "紫色心形披风"},
+ {"Follower's", "追随者披风"}, {"MCC 15th Year", "MCC 15 周年披风"}
}
Dim SelectionControl As New List(Of IMyRadio) From {New MyRadioBox With {.Text = "无披风"}}
For Each Cape In SkinData("capes")
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchLeft.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchLeft.xaml.vb
index c7da13c..206f96a 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchLeft.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchLeft.xaml.vb
@@ -21,6 +21,27 @@
'加载版本
RunInNewThread(
Sub()
+ '自动整合包安装:准备
+ Dim PackInstallPath As String = Nothing
+ If File.Exists(Path & "modpack.zip") Then PackInstallPath = Path & "modpack.zip"
+ If File.Exists(Path & "modpack.mrpack") Then PackInstallPath = Path & "modpack.mrpack"
+ If PackInstallPath IsNot Nothing Then
+ If MyMsgBox($"PCL 即将在当前文件夹下自动安装整合包。", "自动安装", "继续", "取消") = 1 Then
+ '确认自动安装
+ Log("[Launch] 需自动安装整合包:" & PackInstallPath, LogLevel.Debug)
+ Setup.Set("LaunchFolderSelect", "$.minecraft\")
+ If Not Directory.Exists(Path & ".minecraft\") Then
+ Directory.CreateDirectory(Path & ".minecraft\")
+ Directory.CreateDirectory(Path & ".minecraft\versions\")
+ McFolderLauncherProfilesJsonCreate(Path & ".minecraft\")
+ End If
+ McFolderListLoader.WaitForExit(IsForceRestart:=True)
+ Else
+ '取消自动安装
+ Log("[Launch] 取消自动安装整合包:" & PackInstallPath, LogLevel.Debug)
+ PackInstallPath = Nothing
+ End If
+ End If
'确认 Minecraft 文件夹存在
PathMcFolder = Setup.Get("LaunchFolderSelect").ToString.Replace("$", Path)
If PathMcFolder = "" OrElse Not Directory.Exists(PathMcFolder) Then
@@ -35,17 +56,27 @@
End If
Log("[Launch] Minecraft 文件夹:" & PathMcFolder)
If Setup.Get("SystemDebugDelay") Then Thread.Sleep(RandomInteger(500, 3000))
+ '自动整合包安装
+ If PackInstallPath IsNot Nothing Then
+ Dim InstallLoader = ModpackInstall(PackInstallPath)
+ If InstallLoader Is Nothing Then
+ Log("[Launch] 自动安装整合包失败:" & PackInstallPath)
+ Else
+ Log("[Launch] 自动安装整合包开始:" & PackInstallPath)
+ RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
+ InstallLoader.WaitForExit()
+ If InstallLoader.State = LoadState.Finished Then
+ Log("[Launch] 自动安装整合包成功,删除安装包:" & PackInstallPath)
+ File.Delete(PackInstallPath)
+ End If
+ End If
+ End If
'确认 Minecraft 版本存在
Dim Selection As String = Setup.Get("LaunchVersionSelect")
- Dim Version As McVersion
- If Selection = "" Then
- Version = Nothing
- Else
- Version = New McVersion(Selection)
- End If
- If IsNothing(Version) OrElse Not (Version.Path.StartsWith(PathMcFolder) AndAlso Version.Check) Then
+ Dim Version As McVersion = If(Selection = "", Nothing, New McVersion(Selection))
+ If Version Is Nothing OrElse Not Version.Path.StartsWithF(PathMcFolder) OrElse Not Version.Check() Then
'无效的版本
- Log("[Launch] Minecraft 版本无效" & If(IsNothing(Version), ",没有有效版本", ":" & Version.Path), If(IsNothing(Version), LogLevel.Normal, LogLevel.Debug))
+ Log("[Launch] 当前选择的 Minecraft 版本无效:" & If(Version Is Nothing, "null", Version.Path), If(IsNothing(Version), LogLevel.Normal, LogLevel.Debug))
If Not McVersionListLoader.State = LoadState.Finished Then LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
If Not McVersionList.Any() OrElse McVersionList.First.Value(0).Logo.Contains("RedstoneBlock") Then
Version = Nothing
@@ -619,7 +650,7 @@ Finish:
Log("[Minecraft] 启动按钮:正在加载 Minecraft 版本")
FrmLaunchLeft.BtnLaunch.Text = "正在加载"
FrmLaunchLeft.BtnLaunch.IsEnabled = False
- FrmLaunchLeft.LabVersion.Text = "正在加载版本列表,请稍候"
+ FrmLaunchLeft.LabVersion.Text = "正在加载中,请稍候"
FrmLaunchLeft.BtnVersion.IsEnabled = False
FrmLaunchLeft.BtnMore.Visibility = Visibility.Collapsed
Case 1
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb
index 8da1fc5..5efe384 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb
@@ -27,15 +27,16 @@
''' 刷新自定义主页。
'''
Private Sub Refresh() Handles Me.Loaded
- RunInNewThread(Sub()
- Try
- SyncLock RefreshLock
- RefreshReal()
- End SyncLock
- Catch ex As Exception
- Log(ex, "加载 PCL 主页自定义信息失败", LogLevel.Msgbox)
- End Try
- End Sub, $"刷新自定义主页 #{GetUuid()}")
+ RunInNewThread(
+ Sub()
+ Try
+ SyncLock RefreshLock
+ RefreshReal()
+ End SyncLock
+ Catch ex As Exception
+ Log(ex, "加载 PCL 主页自定义信息失败", LogLevel.Msgbox)
+ End Try
+ End Sub, $"刷新自定义主页 #{GetUuid()}")
End Sub
Private Sub RefreshReal()
Dim Content As String = ""
@@ -155,7 +156,6 @@ Download:
Else
Log(ex, $"联网下载自定义主页失败({Address})")
End If
- Address = ""
End Try
End Sub
@@ -204,7 +204,7 @@ Download:
End If
Content = "" & Content & ""
Content = HelpArgumentReplace(Content)
- Log($"[Page] 实例化:加载自定义主页 UI,最终内容长度:{Content.Count}")
+ Log($"[Page] 实例化:加载自定义主页 UI 开始,最终内容长度:{Content.Count}")
Try
PanCustom.Children.Add(GetObjectFromXML(Content))
Catch ex As Exception
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuth.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuth.xaml.vb
index b5422ae..3476e70 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuth.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuth.xaml.vb
@@ -71,9 +71,9 @@
End Sub
Private Sub Btn_Click(sender As Object, e As EventArgs) Handles BtnLink.Click
If BtnLink.Content = "注册账号" Then
- OpenWebsite(If(McVersionCurrent Is Nothing, Setup.Get("VersionServerAuthRegister", Version:=McVersionCurrent), Setup.Get("CacheAuthServerRegister")))
+ OpenWebsite(If(McVersionCurrent IsNot Nothing, Setup.Get("VersionServerAuthRegister", Version:=McVersionCurrent), Setup.Get("CacheAuthServerRegister")))
Else
- Dim Website As String = If(McVersionCurrent Is Nothing, Setup.Get("VersionServerAuthRegister", Version:=McVersionCurrent), Setup.Get("CacheAuthServerRegister"))
+ Dim Website As String = If(McVersionCurrent IsNot Nothing, Setup.Get("VersionServerAuthRegister", Version:=McVersionCurrent), Setup.Get("CacheAuthServerRegister"))
OpenWebsite(Website.Replace("/auth/register", "/auth/forgot"))
End If
End Sub
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb
index 0ed101d..ca21ffa 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb
@@ -58,19 +58,21 @@
Hint("正在尝试更换,请稍候!")
Setup.Set("CacheAuthUuid", "") '清空选择缓存
Setup.Set("CacheAuthName", "")
- RunInThread(Sub()
- Try
- Dim Data As McLoginServer = GetLoginData()
- Data.ForceReselectProfile = True
- McLoginLoader.WaitForExit(Data, IsForceRestart:=True)
- RunInUi(Sub() Reload(True))
- Catch ex As Exception
- Log(ex, "更换角色失败", LogLevel.Hint)
- End Try
- End Sub)
+ RunInThread(
+ Sub()
+ Try
+ Dim Data As McLoginServer = GetLoginData()
+ Data.ForceReselectProfile = True
+ McLoginLoader.WaitForExit(Data, IsForceRestart:=True)
+ RunInUi(Sub() Reload(True))
+ Catch ex As Exception
+ Log(ex, "更换角色失败", LogLevel.Hint)
+ End Try
+ End Sub)
End Sub
Private Sub BtnExit_Click() Handles BtnExit.Click
Setup.Set("CacheAuthAccess", "")
+ Setup.Set("CacheAuthUuid", "")
FrmLaunchLeft.RefreshPage(False, True)
End Sub
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMs.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMs.xaml.vb
index 4bf92e2..e61fa4e 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMs.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMs.xaml.vb
@@ -39,14 +39,15 @@
Public Shared Function GetLoginData() As McLoginMs
If FrmLoginMs Is Nothing Then Return New McLoginMs With {.OAuthRefreshToken = Setup.Get("CacheMsOAuthRefresh"), .UserName = Setup.Get("CacheMsName")}
Dim Result As McLoginMs = Nothing
- RunInUiWait(Sub()
- If FrmLoginMs.ComboAccounts.SelectedIndex = 0 Then
- Result = New McLoginMs
- Else
- Dim Item As MyListItem = FrmLoginMs.ComboAccounts.SelectedItem
- Result = New McLoginMs With {.OAuthRefreshToken = Item.Tag, .UserName = Item.Title}
- End If
- End Sub)
+ RunInUiWait(
+ Sub()
+ If FrmLoginMs.ComboAccounts.SelectedIndex = 0 Then
+ Result = New McLoginMs
+ Else
+ Dim Item As MyListItem = FrmLoginMs.ComboAccounts.SelectedItem
+ Result = New McLoginMs With {.OAuthRefreshToken = Item.Tag, .UserName = Item.Title}
+ End If
+ End Sub)
Return Result
End Function
'''
diff --git a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
index a404b44..f693f70 100644
--- a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
+++ b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
@@ -29,7 +29,7 @@
-
+
@@ -55,7 +55,7 @@
-
+
@@ -75,7 +75,7 @@
-
+
@@ -104,138 +104,91 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -245,7 +198,7 @@
-
+
@@ -254,12 +207,12 @@
-
+
-
+
-
+
diff --git a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml.vb b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml.vb
index 40afd2e..237bd2a 100644
--- a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml.vb
@@ -19,7 +19,7 @@
End Sub
Private Sub BtnAboutBmclapi_Click(sender As Object, e As EventArgs) Handles BtnAboutBmclapi.Click
- OpenWebsite("https://afdian.net/a/bangbang93")
+ OpenWebsite("https://afdian.com/a/bangbang93")
End Sub
Private Sub BtnAboutWiki_Click(sender As Object, e As EventArgs) Handles BtnAboutWiki.Click
OpenWebsite("https://www.mcmod.cn")
@@ -27,7 +27,7 @@
Public Shared Sub CopyUniqueAddress() Handles BtnDonateCopy.Click
ClipboardSet(UniqueAddress)
End Sub
- Private Sub DonateCodeInput() Handles BtnDonateInput.Click
+ Private Sub BtnDonateCodeInput_Click() Handles BtnDonateInput.Click
DonateCodeInput()
End Sub
diff --git a/Plain Craft Launcher 2/Pages/PageSelectRight.xaml.vb b/Plain Craft Launcher 2/Pages/PageSelectRight.xaml.vb
index 1709a4a..5b88927 100644
--- a/Plain Craft Launcher 2/Pages/PageSelectRight.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageSelectRight.xaml.vb
@@ -38,17 +38,21 @@
CardName = "常规版本"
Case McVersionCardType.API
Dim IsForgeExists As Boolean = False
+ Dim IsNeoForgeExists As Boolean = False
Dim IsFabricExists As Boolean = False
Dim IsLiteExists As Boolean = False
For Each Version As McVersion In Card.Value
If Version.Version.HasFabric Then IsFabricExists = True
If Version.Version.HasLiteLoader Then IsLiteExists = True
If Version.Version.HasForge Then IsForgeExists = True
+ If Version.Version.HasNeoForge Then IsNeoForgeExists = True
Next
- If If(IsLiteExists, 1, 0) + If(IsForgeExists, 1, 0) + If(IsFabricExists, 1, 0) > 1 Then
+ If If(IsLiteExists, 1, 0) + If(IsForgeExists, 1, 0) + If(IsFabricExists, 1, 0) + If(IsNeoForgeExists, 1, 0) > 1 Then
CardName = "可安装 Mod"
ElseIf IsForgeExists Then
CardName = "Forge 版本"
+ ElseIf IsNeoForgeExists Then
+ CardName = "NeoForge 版本"
ElseIf IsLiteExists Then
CardName = "LiteLoader 版本"
Else
@@ -210,8 +214,8 @@
FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadInstall)
End Sub
+ '修改此代码时,同时修改 PageVersionOverall 中的代码
Public Shared Sub DeleteVersion(Item As MyListItem, Version As McVersion)
- '修改此代码时,同时修改 PageVersionOverall 中的代码
Try
Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
Dim IsHintIndie As Boolean = Version.State <> McVersionState.Error AndAlso Version.PathIndie <> PathMcFolder
diff --git a/Plain Craft Launcher 2/Pages/PageSetup/ModSetup.vb b/Plain Craft Launcher 2/Pages/PageSetup/ModSetup.vb
index faef9cc..5caddae 100644
--- a/Plain Craft Launcher 2/Pages/PageSetup/ModSetup.vb
+++ b/Plain Craft Launcher 2/Pages/PageSetup/ModSetup.vb
@@ -108,6 +108,7 @@
{"ToolDownloadKeepModpack", New SetupEntry(False, Source:=SetupSource.Registry)},
{"ToolDownloadIgnoreQuilt", New SetupEntry(True, Source:=SetupSource.Registry)},
{"ToolDownloadCert", New SetupEntry(True, Source:=SetupSource.Registry)},
+ {"ToolDownloadMod", New SetupEntry(1, Source:=SetupSource.Registry)},
{"ToolUpdateAlpha", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
{"ToolUpdateRelease", New SetupEntry(False, Source:=SetupSource.Registry)},
{"ToolUpdateSnapshot", New SetupEntry(False, Source:=SetupSource.Registry)},
@@ -163,6 +164,7 @@
{"VersionAdvanceRunWait", New SetupEntry(True, Source:=SetupSource.Version)},
{"VersionRamType", New SetupEntry(2, Source:=SetupSource.Version)},
{"VersionRamCustom", New SetupEntry(15, Source:=SetupSource.Version)},
+ {"VersionRamOptimize", New SetupEntry(0, Source:=SetupSource.Version)},
{"VersionArgumentTitle", New SetupEntry("", Source:=SetupSource.Version)},
{"VersionArgumentInfo", New SetupEntry("", Source:=SetupSource.Version)},
{"VersionArgumentIndie", New SetupEntry(-1, Source:=SetupSource.Version)},
diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml
index a1957fe..d34419c 100644
--- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml
+++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml
@@ -7,9 +7,9 @@
PanScroll="{Binding ElementName=PanBack}">
-
+
-
+
diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb
index 99b962a..fe721e6 100644
--- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb
@@ -206,10 +206,8 @@
SliderRamCustom.MaxValue = Math.Floor((RamTotal - 1.5) / 0.5) + 12
ElseIf RamTotal <= 16 Then
SliderRamCustom.MaxValue = Math.Floor((RamTotal - 8) / 1) + 25
- ElseIf RamTotal <= 32 Then
- SliderRamCustom.MaxValue = Math.Floor((RamTotal - 16) / 2) + 33
Else
- SliderRamCustom.MaxValue = Math.Min(Math.Floor((RamTotal - 32) / 4) + 41, 49)
+ SliderRamCustom.MaxValue = Math.Min(Math.Floor((RamTotal - 16) / 2) + 33, 41)
End If
'设置文本
LabRamGame.Text = If(RamGame = Math.Floor(RamGame), RamGame & ".0", RamGame) & " GB" &
@@ -259,7 +257,6 @@
End If
If RamTextLeft <> Left Then
RamTextLeft = Left
- 'If AniControlEnabled = 0 Then
Select Case Left
Case 0
AniStart({
@@ -280,22 +277,6 @@
AaOpacity(LabRamUsedTitle, 0.7 - LabRamUsedTitle.Opacity, 100)
}, "SetupLaunch Ram TextLeft")
End Select
- 'Else
- ' Select Case Left
- ' Case 0
- ' LabRamUsed.Opacity = 0
- ' LabRamTotal.Opacity = 0
- ' LabRamUsedTitle.Opacity = 0
- ' Case 1
- ' LabRamUsed.Opacity = 1
- ' LabRamTotal.Opacity = 0
- ' LabRamUsedTitle.Opacity = 0.7
- ' Case 2
- ' LabRamUsed.Opacity = 1
- ' LabRamTotal.Opacity = 1
- ' LabRamUsedTitle.Opacity = 0.7
- ' End Select
- 'End If
End If
'右侧
Dim Right As Integer
@@ -404,15 +385,14 @@ PreFin:
RamGive = (Value - 12) * 0.5 + 1.5
ElseIf Value <= 33 Then
RamGive = (Value - 25) * 1 + 8
- ElseIf Value <= 41 Then
- RamGive = (Value - 33) * 2 + 16
Else
- RamGive = (Value - 41) * 4 + 32
+ RamGive = (Value - 33) * 2 + 16
End If
End If
'若使用 32 位 Java,则限制为 1G
If If(Is32BitJava, Not JavaIs64Bit(If(UseVersionJavaSetup, Version, Nothing))) Then RamGive = Math.Min(1, RamGive)
- Return RamGive
+ '封顶 32G
+ Return Math.Min(32, RamGive)
End Function
#End Region
@@ -557,8 +537,8 @@ PreFin:
Private Sub CheckArgumentRam_Change() Handles CheckArgumentRam.Change
If AniControlEnabled <> 0 Then Exit Sub
If Not CheckArgumentRam.Checked Then Return
- If MyMsgBox("内存优化耗时较长,这会拖慢游戏的启动过程,建议仅在电脑内存不充裕时开启此选项。" & vbCrLf &
- "如果你在使用机械硬盘,这还可能会导致一小段时间的严重卡顿。" &
+ If MyMsgBox("内存优化会显著延长启动耗时,建议仅在内存不足时开启。" & vbCrLf &
+ "如果你在使用机械硬盘,这还可能导致一小段时间的严重卡顿。" &
If(IsAdmin(), "", $"{vbCrLf}{vbCrLf}每次启动游戏,PCL 都需要申请管理员权限以进行内存优化。{vbCrLf}若想自动授予权限,可以右键 PCL,打开 属性 → 兼容性 → 以管理员身份运行此程序。"),
"提醒", "确定", "取消") = 2 Then
CheckArgumentRam.Checked = False
diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml
index 325c1f6..4f95fe3 100644
--- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml
+++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml
@@ -20,6 +20,8 @@
+
+
@@ -31,32 +33,38 @@
-
-
+
+
-
-
+
+
+
+
+
+
+
-
-
+
-
-
+
-
-
-
+
+
-
-
@@ -93,7 +101,8 @@
-
+
+
@@ -116,15 +125,23 @@
-
+
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml.vb b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml.vb
index 5156d1f..0b19b11 100644
--- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml.vb
@@ -35,7 +35,10 @@
'重复加载部分
PanBack.ScrollToHome()
-#If Not BETA Then
+#If BETA Then
+ PanDonate.Visibility = Visibility.Collapsed
+#Else
+ PanDonate.Visibility = Visibility.Visible
ItemSystemUpdateDownload.Content = "在有新版本时自动下载(更新快照版可能需要更新密钥)"
#End If
@@ -56,6 +59,7 @@
SliderDownloadSpeed.Value = Setup.Get("ToolDownloadSpeed")
ComboDownloadVersion.SelectedIndex = Setup.Get("ToolDownloadVersion")
ComboDownloadTranslate.SelectedIndex = Setup.Get("ToolDownloadTranslate")
+ ComboDownloadMod.SelectedIndex = Setup.Get("ToolDownloadMod")
CheckDownloadKeepModpack.Checked = Setup.Get("ToolDownloadKeepModpack")
CheckDownloadIgnoreQuilt.Checked = Setup.Get("ToolDownloadIgnoreQuilt")
CheckDownloadCert.Checked = Setup.Get("ToolDownloadCert")
@@ -90,6 +94,7 @@
Setup.Reset("ToolDownloadKeepModpack")
Setup.Reset("ToolDownloadIgnoreQuilt")
Setup.Reset("ToolDownloadCert")
+ Setup.Reset("ToolDownloadMod")
Setup.Reset("ToolUpdateRelease")
Setup.Reset("ToolUpdateSnapshot")
Setup.Reset("ToolHelpChinese")
@@ -117,7 +122,7 @@
Private Shared Sub SliderChange(sender As MySlider, e As Object) Handles SliderDebugAnim.Change, SliderDownloadThread.Change, SliderDownloadSpeed.Change
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Value)
End Sub
- Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboDownloadVersion.SelectionChanged, ComboDownloadTranslate.SelectionChanged, ComboSystemUpdate.SelectionChanged, ComboSystemActivity.SelectionChanged
+ Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboDownloadVersion.SelectionChanged, ComboDownloadTranslate.SelectionChanged, ComboSystemUpdate.SelectionChanged, ComboSystemActivity.SelectionChanged, ComboDownloadMod.SelectionChanged
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex)
End Sub
Private Shared Sub TextBoxChange(sender As MyTextBox, e As Object) Handles TextSystemCache.ValidatedTextChanged
@@ -212,4 +217,15 @@
End Try
End Function
+#Region "导出 / 导入设置"
+
+ Private Sub BtnSystemSettingExp_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnSystemSettingExp.Click
+ Hint("该功能尚在开发中!")
+ End Sub
+ Private Sub BtnSystemSettingImp_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnSystemSettingImp.Click
+ Hint("该功能尚在开发中!")
+ End Sub
+
+#End Region
+
End Class
diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.vb b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.vb
index 181eb95..57b6279 100644
--- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.vb
@@ -41,8 +41,8 @@
'设置解锁
If Not RadioLauncherTheme8.IsEnabled Then LabLauncherTheme8Copy.ToolTip = "累积赞助达到 ¥23.33 后,在爱发电私信发送【解锁码】以解锁。" & vbCrLf & "右键打开赞助页面,如果觉得 PCL 做得还不错就支持一下吧 =w=!"
RadioLauncherTheme8.ToolTip = "累积赞助达到 ¥23.33 后,在爱发电私信发送【解锁码】以解锁"
- If Not RadioLauncherTheme9.IsEnabled Then LabLauncherTheme9Copy.ToolTip = "· 反馈一个 Bug,在 Issue 标记为 [已完成] 后回复 Issue 要求解锁(右键打开反馈页面)" & vbCrLf & "· 向帮助库提交 Pull Request,在龙猫合并后解锁"
- RadioLauncherTheme9.ToolTip = "· 反馈一个 Bug,在反馈标记为 [完成] 后回复 Issue 要求解锁" & vbCrLf & "· 向帮助库提交 Pull Request,在龙猫合并后解锁"
+ If Not RadioLauncherTheme9.IsEnabled Then LabLauncherTheme9Copy.ToolTip = "· 反馈一个 Bug,在标记为 [完成] 后回复识别码要求解锁(右键打开反馈页面)" & vbCrLf & "· 提交一个 Pull Request,在合并后回复识别码要求解锁"
+ RadioLauncherTheme9.ToolTip = "· 反馈一个 Bug,在标记为 [完成] 后回复识别码要求解锁" & vbCrLf & "· 提交一个 Pull Request,在合并后回复识别码要求解锁"
'极客蓝的处理在 ThemeCheck 中
End Sub
@@ -83,7 +83,11 @@
MusicRefreshUI()
'主页
- ComboCustomPreset.SelectedIndex = Setup.Get("UiCustomPreset")
+ Try
+ ComboCustomPreset.SelectedIndex = Setup.Get("UiCustomPreset")
+ Catch
+ Setup.Reset("UiCustomPreset")
+ End Try
CType(FindName("RadioCustomType" & Setup.Load("UiCustomType")), MyRadioBox).Checked = True
TextCustomNet.Text = Setup.Get("UiCustomNet")
@@ -360,27 +364,28 @@ Refresh:
End Sub
Private Sub BtnMusicClear_Click(sender As Object, e As EventArgs) Handles BtnMusicClear.Click
If MyMsgBox("即将删除背景音乐文件夹中的所有文件。" & vbCrLf & "此操作不可撤销,是否确定?", "警告",, "取消", IsWarn:=True) = 1 Then
- RunInThread(Sub()
- Hint("正在删除背景音乐……")
- '停止播放音乐
- MusicNAudio = Nothing
- MusicWaitingList = New List(Of String)
- MusicAllList = New List(Of String)
- Thread.Sleep(200)
- '删除文件
- Try
- DeleteDirectory(Path & "PCL\Musics")
- Hint("背景音乐已删除!", HintType.Finish)
- Catch ex As Exception
- Log(ex, "删除背景音乐失败", LogLevel.Msgbox)
- End Try
- Try
- Directory.CreateDirectory(Path & "PCL\Musics")
- RunInUi(Sub() MusicRefreshPlay(False))
- Catch ex As Exception
- Log(ex, "重建背景音乐文件夹失败", LogLevel.Msgbox)
- End Try
- End Sub)
+ RunInThread(
+ Sub()
+ Hint("正在删除背景音乐……")
+ '停止播放音乐
+ MusicNAudio = Nothing
+ MusicWaitingList = New List(Of String)
+ MusicAllList = New List(Of String)
+ Thread.Sleep(200)
+ '删除文件
+ Try
+ DeleteDirectory(Path & "PCL\Musics")
+ Hint("背景音乐已删除!", HintType.Finish)
+ Catch ex As Exception
+ Log(ex, "删除背景音乐失败", LogLevel.Msgbox)
+ End Try
+ Try
+ Directory.CreateDirectory(Path & "PCL\Musics")
+ RunInUi(Sub() MusicRefreshPlay(False))
+ Catch ex As Exception
+ Log(ex, "重建背景音乐文件夹失败", LogLevel.Msgbox)
+ End Try
+ End Sub)
End If
End Sub
Private Sub CheckMusicStart_Change() Handles CheckMusicStart.Change
@@ -423,9 +428,9 @@ Refresh:
RadioLauncherTheme5Gray.Opacity -= 0.23
RadioLauncherTheme5.Opacity += 0.23
AniStart({
- AaOpacity(RadioLauncherTheme5Gray, 1, 1000),
- AaOpacity(RadioLauncherTheme5, -1, 1000)
- }, "ThemeUnlock")
+ AaOpacity(RadioLauncherTheme5Gray, 1, 1000),
+ AaOpacity(RadioLauncherTheme5, -1, 1000)
+ }, "ThemeUnlock")
If RadioLauncherTheme5Gray.Opacity < 0.08 Then
ThemeUnlock(5, UnlockHint:="隐藏主题 玄素黑 已解锁!")
AniStop("ThemeUnlock")
@@ -433,7 +438,7 @@ Refresh:
End If
End Sub
Private Sub LabLauncherTheme11Click_MouseLeftButtonUp() Handles LabLauncherTheme11Click.MouseLeftButtonUp, RadioLauncherTheme11.MouseRightButtonUp
- If LabLauncherTheme11Click.Visibility = Visibility.Collapsed OrElse LabLauncherTheme11Click.ToolTip.ToString.Contains("点击") Then
+ If LabLauncherTheme11Click.Visibility = Visibility.Collapsed OrElse If(LabLauncherTheme11Click.ToolTip, "").ToString.Contains("点击") Then
If MyMsgBox(
"1. 不爬取或攻击相关服务或网站,不盗取相关账号,没有谜题可以或需要以此来解决。" & vbCrLf &
"2. 不得篡改或损毁相关公开信息,请尽量让它们保持原状。" & vbCrLf &
@@ -446,7 +451,7 @@ Refresh:
End If
End Sub
Private Sub LabLauncherTheme8Copy_MouseRightButtonUp() Handles LabLauncherTheme8Copy.MouseRightButtonUp
- OpenWebsite("https://afdian.net/a/LTCat")
+ OpenWebsite("https://afdian.com/a/LTCat")
End Sub
Private Sub LabLauncherTheme9Copy_MouseRightButtonUp() Handles LabLauncherTheme9Copy.MouseRightButtonUp
PageOtherLeft.TryFeedback()
@@ -659,23 +664,15 @@ Refresh:
'公开预览版
Private Sub BtnLauncherDonate_Click(sender As Object, e As EventArgs) Handles BtnLauncherDonate.Click
- OpenWebsite("https://afdian.net/a/LTCat")
+ OpenWebsite("https://afdian.com/a/LTCat")
End Sub
'滑动条
Private Sub SliderLoad()
- SliderMusicVolume.GetHintText = Function(Value As Integer)
- Return Math.Ceiling(Value * 0.1) & "%"
- End Function
- SliderLauncherOpacity.GetHintText = Function(Value As Integer)
- Return Math.Round(40 + Value * 0.1) & "%"
- End Function
- SliderLauncherHue.GetHintText = Function(Value As Integer)
- Return Value & "°"
- End Function
- SliderLauncherSat.GetHintText = Function(Value As Integer)
- Return Value & "%"
- End Function
+ SliderMusicVolume.GetHintText = Function(v) Math.Ceiling(v * 0.1) & "%"
+ SliderLauncherOpacity.GetHintText = Function(v) Math.Round(40 + v * 0.1) & "%"
+ SliderLauncherHue.GetHintText = Function(v) v & "°"
+ SliderLauncherSat.GetHintText = Function(v) v & "%"
SliderLauncherDelta.GetHintText = Function(Value As Integer)
If Value > 90 Then
Return "+" & (Value - 90)
@@ -694,12 +691,8 @@ Refresh:
Return Value - 20
End If
End Function
- SliderBackgroundOpacity.GetHintText = Function(Value As Integer)
- Return Math.Round(Value * 0.1) & "%"
- End Function
- SliderBackgroundBlur.GetHintText = Function(Value As Integer)
- Return Value & " 像素"
- End Function
+ SliderBackgroundOpacity.GetHintText = Function(v) Math.Round(v * 0.1) & "%"
+ SliderBackgroundBlur.GetHintText = Function(v) v & " 像素"
End Sub
End Class
diff --git a/Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.vb b/Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.vb
index 18c7270..665ff21 100644
--- a/Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.vb
@@ -60,11 +60,9 @@ Public Class PageSpeedLeft
End Try
If FrmSpeedRight Is Nothing OrElse FrmSpeedRight.PanMain Is Nothing Then Exit Sub
Try
- SyncLock LoaderTaskbarLock
- For Each Loader In LoaderTaskbar.ToList
- TaskRefresh(Loader)
- Next
- End SyncLock
+ For Each Loader In LoaderTaskbar.ToList
+ TaskRefresh(Loader)
+ Next
Catch ex As Exception
Log(ex, "下载管理右栏监视出错", LogLevel.Feedback)
End Try
@@ -197,13 +195,11 @@ Public Class PageSpeedLeft
Sub(sender As MyIconButton, e As EventArgs)
AniDispose(sender, False)
AniDispose(Card, True, Sub() If FrmSpeedRight.PanMain.Children.Count = 0 AndAlso FrmMain.PageCurrent = FormMain.PageType.DownloadManager Then FrmMain.PageBack())
- RightCards.Remove(Loader.Name)
- SyncLock LoaderTaskbarLock
- LoaderTaskbar.Remove(Loader)
- Log($"[Taskbar] 由于下载管理卡片关闭,{Loader.Name} 已移出任务列表")
- End SyncLock
- Log($"[Watcher] 关闭下载管理卡片:{Loader.Name}")
- RunInThread(Sub() Loader.Abort())
+ Dim LoaderName = If(Loader Is Nothing, "null", Loader.Name)
+ RightCards.Remove(LoaderName)
+ LoaderTaskbar.TryTake(Loader)
+ Log($"[Taskbar] 关闭下载管理卡片:{LoaderName},且移出任务列表")
+ RunInThread(Sub() Loader?.Abort())
End Sub
'如果已经失败,再刷新一次,修改成失败的控件
If Loader.State = LoadState.Failed Then
diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml
index 1915d09..d5b7285 100644
--- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml
+++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml
@@ -7,7 +7,8 @@
-
+
+
@@ -24,6 +25,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb
index 9af7c14..edd7e93 100644
--- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb
@@ -4,6 +4,11 @@
Private IsLoad As Boolean = False
Public Sub PageOther_Loaded() Handles Me.Loaded
+ BtnTypeAll.Tag = ViewType.All
+ BtnTypeEnabled.Tag = ViewType.Enabled
+ BtnTypeDisabled.Tag = ViewType.Disabled
+ BtnTypeCanUpdate.Tag = ViewType.CanUpdate
+ BtnTypeError.Tag = ViewType.InError
If FrmMain.PageLast.Page <> FormMain.PageType.CompDetail Then PanBack.ScrollToHome()
AniControlEnabled += 1
@@ -27,6 +32,8 @@
Public Sub RefreshList(Optional ForceReload As Boolean = False)
If LoaderFolderRun(McModLoader, PageVersionLeft.Version.PathIndie & "mods\", If(ForceReload, LoaderFolderRunType.ForceRun, LoaderFolderRunType.RunOnUpdated)) Then
Log("[System] 已刷新 Mod 列表")
+ ViewModType = ViewType.All
+ BtnTypeAll.Checked = True
PanBack.ScrollToHome()
SearchBox.Text = ""
End If
@@ -125,33 +132,81 @@
''' 刷新结果显示。
'''
Private Sub RefreshResult(Mods As List(Of McMod))
+ If PanList Is Nothing Then Exit Sub
+ Dim ShowMods As List(Of McMod) = New List(Of McMod)
+ Select Case ViewModType
+ Case ViewType.All
+ ShowMods = Mods
+ Case ViewType.Enabled
+ For Each Item In Mods
+ If Item.State.Equals(McMod.McModState.Fine) Then ShowMods.Add(Item)
+ Next
+ Case ViewType.Disabled
+ For Each Item In Mods
+ If Item.State.Equals(McMod.McModState.Disabled) Then ShowMods.Add(Item)
+ Next
+ Case ViewType.CanUpdate
+ For Each Item In Mods
+ If Item.CanUpdate Then ShowMods.Add(Item)
+ Next
+ Case ViewType.InError
+ For Each Item In Mods
+ If Item.State.Equals(McMod.McModState.Unavaliable) Then ShowMods.Add(Item)
+ Next
+ End Select
PanList.Children.Clear()
- For Each TargetMod In Mods
+ For Each TargetMod In ShowMods
PanList.Children.Add(ModItems(TargetMod.RawFileName))
Next
+ Dim ModEnabled As Integer = 0
+ Dim ModDisabled As Integer = 0
+ Dim ModCanUpdate As Integer = 0
+ Dim ModError As Integer = 0
+ For Each ModItem In ModItems
+ If ModItem.Value.Entry.CanUpdate Then
+ ModCanUpdate += 1
+ End If
+ If ModItem.Value.Entry.State.Equals(McMod.McModState.Fine) Then
+ ModEnabled += 1
+ End If
+ If ModItem.Value.Entry.State.Equals(McMod.McModState.Disabled) Then
+ ModDisabled += 1
+ End If
+ If ModItem.Value.Entry.State.Equals(McMod.McModState.Unavaliable) Then
+ ModError += 1
+ End If
+ Next
+ BtnTypeAll.Text = $"全部 ({ModEnabled + ModDisabled + ModError}) "
+ BtnTypeCanUpdate.Text = $"可更新 ({ModCanUpdate}) "
+ BtnTypeEnabled.Text = $"已启用 ({ModEnabled}) "
+ BtnTypeDisabled.Text = $"已禁用 ({ModDisabled}) "
+ BtnTypeError.Text = $"错误 ({ModError}) "
RefreshTitle()
End Sub
'''
''' 刷新卡片标题。
'''
Private Sub RefreshTitle()
- Dim Mods = PanList.Children.Cast(Of MyLocalModItem).Select(Function(i) i.Entry).ToList
- Dim Counter = {0, 0, 0}
- For Each ModEntity As McMod In Mods
- Counter(ModEntity.State) += 1
- Next
- Dim TypeList As New List(Of String)
- If Counter(McMod.McModState.Disabled) > 0 Then TypeList.Add("禁用 " & Counter(McMod.McModState.Disabled))
- If Counter(McMod.McModState.Unavaliable) > 0 Then TypeList.Add("错误 " & Counter(McMod.McModState.Unavaliable))
- If Counter(McMod.McModState.Fine) > 0 Then TypeList.Insert(0, If(TypeList.Any, "启用 ", "") & Counter(McMod.McModState.Fine))
If Not IsSearching Then
- PanListBack.Title = "Mod 列表 (" & Join(TypeList, ",") & ")"
- ElseIf TypeList.Any() Then
- PanListBack.Title = "搜索结果 (" & Join(TypeList, ",") & ")"
+ PanListBack.Title = "Mod 列表 - "
+ ElseIf PanList.Children.Count > 0 Then
+ PanListBack.Title = "搜索结果 - "
Else
- PanListBack.Title = "无搜索结果"
+ PanListBack.Title = "无搜索结果 - "
End If
- PanList.Visibility = If(Mods.Any(), Visibility.Visible, Visibility.Collapsed)
+ Select Case ViewModType
+ Case ViewType.All
+ PanListBack.Title += BtnTypeAll.Text
+ Case ViewType.Enabled
+ PanListBack.Title += BtnTypeEnabled.Text
+ Case ViewType.Disabled
+ PanListBack.Title += BtnTypeDisabled.Text
+ Case ViewType.CanUpdate
+ PanListBack.Title += BtnTypeCanUpdate.Text
+ Case ViewType.InError
+ PanListBack.Title += BtnTypeError.Text
+ End Select
+ PanList.Visibility = If(PanList.Children.Count > 0, Visibility.Visible, Visibility.Collapsed)
End Sub
#End Region
@@ -192,10 +247,14 @@
''' 全选。
'''
Private Sub BtnManageSelectAll_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageSelectAll.Click
- If SelectedMods.Count < PanList.Children.Count Then
- ChangeAllSelected(True)
+ Dim CurrentSelected As Integer = 0
+ For Each Item In PanList.Children.OfType(Of MyLocalModItem).ToList
+ If Item.Checked Then CurrentSelected += 1
+ Next
+ If CurrentSelected < PanList.Children.Count Then
+ ChangeCurrentSelected(True)
Else
- ChangeAllSelected(False)
+ ChangeCurrentSelected(False)
End If
End Sub
@@ -229,7 +288,7 @@
'改变下边栏状态
Private ShownCount As Integer = 0
- Private Sub RefreshBottomBar()
+ Public Sub RefreshBottomBar()
'计数
Dim NewCount As Integer = SelectedMods.Count
Dim Selected = NewCount > 0
@@ -256,6 +315,7 @@
'更新显示状态
If AniControlEnabled = 0 Then
If Selected Then
+ PanListBack.Margin = New Thickness(0, 0, 0, 95)
'仅在数量增加时播放出现/跳跃动画
If ShownCount >= NewCount Then
ShownCount = NewCount
@@ -272,6 +332,7 @@
AaTranslateY(CardSelect, -1, 90, 270, Ease:=New AniEaseInoutFluent(AniEasePower.Weak))
}, "Mod Sidebar")
Else
+ PanListBack.Margin = New Thickness(0, 0, 0, 15)
'不重复播放隐藏动画
If ShownCount = 0 Then Return
ShownCount = 0
@@ -301,7 +362,7 @@
Private Sub ChangeAllSelected(Value As Boolean)
AniControlEnabled += 1
SelectedMods.Clear()
- For Each Item As MyLocalModItem In PanList.Children
+ For Each Item As MyLocalModItem In ModItems.Values.ToList
Item.Checked = Value
If Value Then SelectedMods.Add(Item.Entry.RawFileName)
Next
@@ -309,6 +370,22 @@
'更新下边栏 UI
RefreshBottomBar()
End Sub
+
+ Private Sub ChangeCurrentSelected(Value As Boolean)
+ AniControlEnabled += 1
+ For Each Item As MyLocalModItem In PanList.Children
+ Item.Checked = Value
+ If Value Then
+ If Not SelectedMods.Contains(Item.Entry.RawFileName) Then SelectedMods.Add(Item.Entry.RawFileName)
+ Else
+ If SelectedMods.Contains(Item.Entry.RawFileName) Then SelectedMods.Remove(Item.Entry.RawFileName)
+ End If
+ Next
+ AniControlEnabled -= 1
+ '更新下边栏 UI
+ RefreshBottomBar()
+ End Sub
+
Private Sub UnselectedAllWithAnimation() Handles Load.StateChanged, Me.PageExit
Dim CacheAniControlEnabled = AniControlEnabled
AniControlEnabled = 0
@@ -316,7 +393,26 @@
AniControlEnabled += CacheAniControlEnabled
End Sub
Private Sub PageVersionMod_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
- If My.Computer.Keyboard.CtrlKeyDown AndAlso e.Key = Key.A Then ChangeAllSelected(True)
+ If My.Computer.Keyboard.CtrlKeyDown AndAlso e.Key = Key.A Then ChangeCurrentSelected(True)
+ End Sub
+
+ Private ViewModType As ViewType = ViewType.All
+
+ Private Enum ViewType As Integer
+ All
+ Enabled
+ Disabled
+ CanUpdate
+ InError
+ End Enum
+
+ Private Sub ChangeViewType(sender As MyRadioButton, raiseByMouse As Boolean) Handles BtnTypeAll.Check, BtnTypeCanUpdate.Check, BtnTypeDisabled.Check, BtnTypeEnabled.Check, BtnTypeError.Check
+ ViewModType = sender.Tag
+ If IsSearching Then
+ SearchRun()
+ Else
+ RefreshResult(McModLoader.Output)
+ End If
End Sub
#End Region
@@ -328,6 +424,7 @@
EDMods(McModLoader.Output.Where(Function(m) SelectedMods.Contains(m.RawFileName)),
Not sender.Equals(BtnSelectDisable))
ChangeAllSelected(False)
+ RefreshResult(McModLoader.Output)
End Sub
Private Sub EDMods(ModList As IEnumerable(Of McMod), IsEnable As Boolean)
Dim IsSuccessful As Boolean = True
@@ -607,8 +704,10 @@
If ModEntry.Comp IsNot Nothing Then
'跳转到 Mod 下载页面
FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.CompDetail,
- .Additional = {ModEntry.Comp, New List(Of String), PageVersionLeft.Version.Version.McName,
- If(PageVersionLeft.Version.Version.HasForge, CompModLoaderType.Forge, If(PageVersionLeft.Version.Version.HasFabric, CompModLoaderType.Fabric, CompModLoaderType.Any))}})
+ .Additional = {ModEntry.Comp, New List(Of String), PageVersionLeft.Version.Version.McName,
+ If(PageVersionLeft.Version.Version.HasForge, CompModLoaderType.Forge,
+ If(PageVersionLeft.Version.Version.HasNeoForge, CompModLoaderType.NeoForge,
+ If(PageVersionLeft.Version.Version.HasFabric, CompModLoaderType.Fabric, CompModLoaderType.Any)))}})
Else
'获取信息
Dim ContentLines As New List(Of String)
diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionModDisabled.xaml b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionModDisabled.xaml
index cfbd13a..1daef41 100644
--- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionModDisabled.xaml
+++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionModDisabled.xaml
@@ -22,7 +22,7 @@
-
+
diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionOverall.xaml b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionOverall.xaml
index 3452357..d461c04 100644
--- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionOverall.xaml
+++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionOverall.xaml
@@ -37,6 +37,7 @@
+
diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionOverall.xaml.vb b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionOverall.xaml.vb
index e4fc8ec..783a111 100644
--- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionOverall.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionOverall.xaml.vb
@@ -127,6 +127,8 @@
'重命名主文件夹
My.Computer.FileSystem.RenameDirectory(OldPath, TempName)
My.Computer.FileSystem.RenameDirectory(TempPath, NewName)
+ '清理 ini 缓存
+ IniClearCache(PageVersionLeft.Version.Path & "PCL\Setup.ini")
'遍历重命名所有文件与文件夹
For Each Entry As DirectoryInfo In New DirectoryInfo(NewPath).EnumerateDirectories
If Not Entry.Name.Contains(OldName) Then Continue For
@@ -282,26 +284,24 @@
Private Sub BtnManageCheck_Click(sender As Object, e As EventArgs) Handles BtnManageCheck.Click
Try
'重复任务检查
- SyncLock LoaderTaskbarLock
- For i = 0 To LoaderTaskbar.Count - 1
- If LoaderTaskbar(i).Name = PageVersionLeft.Version.Name & " 文件补全" Then
- Hint("正在处理中,请稍候!", HintType.Critical)
- Exit Sub
- End If
- Next
- End SyncLock
+ For Each OngoingLoader In LoaderTaskbar
+ If OngoingLoader.Name <> PageVersionLeft.Version.Name & " 文件补全" Then Continue For
+ Hint("正在处理中,请稍候!", HintType.Critical)
+ Exit Sub
+ Next
'启动
Dim Loader As New LoaderCombo(Of String)(PageVersionLeft.Version.Name & " 文件补全", DlClientFix(PageVersionLeft.Version, True, AssetsIndexExistsBehaviour.AlwaysDownload, False))
- Loader.OnStateChanged = Sub()
- Select Case Loader.State
- Case LoadState.Finished
- Hint(Loader.Name & "成功!", HintType.Finish)
- Case LoadState.Failed
- Hint(Loader.Name & "失败:" & GetExceptionSummary(Loader.Error), HintType.Critical)
- Case LoadState.Aborted
- Hint(Loader.Name & "已取消!", HintType.Info)
- End Select
- End Sub
+ Loader.OnStateChanged =
+ Sub()
+ Select Case Loader.State
+ Case LoadState.Finished
+ Hint(Loader.Name & "成功!", HintType.Finish)
+ Case LoadState.Failed
+ Hint(Loader.Name & "失败:" & GetExceptionSummary(Loader.Error), HintType.Critical)
+ Case LoadState.Aborted
+ Hint(Loader.Name & "已取消!", HintType.Info)
+ End Select
+ End Sub
Loader.Start(PageVersionLeft.Version.Name)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
@@ -312,8 +312,8 @@
End Sub
'删除版本
+ '修改此代码时,同时修改 PageSelectRight 中的代码
Private Sub BtnManageDelete_Click(sender As Object, e As EventArgs) Handles BtnManageDelete.Click
- '修改此代码时,同时修改 PageSelectRight 中的代码
Try
Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
Dim IsHintIndie As Boolean = PageVersionLeft.Version.State <> McVersionState.Error AndAlso PageVersionLeft.Version.PathIndie <> PathMcFolder
@@ -321,6 +321,7 @@
If(IsHintIndie, vbCrLf & "由于该版本开启了版本隔离,删除版本时该版本对应的存档、资源包、Mod 等文件也将被一并删除!", ""),
"版本删除确认", , "取消",, IsHintIndie OrElse IsShiftPressed)
Case 1
+ IniClearCache(PageVersionLeft.Version.Path & "PCL\Setup.ini")
If IsShiftPressed Then
DeleteDirectory(PageVersionLeft.Version.Path)
Hint("版本 " & PageVersionLeft.Version.Name & " 已永久删除!", HintType.Finish)
diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml
index e523d04..6dfb1fa 100644
--- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml
+++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml
@@ -77,6 +77,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb
index ad72125..ae11fc8 100644
--- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb
@@ -51,6 +51,7 @@
'游戏内存
CType(FindName("RadioRamType" & Setup.Load("VersionRamType", Version:=PageVersionLeft.Version)), MyRadioBox).Checked = True
SliderRamCustom.Value = Setup.Get("VersionRamCustom", Version:=PageVersionLeft.Version)
+ ComboRamOptimize.SelectedIndex = Setup.Get("VersionRamOptimize", Version:=PageVersionLeft.Version)
'服务器
TextServerEnter.Text = Setup.Get("VersionServerEnter", Version:=PageVersionLeft.Version)
@@ -95,6 +96,7 @@
Setup.Set("VersionArgumentIndie", 0, Version:=PageVersionLeft.Version)
Setup.Reset("VersionRamType", Version:=PageVersionLeft.Version)
Setup.Reset("VersionRamCustom", Version:=PageVersionLeft.Version)
+ Setup.Reset("VersionRamOptimize", Version:=PageVersionLeft.Version)
Setup.Reset("VersionAdvanceJvm", Version:=PageVersionLeft.Version)
Setup.Reset("VersionAdvanceGame", Version:=PageVersionLeft.Version)
Setup.Reset("VersionAdvanceAssets", Version:=PageVersionLeft.Version)
@@ -130,7 +132,7 @@
Private Shared Sub SliderChange(sender As MySlider, e As Object) Handles SliderRamCustom.Change
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Value, Version:=PageVersionLeft.Version)
End Sub
- Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboArgumentIndie.SelectionChanged
+ Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboArgumentIndie.SelectionChanged, ComboRamOptimize.SelectionChanged
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex, Version:=PageVersionLeft.Version)
End Sub
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckAdvanceRunWait.Change, CheckAdvanceAssetsV2.Change, CheckAdvanceJava.Change
@@ -163,10 +165,8 @@
SliderRamCustom.MaxValue = Math.Floor((RamTotal - 1.5) / 0.5) + 12
ElseIf RamTotal <= 16 Then
SliderRamCustom.MaxValue = Math.Floor((RamTotal - 8) / 1) + 25
- ElseIf RamTotal <= 32 Then
- SliderRamCustom.MaxValue = Math.Floor((RamTotal - 16) / 2) + 33
Else
- SliderRamCustom.MaxValue = Math.Min(Math.Floor((RamTotal - 32) / 4) + 41, 49)
+ SliderRamCustom.MaxValue = Math.Min(Math.Floor((RamTotal - 16) / 2) + 33, 41)
End If
'设置文本
LabRamGame.Text = If(RamGame = Math.Floor(RamGame), RamGame & ".0", RamGame) & " GB" &
@@ -351,15 +351,14 @@ PreFin:
RamGive = (Value - 12) * 0.5 + 1.5
ElseIf Value <= 33 Then
RamGive = (Value - 25) * 1 + 8
- ElseIf Value <= 41 Then
- RamGive = (Value - 33) * 2 + 16
Else
- RamGive = (Value - 41) * 4 + 32
+ RamGive = (Value - 33) * 2 + 16
End If
End If
'若使用 32 位 Java,则限制为 1G
If If(Is32BitJava, Not JavaIs64Bit(PageVersionLeft.Version)) Then RamGive = Math.Min(1, RamGive)
- Return RamGive
+ '封顶 32G
+ Return Math.Min(32, RamGive)
End Function
#End Region
diff --git a/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj b/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj
index 72db688..8246a85 100644
--- a/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj
+++ b/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj
@@ -38,7 +38,7 @@
false
false
true
- D:\Minecraft\程序\
+ .\bin\
Plain Craft Launcher 2.xml
41999,42016,42017,42018,42019,42020,42021,42022,42032,42036,42314
false
@@ -55,7 +55,7 @@
false
false
true
- D:\Minecraft\程序\
+ .\bin\
Plain Craft Launcher 2.xml
41999,42016,42017,42018,42019,42020,42021,42022,42032,42036,42314
false
@@ -100,7 +100,7 @@
false
- D:\Minecraft\程序\
+ .\bin\
Plain Craft Launcher 2.xml
true
1
@@ -111,7 +111,7 @@
false
- D:\Minecraft\程序\
+ .\bin\
Plain Craft Launcher 2.xml
true
1
@@ -129,7 +129,7 @@
- D:\Minecraft\程序\
+ .\bin\
RELEASE,BY_UPDATE
Plain Craft Launcher 2.xml
true
@@ -244,6 +244,9 @@
PageDownloadCompDetail.xaml
+
+ PageDownloadNeoForge.xaml
+
PageDownloadPack.xaml
@@ -494,6 +497,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -869,7 +876,6 @@
-
@@ -923,6 +929,11 @@
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Plain Craft Launcher 2/Resources/Custom.xaml b/Plain Craft Launcher 2/Resources/Custom.xaml
index f35be1d..df177e3 100644
--- a/Plain Craft Launcher 2/Resources/Custom.xaml
+++ b/Plain Craft Launcher 2/Resources/Custom.xaml
@@ -79,7 +79,11 @@
+ Text="启动 1.20.1 并进入 Hypixel" EventType="启动游戏" EventData="1.20.1|mc.hypixel.net" ToolTip="服务器 IP:mc.hypixel.net" />
+
+
@@ -144,7 +148,7 @@
+ Text="打开记事本" EventType="打开文件" EventData="notepad" />
@@ -180,28 +184,30 @@
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
@@ -264,7 +270,7 @@
+ Text="打开记事本" EventType="打开文件" EventData="notepad" />
diff --git a/Plain Craft Launcher 2/Resources/Help.zip b/Plain Craft Launcher 2/Resources/Help.zip
index c55c8d3..a49d41f 100644
Binary files a/Plain Craft Launcher 2/Resources/Help.zip and b/Plain Craft Launcher 2/Resources/Help.zip differ
diff --git a/Plain Craft Launcher 2/Resources/ModData.txt b/Plain Craft Launcher 2/Resources/ModData.txt
index 822f369..91cb6ce 100644
--- a/Plain Craft Launcher 2/Resources/ModData.txt
+++ b/Plain Craft Launcher 2/Resources/ModData.txt
@@ -31,7 +31,7 @@ flans-mod-5-5-2|Flan 的枪械 (Flan's Mod)
ee3|等价交换3 (Equivalent Exchange 3)
minefactory-reloaded|我的工厂 (MineFactory)
-render-player-api|玩家渲染API (Render Player API) - 已失效¨renderplayerapi|玩家渲染API (Render Player API)
+render-player-api|玩家渲染API (Render Player API)¨renderplayerapi|玩家渲染API (Render Player API)
player-api|玩家API (Player API)¨playerapi|玩家API (Player API)
@@ -42,7 +42,7 @@ not-enough-items-1-8@nei|NEI物品管理器 (Not Enough Items)¨notenoughitems|N
-custom-npcs|自定义NPC*
+custom-npcs|自定义NPC (Custom NPCs)
millenaire|千年村庄 (Millénaire)
clay-soldiers-mod|粘土士兵*
mo-creatures|更多生物 (Mo' Creatures)
@@ -102,7 +102,7 @@ minecraft-comes-alive-mca|虚拟人生/凡家物语 (Minecraft Comes Alive)
forge-essentials-74735@forge-essentials
-translocators@|转运器*¨translocators-1-8|转运器 (Translocators)
+translocators-1-8@translocators|转运器 (Translocators)¨translocators|转运器*
craftguide|G键合成表 (CraftGuide)
biomes-o-plenty@|超多生物群系 (Biomes O' Plenty)
@@ -147,7 +147,7 @@ logistics-pipes|物流管道*
magic-bees|魔法蜜蜂*
carpenters-blocks|木匠方块 (Carpenter's Blocks)
-mystcraft@|神秘岛*
+mystcraft|神秘岛*¨@mystcraft|神秘岛 (Mystcraft) - Archived
@@ -182,7 +182,7 @@ ender-io@enderio|末影接口 (Ender IO)
-electrodynamics|电动力学*
+electrodynamics@|电动力学*
elite-armageddon¨mc-1-6-4-solar-apocalypse
mekanism@|通用机械*
@@ -209,7 +209,7 @@ plasmacraft|电浆工艺 (PlasmaCraft)
fossils@fossils-and-archeology-revival|考古与化石 (Fossils and Archeology Revival)
glenns-gases|格林的气体 (Glenn's Gases)
the-lord-of-the-rings-mod-legacy|魔戒:传承 (The Lord of the Rings Mod: Legacy)
-thaumic-tinkerer|神秘工匠*¨thaumic-tinkerer-unofficial|神秘工匠 (Thaumic Tinkerer)¨ichorium-kit|神秘工匠 (Thaumic Tinkerer)
+thaumic-tinkerer|神秘工匠*
@@ -232,13 +232,13 @@ animal-bikes|动物坐骑*
electro-magic-tools|电力魔法工具 (Electro-Magic Tools)
forbidden-magic|禁忌魔法*
mobtalker2|怪物交谈2 (MobTalker 2)
-icbm-classic|洲际导弹 (ICBM)¨icbm|洲际导弹 (ICBM) - 已停更
+icbm-classic@icbm|洲际导弹 (ICBM)¨icbm|洲际导弹 (ICBM) - 已停更
thaumic-infusion|神秘注魔*
thaumic-exploration|神秘探险*
deconstruction-table|解构工作台*
-b0bgarys-growable-ores|可生长矿石 (B0bGary's Growable Ores)
+kcs-growable-ores|可生长矿石 (Kc's Growable Ores)
@@ -386,7 +386,7 @@ thaumic-energistics|神秘能源*
chisel|凿子*
nuclearcraft-mod@nuclearcraft|核电工艺 (NuclearCraft)
-opencomputers|开放式电脑 (Open Computers)
+opencomputers@|开放式电脑 (Open Computers)
elemental-stones|元素之石*
waila-nbt|万用高亮显示 (Waila NBT)
@@ -416,16 +416,16 @@ lanteacraft|星际之门 (LanteaCraft)
matteroverdrive-17-edition|超能物质 (Matter Overdrive)¨matteroverdrive-legacy|超能物质 (Matter Overdrive)
tainted-magic|污秽魔法*
minetweaker3
-treecapitator|砍树 (Tree Capitator)
+treecapitator|砍树*
insta-house|即时建造*
multi-page-chest|多页箱子 (Multi-Page Chest)
-draconic-evolution|龙之进化/龙之研究*
+draconic-evolution@|龙之进化/龙之研究*
galacticraft-add-on-more-planets@more-planets|更多行星 (More Planets)
+thermal-expansion@thermal-foundation|热力基本 (Thermal Foundation)
-
-ding|界面进入提醒*
+ding@|界面进入提醒*
ender-utilities@|末影设备*
magical-crops|魔法作物*
headcrumbs|更多头颅*
@@ -483,7 +483,7 @@ zoology|动物学*
thaumic-revelations|神秘启示录*
warp-book|传送书*
-ex-compressum|压缩工具*
+ex-compressum@|压缩工具*
simply-jetpacks|简易喷气背包*
blood-arsenal|血液兵工厂*
sim-u-kraft-old|模拟城市 (Sim-U-Kraft)
@@ -503,7 +503,7 @@ real-first-person-render|真实的第一人称 (Real First Person 2)
custom-stuff-3|自定义物品3*
lockdown|地图生成锁定*
avaritia|无尽贪婪*¨avaritia-1-10|无尽贪婪 (Avaritia)
-minecraft-flight-simulator|飞行模拟*¨transport-simulator-official-vehicle-set|飞行模拟 (Minecraft Flight Simulator) - 官方认证续写
+minecraft-flight-simulator@immersive-vehicles-official-content-pack|飞行模拟*¨transport-simulator-official-vehicle-set|飞行模拟 (Minecraft Flight Simulator)
essential-thaumaturgy|源质神秘学*
abyssalcraft|深渊国度 (AbyssalCraft)
calculator|运算工艺*
@@ -547,7 +547,7 @@ candycraft|糖果世界 (CandyCraft)
minefantasy2|我的幻想2 (MineFantasy2)
rails-of-war|铁路战争 (Rails of War)
-actually-additions|实用拓展*
+actually-additions@|实用拓展*
galaxy-space-addon-for-galacticraft@galaxy-space|星空 (Galaxy Space)
latiao-craft|辣条工艺*
@@ -596,7 +596,7 @@ vics-modern-warfare-mod|维克的现代战争 (Vic's Modern Warfare Mod)
chance-cubes@|机会方块*
gun-customization
endercore@|末影核心 (EnderCore)
-brandons-core
+brandons-core@
cofh-core@|CoFH核心 (CoFH Core)
statuseffecthud|状态信息显示 (StatusEffectHUD)
lambdalib
@@ -621,10 +621,10 @@ mob-properties|怪物属性*
ganys-surface|Gany的世界 (Gany's Surface)
ezstorage|EZ存储 (EZStorage)
-ichunutil
+ichunutil@
intangible
-forge-multipart-cbe¨forge-multi-part
+forge-multipart-cbe@cb-multipart¨forge-multi-part
the-titans-mod|泰坦生物 (The Titans)
enchiridion
stimmedcow-nomorerecipeconflict|合成冲突消除 (NoMoreRecipeConflict)
@@ -679,7 +679,7 @@ pressure-pipes|压力管道*
onlinepictureframe|在线相框显示 (OnlinePictureFrame)
super-circuit-maker|超级电路*
switch-bow
-minecolonies|模拟殖民地*
+minecolonies@|模拟殖民地*
mcjtylib@
mcmultipart
@@ -740,7 +740,7 @@ thaumic-palmistry
one-click-crafting|一键合成 (One click crafting)
essential-thaumaturgy-unofficial|源质神秘学(非官方版)*
wireless-crafting-terminal|无线合成终端*
-waila-plugins|Waila插件*
+waila-plugins|Waila 插件*
appleskin@|苹果皮 (AppleSkin)
tcbotaniaexoflame|奥术投射 (TCBotaniaExoflame)
thaumic-equivalence|奥法置换*
@@ -788,7 +788,7 @@ solar-flux-reborn|日光通量:重制版*
simple-void-world|简单虚空世界*
shetiphiancore@¨shetiphiancore-fabric
shadowmc
-scannable|扫描器*
+scannable@|扫描器*
rebornstorage|存储重置 (Reborn Storage)
quantumstorage|量子存储 (QuantumStorage)
p455w0rds-library
@@ -912,7 +912,7 @@ world-of-warcraft|魔兽世界*
the-witcher-adventure|猎魔人*
fancy-battleaxes@|华丽战斧*
zora-no-densha|Zora的电车 (Zora no Densha)
-roguelike-dungeons|冒险地牢*
+roguelike-dungeons@roguelikedungeons|冒险地牢*
first-aid@firstaid|急救/医疗护理*
bonfires@|篝火*
immersive-craft@|沉浸工艺*
@@ -956,7 +956,7 @@ ex-nihilo-creatio|无中生有:创世 (Ex Nihilo: Creatio)
thaumcraft|神秘时代*
colossal-chests|巨型箱子*
auto-pickup|自动拾取*
-all-u-want|背包编辑器 (All-U-Want)
+mc-mods-u-want|背包编辑器 (All-U-Want)
potion-core|药水核心*
solar-expansion
blue-power|蓝石力量 (Blue power)
@@ -1007,14 +1007,14 @@ croparia@|矿石作物/魔种之咏*
simple-corn|简单玉米*
thaumic-jei
tinkers-steelworks|匠魂炼钢厂 (Tinkers' Steelworks)
-unicode-font-extension|Unicode字体扩展*
+unicode-font-extension|Unicode 字体扩展*
placeable-items|可放置物品*
compendium|工匠防御 (Tinkers' Compendium (Tinkers' Defense))
stargate-network|格雷的星门 (Greg's SG Craft)
damage-indicators-mod|伤害显示 (Damage Indicators)
torohealth-damage-indicators|ToroHealth 伤害显示 (ToroHealth Damage Indicators)
omni-ocular
-wrapup
+wrapup@
nuclear-physics
wither-skeleton-tweaks|凋灵骷髅调整*
heat-and-climate|热量与气候*
@@ -1071,7 +1071,7 @@ omlib|开放式炮台库 (OMLib)
dynamictrees@|动态的树/有活力的树 (Dynamic Trees)
merry-christmas|圣诞箱子 (Merry Christmas!)
cloud-control|可控制的云*
-zombie-ore|矿石僵尸 (Zombie ore)
+zombie-ore|矿石僵尸*
meanmobs|残忍怪物 (MeanMobs)
zyins-hud
@@ -1081,7 +1081,7 @@ the-disenchanter-mod|祛魔台 (The Disenchanter)
carry-on@|搬运*
better-than-llamas|更好看的羊驼*¨better-than-llamas-fabric|更好看的羊驼 (Better Than Llamas)
dynamic-surroundings@dynamicsurroundingsfabric|动态环境/动态环绕*¨dynamic-surroundings-fabric-edition|动态环境/动态环绕 (Dynamic Surroundings)
-alfheim|亚尔夫海姆*
+alfheim@|亚尔夫海姆*
mob-battle-mod@|怪物大乱斗*¨mob-battle-mod-fabric|怪物大乱斗 (Mob Battle Mod)
smooth-font|平滑字体*
@@ -1107,7 +1107,7 @@ bonsai-trees|盆栽*
misty-world@|朦胧世界*
-beta-kathairis|卡塞瑞斯 (Kathairis/Kether)¨kathairis-alive|卡塞瑞斯 (Kathairis/Kether)
+beta-kathairis|卡塞瑞斯 (Kathairis / Kether)¨kathairis-alive|卡塞瑞斯 (Kathairis / Kether)
manametal|魔法金属 (ManaMetalMod)
avaritiaddons|无尽收容 / 更多空间箱子*
base
@@ -1162,7 +1162,7 @@ cloche-call
mouse-tweaks@|鼠标手势*
jaopcaagriculture|JAOPCA神秘农业附属 (Just A Resource Generation Compatibility Attempt)
sky-resources|空岛资源2 (Sky Resources2)
-hexxit-gear|Hexxit装备*
+hexxit-gear|Hexxit 装备*¨hexxit-gear-restored|Hexxit 装备 (Hexxit Gear)
magic-clover|幸运四叶草*
inventory-crafting-grid|背包工作台*
@@ -1220,7 +1220,7 @@ poop|屎 (Poop Mod)
slurp|啜饮*
tough-expansion|意志坚定:热力附属*
mystical-agradditions@|神秘农业扩展*
-vanillafix|原版修复 (VanillaFix)
+vanillafix@|原版修复 (VanillaFix)
just-enough-harvestcraft|更多潘马斯配方查询 (Just Enough HarvestCraft)
charcoal-pit@charcoal_pit
uncomplication|IC2exp还原*
@@ -1228,7 +1228,7 @@ the-wings-of-alfheim-1-7-10|亚尔夫海姆之翼 (The Wings of Alfheim)
mubble¨mubble-forge
-libraryex|MineEx通用库 (LibraryEx)
+libraryex|MineEx 通用库 (LibraryEx)
industrial-wires|工业线缆*
mystagrad-cloche-compat
waitingtime|加载页面游戏 (WaitingTime)
@@ -1252,7 +1252,7 @@ level-up-legacy|升级!前版 (Level Up!Legacy)
moar-boats|模块化船*
numina|模块化动力装甲前置*
tinkers-complement@|匠魂补充 (Tinkers' Complement)
-everlastingabilities|永恒能力 (EverlastingAbilities)
+everlastingabilities@everlasting-abilities|永恒能力 (EverlastingAbilities)
abyssalcraft-heads|深渊国度头颅 (AbyssalCraft Heads)
overlord@|不死者之王*
multifarm-crops|多功能农场兼容*
@@ -1360,7 +1360,7 @@ morelibs
game-stages@|游戏阶段*
silents-gems@|寂静宝石 (Silent's Gems)
-silent-lib
+silent-lib@
silents-gems-tic-support|寂静宝石:匠魂支持 (Silent's Gems: TiC Support)
lit-little-insignificant-things
gemulation
@@ -1404,7 +1404,7 @@ architecturecraft-tridev@architecture-craft|建筑师工艺重置版 (Architectu
ore-farm|矿石农场*
sound-physics-fabric|物理声效 (Sound Physics)
-plethora-peripherals
+plethora-peripherals@
simple-flight|简单的飞行*
factory-tech|工厂科技 (FactoryTech)
@@ -1419,13 +1419,13 @@ road-stuff@|道路2 (Road Stuff2)
ae2wtlib
real-filing-cabinet|仿真档案柜*
hycrafthds-wtf-ic2-addon|WTF 工业拓展 (WTF Ic2 Addon)
-u-team-core
+u-team-core@
ftb-quests|FTB任务 (FTB Quests)¨ftb-quests-fabric|FTB任务 (FTB Quests)
texfix@|材质修复 (TexFix)
mapmakers-gadgets|地图作者小帮手 (Mapmaker's Gadgets)
travellers-gear|旅者之器 (Traveller's Gear)
ceramics@|陶瓷器*
-slashblade-japanese-addon-pack|拔刀剑日系附属包 (SlashBlade Japanese Addon Pack)
+slashblade-japanese-addon-pack@sjap|拔刀剑日系附属包 (SlashBlade Japanese Addon Pack)
planet-progression|星球研究*
space-advanced-addon-for-galactic-craft-3
@@ -1436,7 +1436,7 @@ new-tardis-mod
advanced-chimneys|高级烟囱*
regeneration|神秘博士 - 再生 (Doctor Who - Regeneration)
-stevekungs-lib
+more-planets-gc-addon
make-zoom-zoom|更快的加载 (MakeZoomZoom)
minecraft-virtual-machines|Minecraft虚拟机*
cavern2|洞穴 II (Cavern II)
@@ -1506,8 +1506,8 @@ vanillaautomation|原版自动化 (VanillaAutomation)
tickprofiler|Tick分析器 (TickProfiler)
vanilla-immersion|立体工具方块*
earthworks|土方工程*
-terraqueous|地灵云心/海树山花*¨terraqueous-fabric|地灵云心/海树山花 (Terraqueous)
-initial-inventory|自定义初始物品*
+terraqueous@|地灵云心/海树山花*¨terraqueous-fabric|地灵云心/海树山花 (Terraqueous)
+initial-inventory@|自定义初始物品*
interaction-wheel@
water-strainer|滤水器*
tinkers-skyblock|匠魂空岛 (Tinkers' Skyblock)
@@ -1518,7 +1518,7 @@ hp-spells|哈利·波特:法术 (Harry Potter Spells)
recurrent-complex|自然建筑生成*
capabilityproxy|功能代理 (CapabilityProxy)
reauth¨reauth-fabric
-autoverse
+autoverse@
transprot|运输*
default-world-generator-port
better-questing-standard-expansion|更好的任务-基础扩展 (Better Questing - Standard Expansion)
@@ -1526,10 +1526,10 @@ exchangers|方块交换器*
flexible-tools|灵活的工具*
dimensional-control|维度控制*
valkyrien-warfare@valkyrien-skies|瓦尔基里天空/瓦尔基里战争 (Valkyrien Skies/Valkyrien Warfare)
-item-scroller|物品滚轮*
+item-scroller@|物品滚轮*
better-advancements@|更好的进度*
lucraft-core
-progressive-bosses@|进化的BOSS*¨fabric-progressive-bosses|进化的BOSS (Progressive Bosses)
+progressive-bosses@|进化的 BOSS*¨fabric-progressive-bosses|进化的 BOSS (Progressive Bosses)
persistent-bits
rc-roads|真实公路 (RC Roads)
emoticons|动作表情*
@@ -1630,7 +1630,7 @@ tinkers-slashblade|刀锻冶匠魂 (Tinker's SlashBlade)
audio-death|死亡音效*
deep-mob-learning|深度怪物学习*
-tofucraftreload|豆腐工艺重制版 (TofuCraftReload)
+tofucraftreload@|豆腐工艺重制版 (TofuCraftReload)
electroblobs-wizardry|巫术学 (Electroblob's Wizardry)
moarsigns|更多告示牌 (MoarSigns)
kamen-rider-craft|假面骑士工艺 (KamenRiderCraft)
@@ -1661,7 +1661,7 @@ cplpibalds-tweaks|CplPibald的微调 (CplPibald's Tweaks)
ore-biome|矿石生态群系*
farm-adventure|农场冒险*
the-shadow-world|暗影世界 (Shadow World)
-japaricraftmod-2|加帕里公园 (JapariCraftMod)
+project-306141|加帕里公园 (JapariCraftMod)
mchorses-mclib
musiccraft-mod|音乐工艺 (MusicCraft mod)
hardcore-darkness|真实的黑夜*
@@ -1688,7 +1688,7 @@ refined-machinery|精致机械*
magicalsculpture|魔法雕像 (MagicalSculpture)
ash-another-simple-hud|另一个简单的HUD (Another Simple HUD)
-customselectionbox|自定义选择框 (Custom Selection Box)¨custom-selection-box-port|自定义选择框 (Custom Selection Box) - 已失效
+custom-selection-box-port|自定义选择框 (Custom Selection Box)¨customselectionbox|自定义选择框 (Custom Selection Box)
librikka-api
not-enough-wands@|更多魔杖*
deep-mob-learning-blood-magic-addon|深度怪物知识-血魔法插件 (Deep Mob Learning - Blood Magic Addon)
@@ -1696,7 +1696,7 @@ informed-load-fabric|更多加载信息 (Informed Load)
huajiage-infinite-galaxy|滑稽纪元II:无尽星河 (Huaji Age II:Infinite Galaxy)
cqrepoured|寻找巧克力重铸版 (Chocolate Quest Repoured)
-fabricproxy@|Fabric群组支持 (FabricProxy)
+fabricproxy@|Fabric 群组支持 (FabricProxy)
ex-sartagine|锅具*
xaeros-minimap@|Xaero的小地图 (Xaero's Minimap) - 完整版¨xaeros-minimap-fair-play-edition@xaeros-minimap-fair|Xaero的小地图 (Xaero's Minimap) - 公平竞争版
everlastingabilities-potioncore|永恒能力-药水核心 (EverlastingAbilities-PotionCore)
@@ -1777,7 +1777,7 @@ ender-compass|末影指南针*
ic2-tweaker
thaumic-gadgets|神秘宝具*
multi-mine|多人开采*
-extra-foam-for-liteloader|Liteloader修复 (Extra Foam For LiteLoader)
+extra-foam-for-liteloader@|Liteloader 修复 (Extra Foam For LiteLoader)
embersified|余烬能量转换*
thaumic-grid|神秘网络*
@@ -1813,7 +1813,7 @@ crafttweaker-utils
fps-reducer@|FPS减速器 (FPS Reducer)
-freelook|自由视角 (FreeLook)
+freelook@freelook-og|自由视角 (FreeLook)
spacecraftx@spacecraftx-reloaded|航天高科X (SpaceCraftX)¨spacecraftx-reloaded|航天高科X (SpaceCraftX)
bamboo-everything@|竹子制品*¨bamboo-everything-fabric|竹子制品 (Bamboo Everything)
@@ -1864,11 +1864,11 @@ multi-mob-core
structurize|结构化*
-improvable-skills|技能进阶 (Improvable Skills 3)
+improvable-skills@|技能进阶 (Improvable Skills 3)
bounding-box-outline-reloaded@bbor|自然生成建筑结构显示*
sauceconstruct
-colorful-hearts@|更美观的血条 (Health Overlay/Colorful Hearts)¨health-overlay-fabric|更美观的血条 (Health Overlay/Colorful Hearts)¨health-overlay|更美观的血条 (Health Overlay/Colorful Hearts)
+colorful-hearts@|更美观的血条 (Health Overlay / Colorful Hearts)¨health-overlay-fabric|更美观的血条 (Health Overlay / Colorful Hearts)¨health-overlay|更美观的血条 (Health Overlay / Colorful Hearts)
auto-feeder-helmet|自动进食头盔*
cc-tweaked-fabric
simple-farming|简单农业*
@@ -1911,7 +1911,7 @@ ftb-money|FTB交易 (FTB Money)
restricted-portals|传送门限制*
vampirelib@
ingameconfigmanager|游戏内配置器 (InGameConfigManager)
-playerrevive|玩家救援 (PlayerRevive)
+playerrevive@|玩家救援 (PlayerRevive)
farlands|边境之地 (FarLands)
inworldcrafting|世界合成 (InWorldCrafting)
food-editor|食物编辑器*
@@ -1923,7 +1923,7 @@ unforgiving-void|不那么仁慈的虚空*
moretweaker
riteclicker-mod|小石子 (RiteClicker Mod)
-forgiving-void|仁慈的虚空*¨forgiving-void-fabric|仁慈的虚空 (Forgiving Void)
+forgiving-void@|仁慈的虚空*¨forgiving-void-fabric|仁慈的虚空 (Forgiving Void)
bread-craft|面包工艺*
alchemistry|炼金化学*¨alchemistry-fabric|炼金化学 (Alchemistry)
damage-control|伤害控制*
@@ -1945,7 +1945,7 @@ instantlava|无限岩浆 (InstantLava)
enchantment-descriptions@|附魔描述*
streak|残影*
dttc|动态的树:神秘时代附属 (Dynamic Trees - Thaumcraft Compat)
-dtbop|动态的树:超多生物群系附属 (Dynamic Trees - Biomes O' Plenty Compat)
+dtbop@dynamic-trees-biomes-o-plenty|动态的树:超多生物群系附属 (Dynamic Trees - Biomes O' Plenty Compat)
dynamic-trees-compatibility-for-climatic-biomes|动态的树:气候生态群系附属 (Dynamic Trees Compatibility for Climatic Biomes)
capability-adapter|ME功能适配器 (ME Capability Adapter)
tf2-stuff-mod|军团要塞2 (TF2 stuff mod)
@@ -1978,11 +1978,11 @@ kottle
customdrones|自定义无人机 (Custom Drones)
call-to-battle-2-authentic-world-war-2-experience|战争召唤2 (Call To Battle 2)¨call-to-battle-the-wwii-mod|战争召唤2 (Call To Battle 2) - 远古
some-like-it-dry
-yungs-better-caves|YUNG的洞穴优化 (YUNG's Better Caves)¨yungs-better-caves-fabric|YUNG的洞穴优化 (YUNG's Better Caves)
+yungs-better-caves|YUNG 的洞穴优化 (YUNG's Better Caves)¨yungs-better-caves-fabric|YUNG 的洞穴优化 (YUNG's Better Caves)
resynth|神农科技*
flatworld|开山棒 (Flat World)
pymtech|皮姆科技 (PymTech)
-corail-tombstone|Corail的墓碑 (Corail's Tombstone)
+corail-tombstone|Corail 的墓碑 (Corail's Tombstone)
arcane-archives|奥术档案馆*
@@ -2005,7 +2005,7 @@ world-primer
bookworm
openeye|错误报告器 (OpenEye)
-let-sleeping-dogs-lie|嘘,别吵醒狗狗*¨let-sleeping-dogs-lie-for-fabric|嘘,别吵醒狗狗 (Let Sleeping Dogs Lie)
+let-sleeping-dogs-lie@|嘘,别吵醒狗狗*¨let-sleeping-dogs-lie-for-fabric|嘘,别吵醒狗狗 (Let Sleeping Dogs Lie)
super-ores|超级矿石*
gravelminer@|沙砾终结者 (GravelMiner)¨gravelminer-fabric|沙砾终结者 (GravelMiner)
@@ -2040,7 +2040,7 @@ zollern-galaxy|卓伦星系*
macaws-bridges|Macaw的桥梁 (Macaw's Bridges)
trample-stopper|防止踩踏*¨trample-stopper-fabric|防止踩踏 (Trample Stopper)
-macaws-roofs|Macaw的屋顶 (Macaw's Roofs)
+macaws-roofs@|Macaw的屋顶 (Macaw's Roofs)
shadows-of-greg|格雷之影 (Shadows of Greg)
loottabletweaker@
rockycore
@@ -2067,7 +2067,7 @@ traitors-better-swampland-mod|更好的沼泽 (Traitor's Better Swamplands Mod)
soviet-abandoned-lab-mod@soviet-era|苏维埃风格装饰 (Soviet Era Mod(earlier Soviet Lab))
charm@¨charm-reforged
-village-names@|村庄名字*¨villager-names-fabric|村庄名字 (Village Names)
+village-names@|村庄名字*
advanced-rocketry-tweaker
alternating-flux|交变磁通*
projectextended|等价交换扩展 (ProjectExtended)
@@ -2154,7 +2154,7 @@ usefultnt|更有用的TNT (UsefulTNT)
crow-flight|乌鸦坐飞机*
findme@|东寻西觅 (FindMe)
-minecraft-transit-railway@|我的世界铁路*
+minecraft-transit-railway|我的世界铁路* - 较为落后¨@minecraft-transit-railway|我的世界铁路 (Minecraft Transit Railway)
random-loot-mod|随机战利品*
tinkers-aether|天境工匠*
@@ -2174,7 +2174,7 @@ wsbim-legacy-blocks-and-items
storage-items-mod
what-should-be-in-mc-wsbim
bluestone
-effortless-building
+effortless-building@
ic2-classic-tweaker
Ic2c-Crop-Overrides|IC2经典版作物覆盖 (IC2C Crop Overrides)
ic2c-extras|工业时代2经典版拓展 (IC2C Extras)
@@ -2223,11 +2223,11 @@ hurt-animation-remover
more-cauldrons|更多炼药锅*
parabox
sky-grid
-forbidden-arcanus|禁忌与奥秘 (Forbidden and Arcanus)
+forbidden-arcanus@|禁忌与奥秘 (Forbidden and Arcanus)
mysticalmechanics|奇械学 (Mystical Mechanics API)
backpacked|背包*¨backpacked-fabric|背包 (Backpacked)
starship|星舰 (StarShip)
-tweakeroo
+tweakeroo@
integrated-rest@
citadel@
screenshot-browser|内置截图管理器*
@@ -2258,7 +2258,7 @@ tfc-metric|公制重量转换 (TFC Metric)
tfc-additions|群峦附加 (TFC-Additions)
raolcraft-w
-litematica-forge|投影 (Litematica)¨litematica|投影*
+litematica@|投影*¨litematica-forge|投影 (Litematica)
telepastries|传送蛋糕 (TelePastries)
heroesexpansion|超级英雄拓展 (HeroesExpansion)
attributefix@|属性修复 (AttributeFix)
@@ -2308,7 +2308,7 @@ rediscovered|特性重现*
baubles-reborn|饰品栏重置版*
pams-brewcraft|潘马斯酿造工艺 (Pam's Brewcraft)
dirtcraft|泥土工艺 (DirtCraft)
-minihud|迷你HUD (MiniHUD)
+minihud@|迷你HUD (MiniHUD)
potato-craft|土豆工艺*
bed-patch
@@ -2388,13 +2388,13 @@ tube-transport-system|管道传输系统*
transmutation-alchemy¨transmutation-alchemy-revival
extra-spells-electroblobs-wizardry|额外咒语 (Extra Spells)
ancient-spellcraft|古代咒法*
-moving-elevators@
+@moving-elevators
interstellar-exoplanets@|星际:系外行星 (Interstellar: Exoplanets)
infini-tic
extra-disks@|更多磁盘*
optiforge
magic-seeds-for-electroblobs-wizardry|巫术学魔法种子 (Magic seeds for Electroblobs Wizardry)
-extra-alchemy|扩展炼药*
+extra-alchemy@extraalchemy|扩展炼药*
beyond-the-veil|帷幕彼端*
maple-syrup|枫糖*
blood-particles|血液粒子效果*
@@ -2491,8 +2491,8 @@ beesourceful
middle-earth-industry|中洲工业 (Middle-Earth Industry)
thut-wearables
after-the-drizzle|细雨田园 (After the Drizzle)
-cmdcam|CMD指令摄影机 (CMDCam)
-climate-control-geographicraft|气候控制/地理世界 (Climate Control/Geographicraft)
+cmdcam|CMD 指令摄影机 (CMDCam)
+climate-control-geographicraft@geographicraft|气候控制 / 地理世界 (Climate Control / Geographicraft)
cosmetic-armor-reworked|时装盔甲重置版*
@@ -2610,7 +2610,7 @@ karat-garden|克拉的花园*
bard-mania
shulkerboxtooltip@|潜影盒工具提示 (Shulker Box Tooltip)
-crafting-dead-official|行尸走肉 (Crafting Dead)
+crafting-dead-official|行尸走肉 (Crafting Dead)¨crafting-dead-legacy|行尸走肉 (Crafting Dead)
lord-craft
@@ -2633,7 +2633,7 @@ quirky-generators
megaloot|超级战利品 (MegaLoot)
mad-villagers|疯狂的村民*
-logical-drops|逻辑工艺 (Logical Craft)
+logical-drops|逻辑工艺 (Logical Craft / Logical Drops)
drone-craft
water-source|水源*
@@ -2714,7 +2714,7 @@ recipe-stages|配方阶段*
attack-on-minecraft@wingsoffreedom|自由之翼 (Wings of Freedom)
cavern-miner|洞穴:矿工 (Cavern: Miner)
vanilla-tools|原版工具+ (Vanilla Plus Tools)
-server-tab-info
+server-tab-info@
letsencryptcraft
creeperhost-minetogether
@@ -2736,7 +2736,7 @@ hunterillager@hunters-return|邪猎者 (HunterIllager)
pocket-apocalypse-mod|便携式天灾 (Pocket Apocalypse mod)
compass|指南针 (compass)
-tinkers-evolution|匠魂进化 (Tinkers' Evolution)
+tinkers-evolution@|匠魂进化 (Tinkers' Evolution)
tinkers-exporter|匠魂数据导出器*
farlanders@the-farlanders|更多末影人 (The Farlanders)
vials|瓶瓶罐罐*
@@ -2749,11 +2749,11 @@ immersive-energy|沉浸能源*
crimson-moon|绯红之月*
mobs-attempt-parkour@
identity|化身*¨identity-on-forge|化身 (Identity)
-industrial-revolution|工业革命*
+industrial-revolution@|工业革命*
art-of-alchemy|炼金艺术 (Art of Alchemy)
lan-server-properties|自定义局域网联机*
-immersive-intelligence|沉浸智能*
+immersive-intelligence@|沉浸智能*
analyzeio
wool-buttons@|羊毛按钮*
total-tinkers|统合匠艺*
@@ -2785,7 +2785,7 @@ stepup|平滑自动上坡 (StepUp)
sodium@|钠*
netherlicious
-yungs-better-mineshafts-forge@yungs-better-mineshafts|YUNG的矿井优化 (YUNG's Better Mineshafts)¨yungs-better-mineshafts-fabric|YUNG的矿井优化 (YUNG's Better Mineshafts)
+yungs-better-mineshafts-forge@yungs-better-mineshafts|YUNG 的矿井优化 (YUNG's Better Mineshafts)¨yungs-better-mineshafts-fabric|YUNG 的矿井优化 (YUNG's Better Mineshafts)
terrible-chest|可怕的箱子/可怖箱子*
spartan-shields@|斯巴达之盾*
silent-gear@|寂静装备*
@@ -2815,7 +2815,7 @@ never-needed-or-wanted
ama-damage-indicator
magic-circle|阵法*
-crash-utilities
+crash-utilities@
eldritch-mobs@
farmers-delight@|农夫乐事 (Farmer's Delight)¨farmers-delight-fabric@|农夫乐事 (Farmer's Delight)
artifacts@|奇异饰品*¨artifacts-fabric|奇异饰品 (Artifacts)
@@ -2849,10 +2849,10 @@ camera-mod@|照相机*
heartdrops|生命汲取 (Heart Drops)
observerlib
zen-summoning
-campanion|野营物品* - Farbic¨campanion-forge@campanion|野营物品 (Campanion)
+campanion-forge@campanion|野营物品 (Campanion)¨campanion|野营物品* - Farbic
wolves-with-armor|狼铠*¨wolves-with-armor-forge|狼铠 (Wolves With Armor)
get-exp-for-everything|万物皆可获得经验 (Get exp for everything)
-jei-enchantment-info|JEI附魔信息 (JEI Enchantment Info)
+jei-enchantment-info|JEI 附魔信息 (JEI Enchantment Info)
project-red-fabrication|红石计划:制作 (Project Red - Fabrication)
project-red-integration|红石计划:集成 (Project Red - Integration)
@@ -2868,7 +2868,7 @@ better-loading-screen|自定义加载画面 (Custom Loading Screen)
extended-lights-mod|灯具拓展 (Extended Lights)
more-swords-legacy@|更多剑:传承*
the-undergarden@|深暗之园*
-allure|诱惑*
+mc-modsure|诱惑 (Allure)
glibys-voice-chat-reloaded|Gliby的语音聊天重置版 (Gliby's Voice Chat Reloaded)
greater-eye-of-ender-fabric|高级末影之眼 (Greater Eye of Ender)¨greater-eye-of-ender-forge|高级末影之眼 (Greater Eye of Ender)
@@ -2906,7 +2906,7 @@ wtfs-expedition-cavebiomes-ores-trees-and-tweaks
guide-api-village-and-pillage@guide-api
drcyanos-lootable-bodies|可拾取尸体 (DrCyano's Lootable Bodies)
simply-cats@
-pams-harvestcraft-2-crops|潘马斯农场2 - 作物 (Pam's HarvestCraft 2 - Crops)
+pams-harvestcraft-2-crops@|潘马斯农场2 - 作物 (Pam's HarvestCraft 2 - Crops)
base-metals|基础金属*
mmdlib
@@ -2927,12 +2927,12 @@ scavenge
heaven-earth-ring|乾坤戒指*
-pams-harvestcraft-2-food-extended|潘马斯农场2 - 食物拓展 (Pam's HarvestCraft 2 - Food Extended)
+pams-harvestcraft-2-food-extended@|潘马斯农场2 - 食物拓展 (Pam's HarvestCraft 2 - Food Extended)
-pams-harvestcraft-2-trees|潘马斯农场2 - 果树 (Pam's HarvestCraft 2 - Trees)
+pams-harvestcraft-2-trees@|潘马斯农场2 - 果树 (Pam's HarvestCraft 2 - Trees)
minecart-direction-follow¨better-minecart-rotation-forge
modern-metals|现代金属*
-block-renderer¨blockrenderer
+blockrenderer¨block-renderer
blockus@
conjurers-cookbook
color-unchained
@@ -2947,12 +2947,12 @@ furbishcraft
ambientsounds@|自然音效 (AmbientSounds)
ordinary-firearms|普通枪械2 (Ordinary Firearms 2)
territory|领地 (MineTerritory)
-better-ping-display@better-ping-display-fabric|更好的延迟显示*¨better-ping-display-fabric@better-ping-display|更好的延迟显示 (Better Ping Display)
+better-ping-display@|更好的延迟显示*¨better-ping-display-fabric@|更好的延迟显示 (Better Ping Display)
turned-the-changed-mod
survival-tweaks|生存微调*
-melon-slabs|西瓜台阶*
-lambdynamiclights@|Lambda的动态光源 (LambDynamicLights)
-realistic-torches|真实火把*
+melon-slabs@|西瓜台阶*
+lambdynamiclights@|Lambd 的动态光源 (LambDynamicLights)
+realistic-torches@|真实火把*
durability-viewer|耐久显示器*
@@ -2971,15 +2971,15 @@ travellers-boots
cofh-vanilla-satchels
betteranimalsplus|更多动物 (Better Animals Plus)
-packagedauto|封包合成 (PackagedAuto)
-packagedexcrafting|封包合成拓展 (PackagedExCrafting)
+packagedauto@|封包合成 (PackagedAuto)
+packagedexcrafting@|封包合成拓展 (PackagedExCrafting)
-compactstorage@compact_storage|紧凑存储 (compactstorage)
-useful-backpacks|实用背包*
+compactstorage|紧凑存储 (compactstorage)¨@compact_storage|紧凑存储 (compactstorage) - 已失效
+useful-backpacks@|实用背包*
conquest-reforged@|征服者*
steelseries-gamesense
pizzaatimes-timber-mod
-tellme
+tellme@
minerva-library
@@ -2998,7 +2998,7 @@ oc-sensors
fabric-for-fabric
storage-tech
thaumic-periphery|神秘外饰*
-embellishcraft|装饰工艺 (EmbellishCraft)
+embellishcraft@|装饰工艺 (EmbellishCraft)
open-loader@|开放式加载*
deep-mob-learning-refabricated@|深度怪物学习:重制版 (Deep Mob Learning: Refabricated)
ftb-ultimine-forge|连锁破坏 (FTB Ultimine)¨ftb-ultimine-fabric|连锁破坏 (FTB Ultimine)
@@ -3024,9 +3024,9 @@ crock-pot|烹饪锅*
together-forever
-iron-furnaces|更多熔炉*¨iron-furnaces-fabric|更多熔炉 (Iron Furnaces)
+iron-furnaces@|更多熔炉*¨iron-furnaces-fabric|更多熔炉 (Iron Furnaces)
-lenient-creepers|仁慈的苦力怕*
+lenient-creepers@|仁慈的苦力怕*
treasure2|寻宝记2 (Treasure2!)
@autoreconnector-fabric|自动断线重连 (AutoReconnector-Fabric)
@@ -3041,12 +3041,12 @@ tumat
riddle-chests|谜题箱*
totem-plus|图腾增强*
-blockmeterfabric@blockmeter|方块计量表 (BlockMeterFabric)
+blockmeterfabric@blockmeter|方块计量表 (Block Meter Fabric)
fluid-drawers|储液抽屉*
creepypastacraft-reborn|蠕动意面重置版 (CreepyPastaCraft Reborn)
itemzoom|物品缩放 (ItemZoom)
-light-overlay|亮度覆盖*
+light-overlay@|亮度覆盖*
smallerfpsincrements
regex-filters|正则表达式过滤器*
@@ -3192,13 +3192,13 @@ extracpus|更多CPU (Extra CPUs)
extra-crafting-storage
underground-city-engineering@|地下城市工程*
-essentials
+essentials@essentialsmod
soul-shards-respawn
soul-shards-the-old-ways
the-flying-things
ftb-ranks¨ftb-ranks-fabric
-ftb-chunks-forge¨ftb-chunks-fabric
+ftb-chunks-forge|FTB 区块 (FTB Chunks)¨ftb-chunks-fabric|FTB 区块 (FTB Chunks)
ftb-essentials
silveroak-outpost|银橡前哨*
pehkui@
@@ -3223,7 +3223,7 @@ boatload@|额外船只 (Extra Boats / Boatload)¨extra-boats@|额外船只 (Extr
outvoted@|落选生物*
attribute|属性修复 - Fabric版 (Attribute Fix {FABRIC})
-packmodemenu|PackMode菜单 (PackModeMenu)
+packmodemenu|PackMode 菜单 (PackModeMenu)
simple-gamemodes|游戏模式短指令*
uniq|流体统一/物品统一 (UniQ)
@@ -3244,13 +3244,13 @@ inventory-free|无物品栏 (Inventory-Free)
randompatches-integration
bubble-column-elevator-backport|1.13水域机制 (1.13 Water Mechanics)
-basic-nether-ores|基础下界矿石*
+basic-nether-ores@|基础下界矿石*
nuclearcraft-reactor-builder|核电工艺反应堆建造机 (NuclearCraft Reactor Builder)
pams-harvestcraft-2-food-core@|潘马斯农场2 - 食物核心 (Pam's HarvestCraft 2 - Food Core)
eki-lib
@immibis-core
nodami|伤害免疫机制移除 (No Damage Immunity)
-astrological-sorcery|星占魔法*
+astrological-sorcery@|星占魔法*
efab-ct-bindings
golden-hopper|金漏斗*
wizardry-golems|巫术傀儡*
@@ -3306,23 +3306,23 @@ shoulder-surfing-reloaded@|越肩视角重制*
aqua-acrobatics|水游技艺*
silents-mechanisms|寂静机械 (Silent Mechanisms)
project-potman|背锅人计划 (ProjectPotman)
-nbt-crafting@|数据包NBT合并*
+nbt-crafting@|数据包 NBT 合并*
diregoo
ogdragon|OG龙+ (OGDragon+)
sevtweaks
journeymapstages|旅行地图阶段控制 (JourneyMapStages)
-textile-backup@textile_backup|Textile备份*
+textile-backup@textile_backup|Textile 备份*
goopers
mob-drops|自定义生物战利品 (Mob Drops Your Way)
alexs-mobs@|Alex 的生物 (Alex's Mobs)
-all-stackable@|可堆叠物品自定义*
+mc-mods-stackable@all-stackable|可堆叠物品自定义 (All Stackable)
thermal-mj|热力MJ支持 (Thermal MJ)
ctd-core@
time-speed-mod|Minecraft地球自转/真实昼夜循环 (Вращение Земли Майнкрафтская (Accurate day/night-cycles Mod))
mineral-tracker
-carpet-extra@|Carpet拓展 (carpet-extra)
+carpet-extra@|Carpet 拓展*
viafabric@
double-slabs|双重台阶*
@@ -3375,7 +3375,7 @@ assembly-line-machines|装配线*
netherending-ores
Flex-FOV|扭曲视野*
hooked|抓钩*
-createtweaker
+createtweaker@
iTorch
gullivern
@@ -3389,7 +3389,7 @@ time-travel-mod|时间旅行*
backslotaddon@|背用武器拓展 (BackSlotAddon)
optifabric-1-8-9
-gt6-ore-helper|GT6矿石助手 (GT6 Ore Helper)
+gt6-ore-helper|GT6 矿石助手 (GT6 Ore Helper)
applied-integrations|应用集成*
inventory-hud-forge|物品栏HUD+ (Inventory HUD+)
@@ -3470,7 +3470,7 @@ eidolon|幻梦*
rats-ratlantis|老鼠:鼠西洲 (Rats: Ratlantis)
wthit@¨wthit-forge
modern-industrialization@|现代工业化*
-chunk-pregenerator-fabric|区块预生成器(Fabric) (Fabric Chunk Pregenerator)
+chunk-pregenerator-fabric@fabricquilt-chunk-pregenerator|区块预生成器(Fabric) (Fabric Chunk Pregenerator)
jumploader
unloader
better-animal-models|更真实的动物 (Better animal models)
@@ -3488,14 +3488,14 @@ clear-despawn
unionlib@
-botany-trees@
+botany-trees@|植树盆栽*
better-third-person@
survive|生存要素*
wallpapercraft-a-fresh-roll-stairs|墙纸创造:楼梯 (Wallpapercraft - A Fresh Roll (Stairs!))
wallpapercraft-a-fresh-roll-slabs|墙纸创造:台阶 (Wallpapercraft - A Fresh Roll (Slabs!))
wallpapercraft-a-fresh-roll-walls|墙纸创造:围墙 (Wallpapercraft - A Fresh Roll (Walls!))
compact-crafting
-assembly-lines|装配线*
+assembly-lines@|装配线*
botany-pots@|植物盆栽*
callable-horses|召之马来*
@@ -3510,7 +3510,7 @@ hats|帽子*
smoother-bedrock|平滑基岩层*
c2me-fabric@|C^2M 引擎 (C^2M-Engine/Concurrent Chunk Management Engine)
datapack-anvil
-nuclear-science|核科学*
+nuclear-science@|核科学*
glaretorch|强光火把 (Glare Torch)
mrcrayfishs-jumping-castle-mod|MrCrayfish的充气城堡 (MrCrayfish's Jumping Castle)
exposer
@@ -3538,7 +3538,7 @@ zycraft
quitconfirm|退出前确认 (QuitConfirm)
ruined-equipment@
clickthrough@|穿牌开箱 (ClickThrough)
-dynamic-sound-filters|动态声音滤波器*
+dynamic-sound-filters@|动态声音滤波器*
binniepatcher
subterranean-wilderness
@@ -3557,9 +3557,9 @@ more-fuels-mod
pointless-tech-collective
revampedwolf@
-bedrock-b-gone
+bedrock-b-gone@
-elemental-creepers|元素爬行者*
+elemental-creepers@|元素爬行者*¨elemental-creepers-og|元素爬行者 (Elemental Creepers)
gymcraft
infernal-expansion@|地狱扩展*
@@ -3580,8 +3580,8 @@ xnicex@
krate
chickensshed|鸡棚重置版 (ChickensShed)
chickenshed
-expanded-storage-fabric@expanded-storage|扩展存储 (Expanded Storage)¨expanded-storage-forge|扩展存储 (Expanded Storage)¨expanded-storage|扩展存储*
-project-mmo
+expanded-storage@|扩展存储*¨expanded-storage-fabric|扩展存储 (Expanded Storage)¨expanded-storage-forge|扩展存储 (Expanded Storage)
+project-mmo@
abnormals-delight@
jojos-bizarre-survival
@@ -3608,9 +3608,9 @@ when-dungeons-arise@|地牢浮现之时*¨when-dungeons-arise-fabric|地牢浮
animal-feeding-trough@animal_feeding_trough|动物喂养槽*
wiki-zoomer@
personality@personality!
-allurement@allurement!
+mc-modsurement@allurement!
dwarf-miner-totem|矮人矿工*
-yungs-better-portals|YUNG的传送门机制重构 (YUNG's Better Portals)
+yungs-better-portals|YUNG 的传送门机制重构 (YUNG's Better Portals)
german-road-signs-mod|德国交通标志*
iguana-in-a-blanket|真实调整 (Iguana in a Blanket)
anthill-inside|蚂蚁物流*
@@ -3641,7 +3641,7 @@ abundance@
just-enough-calculation
-mythicbotany|神话植物学 (MythicBotany)
+mythicbotany@|神话植物学 (MythicBotany)
improved-mobs|怪物增强*¨improved-mobs-fabric|怪物增强 (Improved Mobs)
limitless|无上限附魔*
vpn-blocker|禁用VPN (VPN Blocker)
@@ -3652,7 +3652,7 @@ configured|配置界面*¨configured-fabric|配置界面 (Configured)
jellyfishing@|抓水母*
accurate-block-placement
-pro-placer|放置专家*
+pro-placer@|放置专家*
farmers-delight-compats
farmers-tea|农夫的茶 (Farmer's Tea)
farmers-delight-integration
@@ -3661,7 +3661,7 @@ anvil-fix|铁砧修复*
no-increasing-repair-cost
wool-temples|羊毛神殿*
exp-bottling|经验装瓶 (EXP Bottling)
-buildersaddition
+buildersaddition@
gt-remastered|格雷科技重制版 (GT: Remastered)
tips|提示*
Interactio
@@ -3684,7 +3684,7 @@ inductive-logistics|集成物流*
automatic-path
morevanillalib@
-vanilla-excavators@excavar¨vanilla-excavators-forge
+vanilla-excavators@¨vanilla-excavators-forge
dynagear
morevanillatools@|更多原版工具 (MoreVanillaTools)
colorful-health-bar
@@ -3692,7 +3692,7 @@ tipline
ultimate-plane-mod@|终极飞机*
simple-voice-chat@|简单的语音聊天*
not-enough-milk
-ewewukeks-musket-mod|ewewukek的火枪模组 (ewewukek's Musket mod)
+ewewukeks-musket-mod|ewewukek 的火枪模组 (ewewukek's Musket mod)
irisshaders@iris
@dimthread|世界多线程化 (DimensionalThreading)
@@ -3718,8 +3718,8 @@ random-title|随机标题*
astikorcarts
@invsync|背包同步 (InvSync)
jea@|JEI进度 (Just Enough Advancements)
-et-futurum-requiem¨@etfuturum
-better-op|更好的OP*
+et-futurum-requiem|把未来带回现实* - <2.7.0¨@etfuturum|把未来带回现实 (Et Futurum Requiem) - ≥2.4.0
+better-op|更好的 OP*
fastworkbench-minus-replacement
crimson-compass|绯红指南针*
tinkers-construct@|匠魂 (Tinkers' Construct)
@@ -3779,12 +3779,12 @@ astromine-foundations|天体矿工:基础 (Astromine: Foundations)
create-stuff-additions@|机械动力:物品附加 (Create Stuff & Additions)
slab-machines|台阶型设备*
more-create-stuffs|更多机械动力物品*
-rsinfinitybooster|RS无限范围增幅卡 (RSInfinityBooster)
+rsinfinitybooster|RS 无限范围增幅卡 (RSInfinityBooster)
cuneiform
terraincognita
cloth-api
ingameime|游戏内输入法 (IngameIME)
-yungs-better-strongholds@|YUNG的要塞优化 (YUNG's Better Strongholds)¨yungs-better-strongholds-fabric|YUNG的要塞优化 (YUNG's Better Strongholds)
+yungs-better-strongholds@|YUNG 的要塞优化 (YUNG's Better Strongholds)¨yungs-better-strongholds-fabric|YUNG 的要塞优化 (YUNG's Better Strongholds)¨yungs-better-strongholds-neoforge|YUNG 的要塞优化 (YUNG's Better Strongholds)
mojangdark|暗色加载 (MojangDark)
astromine-technologies|天体矿工:科技 (Astromine: Technologies)
astromine-transportations|天体矿工:运输 (Astromine: Transportaions)
@@ -3799,7 +3799,7 @@ ex-nihilo-sequentia-mekanism-addon|无中生有:传承 - 通用机械扩展 (E
panorama@swd-panorama|全景图*
bgcore
induction-charger
-tiered-forge¨tiered
+tiered-forge@tiered¨tiered
c-o-m-b-a-t
burden-of-time
gamemenumodoption@|游戏菜单模组设定 (Game Menu Mod Option)
@@ -3821,7 +3821,7 @@ cat-jammies
rhino@|犀牛*
fastsuite|配方性能优化 (FastSuite)
twerkitmeal|跳舞生长一切 (Twerk To Grow All The Things)
-thermal-expansion@thermal-foundation|热力膨胀*¨thermal-integration@thermal-locomotion|热力集成*
+thermal-integration@thermal-locomotion|热力集成*
piggybanks|存钱罐*
in-control@
mystical-agriculture-refabricated|神秘农业:Fabric版 (Mystical Agriculture: Refabricated)
@@ -3851,7 +3851,7 @@ ctm-fabric|连接纹理Fabric版 (ConnectedTexturesMod for Fabric)
whats-that-slot@
pmmo-and-nbt-compat
techstacks-heavy-machinery-mod
-enhanced-mushrooms|蘑菇增强*¨enhanced-mushrooms-fabric|蘑菇增强 (Enhanced Mushrooms)
+enhanced-mushrooms@|蘑菇增强*¨enhanced-mushrooms-fabric|蘑菇增强 (Enhanced Mushrooms)
versatile-portals|通用传送门*
spawn-egg-recipes|刷怪蛋配方注册*
configurable-extra-mob-drops@|可配置的额外怪物掉落*¨configurable-extra-mob-drops-fabric|可配置的额外怪物掉落 (Configurable Extra Mob Drops)
@@ -3888,14 +3888,14 @@ entity-nan-health-fix|假死修复 (Entity NaN Health Fix)
ferritecore@ferrite-core|铁氧体磁芯 (FerriteCore)¨ferritecore-fabric|铁氧体磁芯 (FerriteCore)
thaumcraft-research-patcher
masterful-machinery
-minecraft-earth-mod|Derec的地球生物 (Derec's Earth Mobs)
+minecraft-earth-mod|Derec 的地球生物 (Derec's Earth Mobs)
scotts-essential
drawerfps|储物抽屉渲染配置 (DrawerFPS)
cursed-earth¨cursed-earth-fabric
sll|逆向交易 (sɹǝƃɐllᴉΛ)
lagmeter|延迟表 (LagMeter)
-hexxit-gear-2|Hexxit装备2*
+hexxit-gear-2|Hexxit 装备 2 (Hexxit Gear R)
scootys-plants-vs-zombies|Scooty的植物大战僵尸重生 (Scootys Plants Vs. Zombies Regrown)
@@ -3905,7 +3905,7 @@ bonsai-tree-crops
rpgz@
-
+@stationapi
scavenge-timing-addon
cull-particles|粒子渲染机制优化*¨cull-particles-fabric|粒子渲染机制优化 (Cull Particles)
majos-broom|魔女的扫帚 (Majo's broom)
@@ -3930,7 +3930,7 @@ incubation@
create-goggles@
-coloured-tooltips@colored-tooltips-fabric
+coloured-tooltips@|彩色提示框*
magicraft-magic|魔法材料 (Magical Materials)
glowstone-ores|荧石矿石*
more-wires
@@ -3941,7 +3941,7 @@ wild-netherwart|野生地狱疣*
the-periodic-table-mod|元素周期表 (The Periodic Table)
adamantium-in-minecraft
forgerocks
-ballistix|弹道学*
+ballistix@|弹道学*
wireless-industry
spice-of-life-tonio-edition|生活调味料:托尼欧版 (Spice of Life: Tonio Editon)
husk-spawn@|尸壳生成微调*¨husk-spawn-fabric|尸壳生成微调 (Husk Spawn)
@@ -3973,7 +3973,7 @@ time-in-a-bottle-standalone|时间之瓶 (Time in a bottle standalone)
compressed-grass|压缩草*
applepie|苹果派 (ApplePie)
doles-mod
-ex-nihilo-sequentia-thermal-addon|无中生有:传承 - 热力扩展 (Ex Nihilo: Sequentia - Thermal Addon)
+ex-nihilo-sequentia-thermal-addon@|无中生有:传承 - 热力扩展 (Ex Nihilo: Sequentia - Thermal Addon)
ex-naturae@|无中生有:传承 - 植物魔法扩展*
ex-nihilo-sequentia-tinkers-addon|无中生有:传承 - 匠魂扩展 (Ex Nihilo: Sequentia - Tinkers Addon)
iron-jetpacks@¨iron-jetpacks-fabric
@@ -4046,7 +4046,7 @@ skds-core
endertech|末影科技 (Ender Tech)
enderpig-mod|末影猪*
-
+no-no-ai-spawn|镇压前端召唤 (No No-AI Spawn)
atomic-bomb-1-16|枪,炮,原子弹! (Guns, Rockets and Atomic Explosions)
se-sign-shop|简单经济:牌子商店 (SE: Sign Shop)
@@ -4066,7 +4066,7 @@ incendium@
cooperative-advancements|合作进度*¨cooperative-advancements-fabric|合作进度 (Cooperative Advancements)
lightstones
openbackup
-fat-experience-orbs|肥胖经验球 ([Fabric] Fat Experience Orbs) - 已失效¨@fat-experience-orbs|肥胖经验球 ([Fabric] Fat Experience Orbs)
+fat-experience-orbs@|肥胖经验球 ([Fabric] Fat Experience Orbs)
better-pipes|更好的管道*
truetype-font-replacement
fluidlogged-api@
@@ -4112,8 +4112,8 @@ village-employment@|村庄就业*
deathlog@|死亡日志*
automatic-elytra|自动鞘翅*
-axolotl-bucket-fix|美西螈桶修复*
-xks-decoration|XK的装饰 (XK's Deco)
+axolotl-bucket-fix@|美西螈桶修复*
+xks-decoration@|XK的装饰 (XK's Decoration)
endgame-materials-addons|更多终局材料*
ravage-and-cabbage@
stackup
@@ -4127,9 +4127,9 @@ moarrecipes|更多的配方 (MoarRecipes)
luminium
better-nether-map-port@better-nether-map
-iguanatweaks-reborn|生存重构/蜥蜴微调重生 (Survival Reimagined/IguanaTweaks Reborn)
+iguanatweaks-reborn|生存重构/蜥蜴微调重生 (Survival Reimagined / IguanaTweaks Reborn)
enter-the-void|进入虚空*
-tensura-mod-that-time-i-got-reincarnated-as-a-slime|关于我转生变成史莱姆这档事 (Tensura Mod -That time I got reincarnated as a Slime)
+tensura-mod-that-time-i-got-reincarnated-as-a-slime@tensura-mod|关于我转生变成史莱姆这档事 (Tensura Mod -That time I got reincarnated as a Slime)
speedometer@speedometer-cafeteria|速度表*
falling-leaves-forge@fallingleavesforge|落叶 (Falling Leaves (NeoForge/Forge))
@@ -4154,7 +4154,7 @@ beehivetooltips|蜂巢工具提示 (BeehiveTooltips)
buddycards@|巴迪卡牌*
extended-caves@expanded-caves¨expanded-caves
-inventorio¨inventorio-forge
+inventorio@¨inventorio-forge
more-curios-totems-of-undying
selene@moonlight
compatibilitylayerforcustomskinloader|万用皮肤补丁兼容层 (CompatibilityLayerForCustomSkinLoader)
@@ -4193,7 +4193,7 @@ insanelib@
daydreamer
phantomfaces|幻灵接口*
improved-villagers|改进的村民 (Improved Villager Mod)
-equipment-compare|装备比较*¨equipment-compare-fabric|装备比较 (Equipment Compare)
+equipment-compare@|装备比较*¨equipment-compare-fabric|装备比较 (Equipment Compare)
PickupWidely
@@ -4235,7 +4235,7 @@ its-the-little-things
fruitful@|硕果累累*¨fruitful-fabric|硕果累累 (Fruitful)
environmental-energy@|环境科技-发电机*
nakranoths-herdcraft|群兽行为 (Nakranoth's Herdcraft)
-lambdabettergrass@|Lambda的更好的草方块 (LambdaBetterGrass)
+lambdabettergrass@|Lambd 的更好的草方块 (LambdaBetterGrass)
@client-commands
bright-ore|矿石高亮*
chinese-style-sword|中式剑 (Arsenal Core)
@@ -4273,7 +4273,7 @@ custom-entity-models-kaimyentity-reborn|自定义玩家和实体模型 / KAI我
miniutilities|迷你实用设备 (Mini Utilities)
stumble-upon-campsites|邂逅:营地 (Stumble Upon: Campsites)
nomad-books|游牧之书*
-yungs-extras@¨yungs-extras-fabric
+yungs-extras@¨yungs-extras-fabric¨yungs-extras-neoforge
stoneholm-forge@stoneholm|地下村庄 (Stoneholm, Underground Villages)¨stoneholm|地下村庄 (Stoneholm, Underground Villages)
inspecio@
@@ -4369,7 +4369,7 @@ simple-ambients
modern-loading-screen|现代加载界面*
-
+dong-dongs-random-creation@|冬冬的随意创作 (Dong Dong's random creation)
transliterationlib
@@ -4426,7 +4426,7 @@ terracore
seeker-compass
ghosts-explosives
power-drop@|蓄力投掷*
-yungs-better-dungeons@|YUNG的地牢优化 (YUNG's Better Dungeons)¨yungs-better-dungeons-fabric|YUNG的地牢优化 (YUNG's Better Dungeons)
+yungs-better-dungeons@|YUNG 的地牢优化 (YUNG's Better Dungeons)¨yungs-better-dungeons-fabric|YUNG 的地牢优化 (YUNG's Better Dungeons)¨yungs-better-dungeons-neoforge|YUNG 的地牢优化 (YUNG's Better Dungeons)
ore-controller
morechickens@|更多鸡 (MoreChickens)
@@ -4468,10 +4468,10 @@ plumed-belt
better-with-minecolonies
calemis-utilities|Calemi的实用设备 (Calemi's Utilities)
botanical-cowardice
-travelers-titles@¨travelers-titles-fabric
+travelers-titles@¨travelers-titles-fabric¨travelers-titles-neoforge
expand-chinese-sword|中式剑拓展 (Arsenal Integration)
-littleframes@littlepictureframes|小画 (LittleFrames)
+littleframes@littlepictureframes|小画 (LittlePictureFrames)
lavalogged-blocks|岩浆充填 (Lavalogged blocks)
awoken-world
gt4-reimagined|格雷科技4:重构想 (GregTech 4 Reimagined)
@@ -4494,7 +4494,7 @@ essential-commands@
caves-and-cliffs-backport
that-future-mod-glow-squid-axolotl-moobloom-etc
diamond-buildcraft|钻石装饰*
-apocalypse-rebooted|启示录重制*
+apocalypse-rebooted|启示录重制* - 已失效¨@apocalypse-rebooted|启示录重制 (Apocalypse Rebooted)
mcwifipnp@|更高级联机设置 (LAN World Plug-n-Play)
requious-frakto
@@ -4508,7 +4508,7 @@ sync-fabric@|克隆(Fabric) (Sync (Fabric))
tale-of-kingdoms-a-new-conquest@|王国:新征程 (Tale of Kingdoms: A new Conquest)
schwarz@|黑*
-megane@¨megane-forge
+megane@¨megane-forge@
crusade@
vending-machine|售货机*
modernxl
@@ -4522,12 +4522,12 @@ electrona
reasonable-sorting@|合理排序*
chat-heads@|聊天头像*
hidden-armor|隐藏盔甲*
-majruszs-progressive-difficulty|Majrusz的进阶难度 (Majrusz's Progressive Difficulty)
+majruszs-progressive-difficulty@|Majrusz的进阶难度 (Majrusz's Progressive Difficulty)
pharmacist|药师*
kappa@
equivalent-integrations|等价集成*
keep-equipment|保留装备*
-herobrines-origin|Herobrine的起源 (Herobrine's Origin)
+herobrines-origin|Herobrine 的起源 (Herobrine's Origin)
the-abyss|深渊:远古 (The Abyss: Legacy)
sekiro-sense-symbols
lurker|Cold的潜伏者 (Colds: Lurker)
@@ -4576,7 +4576,7 @@ tinkers-planner|匠魂蓝图 (Tinker's Planner)
playing-cards|扑克牌*
rainbow-oak-trees-2|彩虹橡树2*
mapfrontiers|地图边界 (MapFrontiers)
-customizable-elytra|可自定义鞘翅*¨customizable-elytra-fabric|可自定义鞘翅 (Customizable Elytra)
+customizable-elytra@|可自定义鞘翅*¨customizable-elytra-fabric|可自定义鞘翅 (Customizable Elytra)
puzzles-lib@¨puzzles-lib-fabric
unique-enchantments-base|独特的附魔:基础*
ore-stages|矿石阶段*
@@ -4596,7 +4596,7 @@ william-wythers-overhauled-overworld@wwoo¨expanded-ecosphere@
infinite-music
cobbler|可靠的潜影贝工厂 (Shulker's Faithful Factories/Cobbler)
nether-fast-transport-layer
-the-outer-end
+the-outer-end@
hamncheese@
buzzy-drones
morevanillaarmor@|更多原版盔甲 (MoreVanillaArmor)
@@ -4612,11 +4612,11 @@ slotlock@|锁定槽 (SlotLock)
panorama-tweaker@
simple-tomb|简单坟墓*
modern-life@|摩登生活*
-paxi-fabric@paxi¨paxi
+paxi-fabric@paxi¨paxi¨paxi-neoforge
waveycapes@wavey-capes|飘扬披风 (Wavey Capes)
skin-layers-3d@3dskinlayers|3D 皮肤层 (Skin Layers 3D)
-all-the-discs|唱片大全 (All the Discs)
+mc-mods-the-discs|唱片大全 (All the Discs)
cryptic-cosmos
bayou-blues@|长沼蓝调*¨bayou-blues-fabric|长沼蓝调 (Bayou Blues)
hex-lands|六边形地貌*
@@ -4624,18 +4624,18 @@ fixrtm
serene-tweaks
ScalingGuis|界面缩放 (ScalingGUIs)
ide-better-command-block-forge-editor|更好的命令方块 (Better Command Block IDE)¨ide-better-command-block-fabric-editor|更好的命令方块 (Better Command Block IDE)
-@breakfree|自由破坏 (Break Free)
+breakfree@|自由破坏 (Break Free)
tinkers-mechworks-fork
extended-nether-backport
borderless|无边框全屏 (Borderless Window)
lifted-restrictions-structure-block|更好的结构方块 (Better Structure Block)
-entity-model-json|实体模型JSON (Entity Model JSON)
+entity-model-json|实体模型 JSON (Entity Model JSON)
death-coords|死亡坐标显示*
never-enough-currency|货币多多*
never-enough-currency-lite|货币多多:精简版*
create-chunkloading
-name-pain
+name-pain@
wireless-chargers@|无线充电器*
bouncier-beds@|弹力床*¨bouncier-beds-fabric|弹力床 (Bouncier Beds)
hexlands-ii|六边形地貌 2 (HexLands II)
@@ -4652,8 +4652,8 @@ fins-and-tails|鳍和尾巴 (Fins and Tails)
smarter-farmers-farmers-replant@|更聪明的农夫 (Smarter Farmers/Farmers Replant)
peculiars|独特风味*
draggable-resource-packs@draggable-lists|可拖动列表/可拖动资源包 (Draggable Lists/Draggable Resource Packs)
-fastchest|快速箱子渲染 (FastChest) - 已不再更新¨@fastchest|快速箱子渲染 (FastChest)
-yuushya-townscape-fabric@yuushya-townscape|方块小镇 (Yuushya Townscape)
+fastchest|快速箱子渲染 (FastChest) - 已不再更新¨@fastchest|快速箱子渲染 (FastChest) - 在此处更新
+yuushya-townscape@|方块小镇*
architects-palette-fabric@|建筑师的调色板 (Architect's Palette)¨architects-palette@architects-palette#all-versions|建筑师的调色板 (Architect's Palette)
whisperwoods|低语之森*
dimensional-dungeons@|维度地牢*
@@ -4699,7 +4699,7 @@ relics-of-gaming|游戏遗物*
modular-controller|模块化控制器*
Item-Collectors@item-collectors
-gamemodeoverhaul|旧版指令 (GamemodeOverhaul)
+gamemodeoverhaul@|旧版指令 (GamemodeOverhaul)
dash@
minecraft-dungeons-content|地下城内容 (Dungeons Content)
@@ -4710,7 +4710,7 @@ compatchedstorage|紧凑存储修复 (ComPatchedStorage)
iseedragons
psionic-peripherals
malum|灵灾*
-allomancy|镕金术*
+mc-modsomancy|镕金术 (Allomancy)
steamcraft2
boilerplate
meldexuns-crystalic-void
@@ -4891,11 +4891,11 @@ underground-loot-crates|地下战利品箱*
smooth-scrolling-everywhere|平滑滚动*¨smooth-scrolling-everywhere-fabric|平滑滚动 (Smooth Scrolling Everywhere)
sword-blocking@|持剑格挡*
-better-mount-hud@|更好的骑乘HUD*
+better-mount-hud@|更好的骑乘 HUD (Better Mount HUD)
fire-overlay-controller@|火焰叠加层调整*
particle-rain@|粒子雨*
-sodium-reforged|镁 (Magnesium/Sodium Reforged)
+sodium-reforged|镁 (Magnesium / Sodium Reforged)
phosphor-reforged|硫 (Sulfuric/Phosphor Reforged)
hydrogen-reforged|氦 (HeIium)
xl-food-mod-plus|超多食物+ (XL Food Mod+)
@@ -4955,7 +4955,7 @@ enderscape@
goblin-traders-fabric@|哥布林商人Fabric版 (Goblin Traders (Fabric))
lakeside@|湖畔*
chenziqius-originality|CHENZIQIU的创意 (CHENZIQIU's Originality)
-alloy-forgery@
+mc-modsoy-forgery@alloy-forgery
mechanical-tech@|机械科技*
hadesgame|阴间游戏 (HadesGame)
one-block-forge
@@ -4977,7 +4977,7 @@ levelz@
betterend-re-forked|更好的末地Forge重铸版 (BetterEnd Reforked)
mining-gadgets|采矿小工具*¨mining-gadgets-fabric|采矿小工具 (Mining Gadgets)
ponderjs
-majrusz-library
+majrusz-library@
ydms-coppergolem@ydms-copper-golem|YDM的铜傀儡 (YDM's CopperGolem)
chococraft-3
chococraft-plus@
@@ -5007,14 +5007,14 @@ right-click-harvest@|右击收割 (Right-Click-Harvest)
custom-content-packs
cake-chomps@¨cake-chomps-fabric
distant-horizons@distanthorizons
-betterp2p|更好的P2P支持 (Better P2P)
-ob-aquamirae@aquamirae|海灵物语 (Aquamirae Mod)¨aquamirae-fabric|海灵物语 (Aquamirae Mod)
+betterp2p@|更好的P2P支持 (Better P2P)
+ob-aquamirae@aquamirae|海灵物语 (Aquamirae)¨aquamirae-fabric|海灵物语 (Aquamirae)
nuclear-tfc
just-more-cakes@|只是更多的蛋糕! (Just More Cakes!)¨just-more-cakes-fabric|只是更多的蛋糕! (Just More Cakes!)
image-mod
reinforced-barrels@|增强木桶*
spyglass-zoom|望远镜变焦*
-npc-variety-port|NPC变体 (NPC Variety)
+npc-variety-port@npc-variety|NPC变体 (NPC Variety)
just-enough-effects
incorporeal-2-rhododendrite|幻想多媒体2 (Incorporeal 2 + Rhododendrite)
@@ -5022,13 +5022,13 @@ einsteins-library
worldshape
rslargepatterns|精致存储大样板 (Refined Storage Large Patterns)
gendustry-jei-addon
-statement
+statement@
mutant-more@|更多突变生物* - 旧¨new-mutant-more@|更多突变生物 (Mutant More) - 新
just-enough-keg
paleolithic-revolution
better-shields|更好的盾牌*
-yungs-bridges@|YUNG的桥 (YUNG's Bridges)¨yungs-bridges-fabric|YUNG的桥 (YUNG's Bridges)
+yungs-bridges@|YUNG 的桥 (YUNG's Bridges)¨yungs-bridges-fabric|YUNG 的桥 (YUNG's Bridges)¨yungs-bridges-neoforge|YUNG 的桥 (YUNG's Bridges)
project-red-transmission|红石计划:传导 (ProjectRed - Transmission)
day-dream
savage-ender-dragon|更凶猛的末影龙*
@@ -5078,7 +5078,7 @@ enhanced-farming@|增强农业*
lava-clear-view@|熔岩下清晰视野*¨lava-clear-view-fabric|熔岩下清晰视野 (Lava Clear View)
-global-xp
+global-xp@
universal-graves@
more-bows-restrung@|更多弓:重振旗鼓! (More Bows: Restrung!)
@@ -5116,7 +5116,7 @@ budschies-morph-mod@
pswg|帕尔奇的星球大战 (Parzi's Star Wars Mod)¨parzis-star-wars-mod|帕尔奇的星球大战 (Parzi's Star Wars Mod)
aquatic-abyss
slimier-slimes
-wacky-weapons
+stupid-weapon
slime-carnage|史莱姆杀戮*
portal-tags
eden-ring@eden-ring-reforked|伊甸星环*
@@ -5211,7 +5211,7 @@ modular-assembly|模块化组装*
healer@
calcium|钙*
from-the-shadows
-l_ender-s-cataclysm@l_enders-cataclysm(cataclysm)|灾变 (L_Ender 's Cataclysm)
+l_ender-s-cataclysm@l_enders-cataclysm|灾变 (L_Ender 's Cataclysm)
brighter-block-light|亮光 (Brighter)
pick-up-notifier@|拾取提示*¨pick-up-notifier-fabric|拾取提示 (Pick Up Notifier)
@@ -5223,7 +5223,7 @@ login
edible-bugs
farsight¨farsight-fabric
-atlantis|亚特兰蒂斯*
+atlantis@|亚特兰蒂斯*
gaia-dimension
pwem
akisephilas-bosses
@@ -5235,7 +5235,7 @@ vanilla-cookbook@vanillacookbook|原版烹饪书*
edible-nether-wart|可食用下界疣*
plasmo-voice@|Plasmo语音*
armor-sound-tweak|盔甲音效调整*
-hexerei|魔法巫师*
+hexerei@|魔法巫师*
morerefinedstorage
give-me-water-or-give-me-death
lost-and-found
@@ -5293,13 +5293,13 @@ boosted-brightness@|亮度增强*
effective@¨effective-forge
voidtotem|虚空图腾 (Void Totem)¨voidtotem-fabric|虚空图腾 (Void Totem)
-tool-leveling-plus@tool-leveling¨tool-leveling-plus-fabric
+tool-leveling-plus@tool-leveling|工具升级 (Tool Leveling+)¨tool-leveling-plus-fabric|工具升级 (Tool Leveling+)
mythicmetals@|神话金属 (Mythic Metals)
creeper-firework@|烟花苦力怕*
second-chance@second-chance-forge¨second-chance-forge
promenade@
-london-underground|伦敦地铁 (The London Underground)
-dynamiclights-reforged|镁/铷:动态光源 (Embeddium/Rubidium Dynamic Lights)
+london-underground@the-tube|伦敦地铁 (The London Underground)
+dynamiclights-reforged|Embeddium/铷:动态光源 (Embeddium/Rubidium Dynamic Lights)
the-wild-mod@|荒野更新*
tuff-depth|凝灰岩深度*
minefantasy-reforged|我的幻想重铸版 (MineFantasy Reforged)
@@ -5311,9 +5311,9 @@ anointed-items
golden-age-combat|黄金时代的战斗*
magnesium-extras|镁/铷:附属 (Magnesium/Rubidium Extras)
chest-tracker@|箱子追踪*
-advancementinfo@|进度信息展示*
+advancementinfo@|进度信息展示 (AdvancementInfo)
animatica@
-all-dimension-height-increase|全维度建筑高度提升*
+mc-mods-dimension-height-increase|全维度建筑高度提升 (All Dimension Height Increase)
merchant-markers@|商人标记*¨merchant-markers-fabric|商人标记 (Merchant Markers)
loot-bag|战利品袋子*
miner-watcher|矿工监视者*
@@ -5331,7 +5331,7 @@ adventtic
questionably-immersive
long-fall-boots
total-darkness
-true-darkness
+true-darkness@
starlight-x-create
grand-economy
chinacraft2|华夏文明2 (ChinaCraft2)
@@ -5343,12 +5343,12 @@ hardcore-buoyance
gregtech-ce-unofficial@|格雷科技社区版:非官方版 (GregTech CE: Unofficial)
eggtab-fabric|独立刷怪蛋列表 (Egg Tab)¨eggtab-forge|独立刷怪蛋列表 (Egg Tab)
always-a-wither-skull@|必得凋灵骷髅头颅 (Always a Wither Skull)¨always-a-wither-skull-fabric|必得凋灵骷髅头颅 (Always a Wither Skull)
-anvil-restoration-fabric@anvil-restoration|铁砧修复 (Anvil Restoration)¨anvil-restoration|铁砧修复*
+anvil-restoration@|铁砧修复*¨anvil-restoration-fabric|铁砧修复 (Anvil Restoration)
hide-hands-fabric@hide-hands|隐藏主副手 (Hide Hands)¨hide-hands|隐藏主副手*
better-beacon-placement-fabric@better-beacon-placement|更好的信标放置 (Better Beacon Placement)¨better-beacon-placement|更好的信标放置*
dead-totems
-functional-storage|功能性存储*
-the-wild-update|荒野更新1.19 (The Wild Update 1.19)
+functional-storage@|功能性存储*
+the-wild-update|荒野更新 1.19 (The Wild Update 1.19)
archeology@|考古学 (CapsLock Archeology)
trinkets-and-baubles|饰品与小玩意 (Trinkets and Baubles)
@@ -5356,7 +5356,7 @@ trinkets-and-baubles|饰品与小玩意 (Trinkets and Baubles)
rope-ladders|绳梯*
skewers-updated|烤串更新版*
keep-my-soil-tilled-fabric|保持肥沃 (Keep My Soil Tilled)¨keep-my-soil-tilled|保持肥沃*
-double-doors-fabric@double-doors|双开门 (Double Doors)¨double-doors|双开门*
+double-doors@|双开门*¨double-doors-fabric|双开门 (Double Doors)
expanded-armor-enchanting@|盔甲附魔扩展*
expanded-weapon-enchanting@|武器附魔扩展*
expanded-axe-enchanting@|斧附魔扩展*
@@ -5393,12 +5393,12 @@ mekanism-matter|通用机械:物质拓展*
inzhefop-core
-legendary-tooltips@|传说工具提示*¨legendary-tooltips-fabric|传说工具提示 (Legendary Tooltips)
+legendary-tooltips@|传说提示框*¨legendary-tooltips-fabric|传说提示框 (Legendary Tooltips)
myrtrees
tiny-redstone
-icarus-fabric@icarus
+icarus@
the-splash-milk@|喷溅牛奶 (Splash Milk)
fastbench-for-fabric|工作台性能优化Fabric版 (FastBench for Fabric)
mob-buckets-fabric|生物桶 (Mob Buckets)
@@ -5432,7 +5432,7 @@ renamer|代号名称*
the-herobrine-mod-1-7-10
aquatic-armors
immersive-industry|沉浸工业*
-lightmans-currency¨lightmans-currency-fabric
+lightmans-currency@¨lightmans-currency-fabric
hellfire-fireball-launcher|地狱火:火焰弹发射器 (Hellfire: Fireball Launcher)¨hellfire-fireball-launcher-fabric|地狱火:火焰弹发射器 (Hellfire: Fireball Launcher)
guild
endless-deep-space|无尽深空*
@@ -5450,12 +5450,12 @@ collision-damage@
project-74246|毁灭地牢 (Doomlike Dungeons)
dynamic-trees-defiled-lands|动态的树:污秽之地附属 (Dynamic Trees - Defiled Lands)
xaero-map-addition@
-lambdacontrols@|Lambda 的控制优化 (LambdaControls)
+lambdacontrols@|Lambd 的控制优化 (LambdaControls)
ducky-mod
-@craftgr|幻想乡电台 (CraftGR)
+craftgr@|幻想乡电台 (CraftGR)
quartz
-all-the-blocks
-allthemodium
+mc-mods-the-blocks
+mc-modsthemodium
ato
just-enough-effect-descriptions-jeed@|JEI药水效果 (Just Enough Effect Descriptions)
hostile-neural-networks
@@ -5465,7 +5465,7 @@ neon-craft-2-mod|霓虹灯艺2*
architects-dream|建筑师之梦 (Architect's Dream)
ignition-enderbags
correlated@
-
+enderbags
no-mob-spawning-on-trees
rf-lux@
@@ -5486,7 +5486,7 @@ giant-player-boss|巨人玩家Boss*
set-bonus
tntutils
giant-swords|巨剑*
-terrablender@¨terrablender-fabric
+terrablender@¨terrablender-fabric¨terrablender-neoforge
commandhelper|命令助手 (CommandHelper)
bilibili
@@ -5514,7 +5514,7 @@ vitality
featured-servers
oldjavawarning@|旧Java警告 (OldJavaWarning)
mercurius
-all-the-swords
+mc-mods-the-swords
pams-simple-recipes
bow-infinity-fix@|无限附魔修复*
@@ -5543,9 +5543,9 @@ better-compatibility-checker
fastfurnace-minus-replacement
harvest
craftpresence@
-stonecutter-recipe-tags
+stonecutter-recipe-tags@stonecutter_recipe_tags
customnpcsreborn|自定义NPC:重生 (Custom NPCs Reborn)
-nightmare-craft-survival|梦魇工艺:生存 (Nightmare Craft: Survival)
+
brassamberbattletowers
jags
sedna
@@ -5567,7 +5567,7 @@ creatures-and-beasts@|动物和野兽 (Creatures and Beasts)
dead-guys-deep-dark
towers-of-the-wild-reworked|旷野之息高塔:重制 (Towers of the Wild: Reworked)
towers-of-the-wild-reloaded|旷野之塔:重置 (Towers of the Wild: Reloaded)
-bansoko|创可贴 (Bansōkō)
+bansoko|创可贴 (Bansoukou)
inventory-backpack@inventory-backpack-mod
@@ -5587,7 +5587,7 @@ no-null-processors
ma-enchants|Ma 附魔*
bits-and-chisels@
trading-post|交易站*¨trading-post-fabric|交易站 (Trading Post)
-phantasmic¨@nourished-nether|Nourished Nether/Phantasmic/Netherific - 已失效
+phantasmic¨@phantasmic|Nourished Nether/Phantasmic/Netherific - 已失效
furnus
permanent-light-generator@plg|恒久光发电机*¨permanent-light-generator-fabric|恒久光发电机 (Permanent Light Generator)
@@ -5604,7 +5604,7 @@ botany-pots-ore-planting@|植物盆栽矿石种植*
satin-api@
easy-magic@|简易附魔台*
-enlightend@enlightened-end
+enlightend¨@enlightened-end|Enlightend/Enlightened End/Nourished End - 已失效
rubidium@|铷*
cultural-delights@|多元乐事*
@@ -5643,10 +5643,10 @@ blaze-gear|烈焰装备*
@aier|反内能革命 (Anti-internal Energy Revolution)
rhodonite-tools-armour
more-minecarts
-corn-delight@|玉米乐事*¨corn-delight-fabric|玉米乐事 (Corn Delight)
+corn-delight@|玉米乐事*¨corn-delight-fabric@|玉米乐事 (Corn Delight)
-blast-craft|防爆工艺 (Blastcraft)
+blast-craft@blastcraft|防爆工艺 (Blastcraft)
zdgx@|mod自动更新 (zdgx-AutoUpdateMod)
@@ -5659,7 +5659,7 @@ cuboiddroids-support-mod
-litematica-tool|投影工具 (litematica tool)
+litematica-tool|投影工具*
frozen-up|千里冰封*
carpet-tis-addition@
@@ -5719,7 +5719,7 @@ herodotusutils@herodotus-utils
platypuses
hostile-villages|敌对村庄*
throwability|投掷*
-biomeinfo|生物群系信息 (BiomeInfo)¨biomeinfo-fabric|生物群系信息 (BiomeInfo)
+biomeinfo@|生物群系信息 (BiomeInfo)¨biomeinfo-fabric|生物群系信息 (BiomeInfo)
clickable-advancements|可点击的进度 (Clickable advancements)
factory0-resources
epic-knights-armor-and-weapons@epic-knights-shields-armor-and-weapons|史诗骑士:盾牌,盔甲和武器 (Epic Knights: Shields, Armor and Weapons)
@@ -5742,7 +5742,7 @@ oculus@
simple-planes-tfc
mishang-urban-construction@|迷上城建*
@cursed-legacy-api
-phi
+phi@
ae2-utilities|AE2实用设备 (AE2 Utilities)
epic-psi
@@ -5755,7 +5755,7 @@ psio
-copper-pot|铜锅! (Copper Pot!)
+copper-pot@|铜锅! (Copper Pot!)
viarewind
@@ -5775,7 +5775,7 @@ creatures-of-the-snow@creatures-from-the-snow-fabric|雪地里的生物! (Crea
collisions-lib@
wooled-boots@|羊毛靴子*
zawa-evolved|野生动物园:进化 (Zoo and Wild Animals: Evolved)
-bongo
+bongo@
impersonate@
calemi-core@ccore
@@ -5805,9 +5805,9 @@ ladylucs-critters-mod
better-signs
@howmanyitems
+@howmanyitems-fabric
-
-
+@glass-config-api
@translated-legacy
@@ -5853,13 +5853,13 @@ comics-bubbles-chat@
fabric-extended-armor-bars-forked
eating-animation-forge@eating-animation|进食动画 (Eating Animation)¨eating-animation-fabric@eating-animations|进食动画 (Eating Animation)
waterdripsound@¨dripsounds-fabric@
-better-horse-hud|更好的骑马HUD*
+better-horse-hud|更好的骑马 HUD*
thermopolium|汤饮铺*
orderly-fabric-2-0
-entity-texture-features-fabric@entitytexturefeatures
+entity-texture-features-fabric@entitytexturefeatures|实体纹理特性 (Entity Texture Features)
sculk-plus
creeper-confetti-fabric|烟花苦力怕Fabric版*
double-jump-attribute¨@double-jump-attribute|Double Jump Attribute - 已失效
@@ -5876,7 +5876,7 @@ window-title-changer
robins-ruby-mod
-just-needed¨just-needed-fabric
+just-needed@justneeded¨just-needed-fabric
nodami-remake|伤害免疫机制移除重制版 (NoDamIRemake)
had-enough-items|HEI物品管理器*
worldinfo
@@ -5904,7 +5904,7 @@ tinkers-golems-addon
tinkers-addons-fork
reagenchant
-sim-u|模拟城市 (Sim-U)
+sim-u|模拟城市/模拟大都市
thorium@|钍*
creative-one-punch@
@@ -6002,7 +6002,7 @@ mobifier¨mobifier-fabric
art-of-forging-a-tetra-addon|锻造之艺 (Art of Forging)
harder-staged-difficulty
material-changer
-tree-harvester¨tree-harvester-fabric
+tree-harvester@¨tree-harvester-fabric
itemfx
mekanism-ce@mekanism-community-edition|通用机械:社区版 (Mekanism Community Edition)¨mekanism-1-12-2-ce|通用机械:社区版 (Mekanism Community Edition)
@@ -6016,12 +6016,12 @@ too-many-glyphs
create-cafe@|机械动力:咖啡馆*
@worldbordercolor
ic2-rpg|工业RPG (IC2 RPG)
-drop-the-meat@dropthemeat
+drop-the-meat@dropthemeat|肉多多 (Drop the Meat)
better-invisibility|更好的隐身*
tweakerplus@
autorun-fabric@autorun
fpv-drone
-campfire-backport
+campfire-backport@
skip-transitions@
just-load@
cheese-dragon
@@ -6029,7 +6029,7 @@ boatjump@
torched
nyfs-quivers|Nyf的箭袋 (Nyf's Quivers)
-party-parrots¨party-parrots-fabric
+party-parrots@¨party-parrots-fabric
patina-pipeworks|古铜管道*
brewevolution|酿造进化🍺 (Brewevolution 🍺)
devil-fruits|恶魔果实*
@@ -6065,7 +6065,7 @@ croptosis
weeping-angels-mod¨the-lonely-assassins
hardcore-item-stages
game-stages-viewer
-mpm-lotr
+mpm-lotr|更多玩家模型:魔戒兼容 (MPM LOTR)
guard-villagers-fabric@guard-villagers-(fabricquilt)|警卫村民Fabric版 (Guard Villagers (Fabric))
item-highlighter@|物品高亮*¨item-highlighter-fabric|物品高亮 (Item Highlighter)
@@ -6106,7 +6106,7 @@ gregicality-multiblocks@
the-box-trot@
better-biome-blend@|更好的生物群系过渡*
forever-enough-items|FEI物品管理器*
-chess|象棋*
+chess|象棋* - 此已不受支持¨@chinesechess|象棋 (Chess) - >=3.0
immersive-fx
ydms-weapon-master@weaponmaster|YDM的武器大师 (YDM's Weapon Master)
galacticrafttweaker
@@ -6119,7 +6119,7 @@ messmod@
log4j2-jndi-exploit-fix
woodcutter¨woodcutter-forge
origins-classes-forge@|起源:职业非官方Forge版 (Origins: Classes (Forge))
-tool-stats
+tool-stats@
thatched
fumo-mod
basement-origins
@@ -6133,10 +6133,10 @@ just-the-binding-of-isaac-pills
pendant-of-life
the-binding-of-isaac-tears-mod
humbling-bundle@|慈善捆绑包*
-grindstone-sharper-tools-fabric¨grindstone-sharper-tools
-nutritious-milk¨nutritious-milk-fabric
+grindstone-sharper-tools@¨grindstone-sharper-tools-fabric
+nutritious-milk@¨nutritious-milk-fabric|Nutritious Milk - 文件已失效
extract-poison¨extract-poison-fabric
-zombie-villagers-from-spawner-fabric@zombie-villagers-from-spawner¨zombie-villagers-from-spawner
+zombie-villagers-from-spawner@¨zombie-villagers-from-spawner-fabric
vine-climber
healing-soup@¨healing-soup-fabric
idas@|地牢建筑统合 (Integrated Dungeons and Structures)
@@ -6177,12 +6177,12 @@ kitteh6660s-morecraft
angel-ring|天使指环*
debugify@
nomowanderer
-allthecompressed
+mc-modsthecompressed
cave-enhancements
creative-apiary|创造蜂场*
creative-crafter
mcmod-search-reborn|MC百科资料搜索-重生 (MCMOD Search Reborn)
-proxy-server
+proxy-server@
multithreaded-noise
spelling-table-mod|拼写台*
@@ -6191,7 +6191,7 @@ dirt-deco
multiblocked
arcanus@
armor-weight
-all-the-tweaks
+mc-mods-the-tweaks
runelic
alexs-cloud-storage@|云存储 (Cloud Storage)
visuality@|可视性*
@@ -6256,13 +6256,13 @@ carpetclient@
dynamic-trees-vampirism|动态的树:吸血鬼附属 (Dynamic Trees - Vampirism)
transcend|超越*
-connectible-chains@connectible_chains¨connectible-chains-forge
+connectible-chains@connectiblechains¨connectible-chains-forge
-birds-nests-fabric|鸟巢Fabric版 (Birds Nests (Fabric))
+birds-nests-fabric|鸟巢 Fabric 版 (Birds Nests (Fabric))
hot-or-not-tfc
eye-of-dragons
paperdoll@|纸娃娃 (PaperDoll)
-little-logistics
+little-logistics@
show-me-what-you-got@
herdspanic@
extrasounds@
@@ -6279,7 +6279,7 @@ ironagefurniture
minekea-fabric
aeble
trident-mod|三叉戟 (Trident)
-custom-professions|自定义村民职业 (Custom Villager Professions)
+custom-professions@custom-villager-professions|自定义村民职业 (Custom Villager Professions)¨custom-villager-professions-fabric|自定义村民职业 (Custom Villager Professions)
nextspring|化作春泥更护花 (NextSpring)¨nextspring-fabric|化作春泥更护花 (NextSpring)
psionic-utilities
@@ -6297,7 +6297,7 @@ biomes-far-away
better-runtime-resource-pack@brrp|更好的运行时资源包*
ends-delight@|末地乐事 (End's Delight)
natures-starlight
-alloygery@
+mc-modsoygery@alloygery
custom-game-rules
lava-walker@lavawalker
pretty-pipes|更好的管道*
@@ -6327,7 +6327,7 @@ reach-fix
lootjs-forge
chat-sounds@chatsounds
advancement-screenshot@¨advancement-screenshot-fabric
-all-loot-drops@
+mc-mods-loot-drops@all-loot-drops
disc-jockey@
better-taskbar@|更好的任务栏*
storage-network
@@ -6378,7 +6378,7 @@ deep-mob-learning-reforged|深度怪物学习:重铸 (Deep Mob Learning: Refor
zenith@
extended-drawers@
equippable-utilities@utilities
-never-enough-currency-2|货币多多2*¨never-enough-currency-fabric|货币多多2 (Never Enough Currency 2)
+never-enough-currency-2@never-enough-currency-2-(forge)#all-versions|货币多多2*¨never-enough-currency-fabric|货币多多2 (Never Enough Currency 2)
quartz-chests|石英箱子*
frozen-delight|冰封乐事*
@@ -6399,7 +6399,7 @@ creeper-chain-reaction
tiffitlib
sanity
-dynamic-trees-the-aether-legacy|动态的树:天境附属 (Dynamic Trees - The Aether Legacy)
+dynamic-trees-the-aether-legacy@dynamic-trees-aether|动态的树:天境附属 (Dynamic Trees - The Aether Legacy)
dynamic-trees-cuisine|动态的树:料理工艺附属 (Dynamic Trees - Cuisine)
ancient-classes
bigger-stacks@biggerstacks
@@ -6529,7 +6529,7 @@ human-companions
odysseyhud
colorblindness@
aether-addon
-@moonstone|月之石 (MoonStone)¨@moonfabric|月之石 (MoonStone)
+moonstone@|月之石 (MoonStone)¨@moonfabric|月之石 (MoonStone)
server-redirect
city-blocks
@@ -6546,12 +6546,12 @@ wumpleutil
twilight-delight@twilightdelight|暮色乐事*
recruits@villager-recruits
the-true-backrooms
-webstreamer
+webstreamer@
op-items-tab
thaumisc|神秘杂项学*
-treechop@tIdTnzkf
+treechop@
idwtialsimmoedm@
entity-collision-fps-fix@¨entity-collision-fps-fix-fabric
hollowwoods
@@ -6599,7 +6599,7 @@ language-reload@
@beer
sound-categories@
@unsuspicious-stew%22
-@preventer
+preventer@
@wpit
starflight-innovation
powah-rearchitected@powah
@@ -6610,12 +6610,12 @@ better-rocks
horse-combat-controls
libgui
simply-houses@
-yungs-better-desert-temples@|YUNG的沙漠神殿优化 (YUNG's Better Desert Temples)¨yungs-better-desert-temples-fabric|YUNG的沙漠神殿优化 (YUNG's Better Desert Temples)
+yungs-better-desert-temples@|YUNG的沙漠神殿优化 (YUNG's Better Desert Temples)¨yungs-better-desert-temples-fabric|YUNG的沙漠神殿优化 (YUNG's Better Desert Temples)¨yungs-better-desert-temples-neoforge|YUNG的沙漠神殿优化 (YUNG's Better Desert Temples)
modern-dynamics@|现代动力学*
doggo-mod@
tan-huge-trees
@wiangdtbisadtn|草我本来不想这么做的但是我这么做了啊啊啊啊啊啊啊啊啊啊啊啊啊啊 (Wait I Am Not Gonna Do This But I Somehow Accidentally Did This Nooooooooooooooo)
-yungs-better-witch-huts@|YUNG的沼泽小屋优化 (YUNG's Better Witch Huts)¨yungs-better-witch-huts-fabric|YUNG的沼泽小屋优化 (YUNG's Better Witch Huts)
+yungs-better-witch-huts@|YUNG的沼泽小屋优化 (YUNG's Better Witch Huts)¨yungs-better-witch-huts-fabric|YUNG的沼泽小屋优化 (YUNG's Better Witch Huts)¨yungs-better-witch-huts-neoforge|YUNG的沼泽小屋优化 (YUNG's Better Witch Huts)
panorama-creator|全景图创建器*
ui-input-undo-fabric@¨ui-input-undo-forge@
paimeng|应急食物 (PaiMeng)
@@ -6677,7 +6677,7 @@ hidden-names|隐藏名称*
doph@|远程命中提示 (Ding On Projectile Hit)
keybinds@
hat-list@hatlist
-@nmuk
+nmuk@
raven-brews-core
raven-coffee|Raven咖啡*
cqc
@@ -6707,7 +6707,7 @@ no-telemetry@
create-chromatic-return|机械动力:异彩化合物 (Create: Chromatic Return)
coffee-spawner
-timber-mod
+timber-mod@timber-mod-by-mycf
sophisticated-storage|精妙存储*
advanced-lootable-weapons
what-the-bucket
@@ -6812,7 +6812,7 @@ nether-tears|下界遗泪 (NetherTears)
africraft
-applied-botanics-addon|应用能源:植物魔法附属*
+applied-botanics-addon@applied-botanics|应用能源:植物魔法附属*
overloaded-armor-bar-updated
delightful@
wizardry-tales
@@ -6820,7 +6820,7 @@ wizardry-tales
tamedrespawn|驯兽重生 (TamedRespawn)
dumplings-delight@|饺子乐事*
-thermal_extra
+thermal_extra@thermal-extra
nether-sky-block@|下界空岛*
arte-magicum
@@ -6836,7 +6836,7 @@ custom-damage-particles@|自定义伤害粒子*
@aei|AEI物品管理器 (Always Enough Items)
cyan-warrior-swords-mod@
plant-in-a-jar@
-solid-mobs
+solid-mobs@solid_mobs
naturalist@|自然主义*
c3h6n6o6@|环三亚甲基三硝胺 (Cyclotrimethylenetrinitramine)
syncmatica@|共享原理图*
@@ -6878,7 +6878,7 @@ create-chromaticreturn
powertool@|电动工具 (PowerTool)
keymap@|键盘映射*
actually-useful-stonecutter
-itemphysic-lite-fabric
+itemphysic-lite-fabric|物品物理掉落:轻量版 - Fabric (ItemPhysic Lite - Fabric)
forgotten-treasures
player-health-indicators@playerhealthindicators
displaycase@|陈列柜 (Display Case)
@@ -6923,7 +6923,7 @@ starry-skies
flesh2leather-forge¨flesh2leather-fabric
fall-damage-indicator
aww-man-achievement-mod
-fire-extinguisher@
+fire-extinguisher@|灭火器*
farmers-knives@
sullys-mod@sullysmod
magicaldecorations
@@ -6936,7 +6936,7 @@ warden-loot-forge¨warden-loot
@vmwcr|维克的现代战争补充合成表 (Crafting Recipes of Vic's Modern Warfare Mod)
-optifine-checker|高清修复检测 (OptiFine Checker)
+optifine-checker@|高清修复检测 (OptiFine Checker)
paintings
builtin-servers@
extractinator@|提炼机*
@@ -6963,7 +6963,7 @@ parrying
back-in-slime-slime-blocks-for-1-7
create-alloyed|机械动力:合金 (Create: Alloyed)
-verdure|郁郁葱葱*
+verdure@|郁郁葱葱*
the-ori-mod
@@ -6982,7 +6982,7 @@ medieval-origins
elytra-chestplate-swapper
-
+the-ends-flora
apollos-additional-structures
chimes
@@ -7023,10 +7023,10 @@ player-tabs
cie
easy-mob-farm@
material-elements
-raised-clouds
+raised-clouds@
music-triggers@
sneaky-screens
-inmis¨inmis-forge
+inmis@¨inmis-forge
rechiseled@
@@ -7041,7 +7041,7 @@ butchers-delight@|屠夫乐事 (Butcher's Delight)
large-meals-an-add-on-for-farmers-delight
explorers-delight@
the-irregular-chef
-compat-o-plenty
+compat-o-plenty@compatoplenty
snow-pig@snowpig|雪猪*¨snow-pig-fabric@snowpig-fabric|雪猪 (Snow Pig)
wandering-collector@
@@ -7056,11 +7056,11 @@ crafting-on-a-stick
endlessids@
@cpm-fabric|压缩空间 Fabric (Compact Machines - Fabric)
-cycle-paintings¨cycle-paintings-fabric
+cycle-paintings@¨cycle-paintings-fabric
fire-spread-tweaks¨fire-spread-tweaks-fabric
anger-management
-easy-elytra-takeoff¨easy-elytra-takeoff-fabric
+easy-elytra-takeoff@¨easy-elytra-takeoff-fabric
stack-refill¨stack-refill-fabric
light-meals@|轻食物语*
lost-and-fished@lost-fished|失而钓得 (Lost and Fished)
@@ -7117,7 +7117,7 @@ goodall
freecam-by-zergatul
macaws-bridges-oh-the-biomes-youll-go@|Macaw的桥梁:你将去的生物群系附属 (Macaw's Bridges - Oh The Biomes You'll Go)
-macaws-fences-oh-the-biomes-youll-go|Macaw的栅栏与墙:你将去的生物群系附属 (Macaw's Fences - Oh The Biomes You'll Go)
+macaws-fences-oh-the-biomes-youll-go@|Macaw的栅栏与墙:你将去的生物群系附属 (Macaw's Fences - Oh The Biomes You'll Go)
alternate-current@
no-unused-chunks@
no-fade@
@@ -7142,9 +7142,9 @@ auto-reconnect
text-damage-indicators
recall
monster-coin
-dotcoin-mod
+dotcoin-mod@dot-coin-mod¨dot-coin-mod-fabric
super-potato|超级土豆*
-custom-fog
+custom-fog@
oc-xnet-driver
@@ -7246,16 +7246,16 @@ ftb-quests-localization-keys
unlit-realistic-torch-remake|真实火把:重置 (Realistic Torch Remake)
chunk-saving-fix|区块保存修复*
fullscreeno@
-
+@xibao-plus-plus|喜报++ (Xibao Plus Plus)
piglin-proliferation@
the-binding-of-isaac-style-consumables
guns-rpg
-configuration
+configuration@
natural-decoration
spice-of-fabric@
-better-climbing@
+better-climbing@|更好的攀爬*
dog-yeeter
mc122477fix@
armors-hud-revived-liteloader-only
@@ -7308,8 +7308,8 @@ mrp-library
bypass-anvil-restriction
no-early-loading-progress
-block-runner-forge¨block-runner
-quick-paths¨quick-paths-fabric
+block-runner-forge@block-runner¨block-runner
+quick-paths@¨quick-paths-fabric
solar-energy
restored-earth
@@ -7322,7 +7322,7 @@ exlines-snorkel-mod@snorkel
two-players-one-horse
headshot-forge
left-hanging
-
+stars_carrier|星光的载具
aetherworks|天华之作 (AetherWorks)
slice-and-dice@
@@ -7345,7 +7345,7 @@ unusual-end@unusual_end|不同寻常的末地*
solar-flux|日光通量*
custom-background-color@cbc|自定义背景颜色*
-simple-shulker-preview@
+simple-shulker-preview|Simple Shulker Preview - 已弃用¨@simple-shulker-preview
bygone-nether¨bygone-nether-fabric
@clickopener
kokoalinux-backport
@@ -7366,7 +7366,7 @@ broken-discs
forgedfabric@
create-extended-flywheels@extended-flywheels|机械动力:更多飞轮 (Create: Extended Flywheels)¨create-extended-flywheels-fabric|机械动力:更多飞轮 (Create: Extended Flywheels)
piggy-bank
-deeperdarker@
+deeperdarker@|幽邃黑暗 (Deeper And Darker)
remote-gui-opener-forge
@@ -7428,7 +7428,7 @@ custom-window-title@
crated-foods-farmers-delight
damage-tilt
-upgraded-core@
+upgraded-core¨@upgraded-core|Upgraded Core - 不全
upgraded-netherite-ultimerite@|下界合金增强:终极 (Upgraded Netherite : Ultimerite)
upgraded-netherite-items@|下界合金增强:物品 (Upgraded Netherite : Items)
upgraded-netherite-creativerite|下界合金增强:创造 (Upgraded Netherite : Creativerite)
@@ -7491,7 +7491,7 @@ auudio-forge@auudio¨auudio-fabric
easy-shulker-boxes@
qu-enchantments@
-ironchests
+ironchests@
piercing-paxels@piercingpaxels
icy-incitement@
visible-librarian-trades
@@ -7511,11 +7511,11 @@ itank
snowy-spirit@
no-tutorial-toasts
experience-ores
-anvil-player-heads-fabric
+anvil-player-heads-fabric@anvil-player-heads
artisan-integrations
seemyname
biomes-o-plenty-tools
-bedrockcraft
+bedrockcraft@
better-mobgriefing-gamerule
frozen-fiend
@@ -7556,7 +7556,7 @@ instant-blocks@¨instant-blocks-fabric
better-sprinting@|更好的疾跑*
rpglevels
snow-under-trees@
-elytra-physics
+elytra-physics@
scout@
zenstages
@@ -7585,7 +7585,7 @@ serene-seasons-harvestcraft2-compat
goat
simple-autofish
-@thinkbeforedrop|丢弃物品保护 (Think Before Drop)
+think-before-drop@thinkbeforedrop|丢弃物品保护*
omo
mushroom-additions
@@ -7608,7 +7608,7 @@ stop-hiding
simple-world-timer
recursive-resources@recursiveresources
inventory-actions
-
+lavafishing@|岩浆钓鱼 (Lava Fishing)
haunted-harvest@
dungeonsenhanced
create-crystal-clear@|机械动力:晶莹剔透 (Create: Crystal Clear)
@@ -7714,7 +7714,7 @@ libipn@
hulsealib
blues-dynamic-lights
gtc-expansion
-nether-depths-upgrade
+nether-depths-upgrade@|炽海生机*
cloud-factory
disc-holders-dj
@econ
@@ -7737,7 +7737,7 @@ simply-swords@|简易刀剑*
kuayue@|跨越 (KuaYue)
summoningrituals|召唤仪式 (Summoning Rituals)
-no-sleep-forge¨no-sleep
+no-rest
you-died@|你死了*
hotbarcycle@
hungry-in-peaceful-mode|无中生饥*
@@ -7771,7 +7771,7 @@ mysteriumlib@
@inrealtime
furnace-recycle@¨furnace-recycle-fabric
-wild-lands
+wild-lands@
noenchanting
gregtech-experimental@
@@ -7823,7 +7823,7 @@ gregicality-tjfork
@flagslib
create-mechanical-extruder@
no-debug-5-you
-packagedavaritia|封包无尽贪婪 (PackagedAvaritia)
+packagedavaritia@|封包无尽贪婪 (PackagedAvaritia)
pillar
resound
mob-plaques@
@@ -7855,7 +7855,7 @@ gregtech-sieves|格雷矿石筛子 (GregTech Sieves)
dynamic-trees-gregtech-ceu-rubber-tree|动态的树:格雷科技社区版:非官方版附属 (Dynamic Trees - GregTech CEu)
fertility
-tcintegrations
+tcintegrations@
underground-villages
spook
broglis-owls
@@ -7890,7 +7890,7 @@ curious-lands
cpmsvcc@|自定义玩家模型的简单的语音聊天兼容 (Customizable Player Models Simple Voice Chat compat)
pettable@
create-enchantment-industry@|机械动力:附魔工业*¨create-enchantment-industry-fabric@|机械动力:附魔工业 (Create Enchantment Industry)
-enchanted-witchcraft
+enchanted-witchcraft@
wyml
bunch-o-bugs
@@ -7901,7 +7901,7 @@ your-items-are-safe@¨your-items-are-safe-fabric
techemistry
the-missing-villages
continents@
-yungs-better-ocean-monuments@|YUNG的海底神殿优化 (YUNG's Better Ocean Monuments)¨yungs-better-ocean-monuments-fabric|YUNG的海底神殿优化 (YUNG's Better Ocean Monuments)
+yungs-better-ocean-monuments@|YUNG的海底神殿优化 (YUNG's Better Ocean Monuments)¨yungs-better-ocean-monuments-fabric|YUNG的海底神殿优化 (YUNG's Better Ocean Monuments)¨yungs-better-ocean-monuments-neoforge|YUNG的海底神殿优化 (YUNG's Better Ocean Monuments)
echoing-depths
advanced-finders
@@ -7983,7 +7983,7 @@ creative-fireworks
invertedbed
time-arrow
catch-me-if-you-can-cmiyc
-allis-one-way-glass|Alli的单向玻璃 (Alli's One Way Glass)
+mc-modsis-one-way-glass|Alli的单向玻璃 (Alli's One Way Glass)
sanguis
ender-trigon
litlaunch
@@ -7996,7 +7996,7 @@ teams-stages
kiwi-boi
rubidium-toolkit@|铷 · 工具箱*
advanced-combat|高级战斗装备*
-advanced-combat-revitalized|高级战斗装备重置 (Advanced Combat (Revitalized))
+advanced-combat-revitalized@|高级战斗装备重置 (Advanced Combat (Revitalized))
totemic-overhaul
battlecorrection|战斗修正 (BattleCorrection)
@@ -8016,7 +8016,7 @@ survival-light-blocks
garden-stuff|园林组合*
forgottenrecipes
corgilib@
-moms-love|母爱 (Mom's Love)
+moms-love@|母爱 (Mom's Love)
food-effect-tooltips@foodeffecttooltips|食物效果显示*
@resounding
hbm-fixes
@@ -8059,7 +8059,7 @@ packet-size-doubler
arachnophobia-mode-for-minecraft@arachnophobia-mode
villagerconfig@|村民配置 (VillagerConfig)
jasm
-paginated-advancements@paginatedadvancements|分页进度*
+paginated-advancements@paginatedadvancements|分页进度 (Paginated Advancements & Custom Frames)
@backport-gamerules
structures-compass
swiss-cheese
@@ -8150,7 +8150,7 @@ rgb-chat
diamond-caliber
@emi_farmersdelight
-world-stripper
+world-stripper@
dayz-remastered|DayZ 重制版 (DayZ Remastered)
visuality-reforged@visuality-forge|可视性:重铸 (Visuality: Reforged)
no-night-vision-flickering@
@@ -8179,7 +8179,7 @@ xp-obelisk|经验方尖碑 (XP Obelisk)
enhanced-searchability@|搜索增强*
compact-ui@
lets-do-wine@lets-do-vinery|葡园酒香 (Let's do Wine / Vinery)
-wealthyandgrowth
+wealthyandgrowth@
subtitle-highlight@|字幕高亮*
clockhud@clock-hud
@@ -8227,7 +8227,7 @@ better-game-menu@
seasonhud@¨seasonhud-fabric@
stack-to-nearby-chests@|堆叠到附近的箱子 (Stack to Nearby Chests)
gmod-title-screen@
-create-steam-n-rails@|机械动力:汽鸣铁道 (Create: Steam 'n Rails)
+create-steam-n-rails@|机械动力:汽鸣铁道 (Create: Steam 'n' Rails)
neutron
applied-cooking|应用厨房*
@litematica-printer|投影打印机 (Litematica Printer)
@@ -8265,7 +8265,7 @@ last-days-of-humanity-tweaks
space-bosstools-giselle-addon
@ser|刷怪蛋配方 (Spawn Eggs Recipes)
mined-rider-kuuga
-inventory-essentials¨inventory-essentials-fabric
+inventory-essentials@¨inventory-essentials-fabric
astral-additions|星辉附加*
simple-copper-pipes@¨simple-copper-pipes-forge
advanced-nbt-tooltips@|高级NBT提示工具 (Advanced NBT Tooltips)
@@ -8329,7 +8329,7 @@ fancy-dyes@
@extra-mod-integrations
mod-settings@
-@dont-dissapear
+dont-disappear-on-me@dont-dissapear
fastquit@
violeta-cannons
war-of-valor
@@ -8340,7 +8340,7 @@ epic-paladins
brazier@|生灵火盆*
stackcalc-revived@
with-thursday-delight|乐在星期四*
-@osmium|锇 (Osmium)
+osmiummod@osmium|锇 (Osmium)
@command-gui-buttons
wagyourminimap@
chunks-fade-in@|区块淡入动画 (Chunks fade in)
@@ -8352,7 +8352,7 @@ masonry-blocks
mssql-jdbc
packages@|自定义包裹*
giant-spawn@¨giant-spawn-fabric
-@mtr-nte|纸板箱的交通扩展 (Nemo's Transit Expansion)
+@mtr-nte|蓝星社交通扩展 (Nemo's Transit Expansion)
serene-shrubbery
gardens-of-the-dead@
pirate-hats
@@ -8362,7 +8362,7 @@ clay-no-more-balanced|黏土不再制衡*
blossom@
whipdashing@
potiontimestacker-forge@timestacker
-breezy
+breezy@
heart-balance
throwabletorch-fabric@throwabletorch¨throwabletorch
potion-descriptions¨potion-descriptions-fabric
@@ -8375,7 +8375,7 @@ biomes-in-jars-forge@biomes-in-jars|群系罐子 (Biomes in Jars)¨biomes-in-jar
craftable-potion-combinations@craftablepotioncombinations
polylib
@creeper-fire-charge-fix|Creeper火焰弹修复 (Creeper Fire Charge Fix)
-@tags-binder
+tags-binder@
fastcaps
throwable-fluids
time-in-a-bottle@|时间之瓶 Fabric 版 (Time in a Bottle (Fabric))
@@ -8404,7 +8404,7 @@ potato-cooking
clienttime
mcpitanlibarch@
-manure-fabric@manure|粪便 (Manure)¨manure|粪便*
+manure@|粪便*¨manure-fabric|粪便 (Manure)
well@
enderling-invaders@
@@ -8492,7 +8492,7 @@ create-mounted-storages|机械动力:更多存储挂载 (Create: Mounted Stora
minecells@|我的细胞 (Mine Cells - Dead Cells Mod)
@heatwaves|热浪 (Heatwaves)
steves-mini-pouch
-infinite-abyss
+infinite-abyss@
@ktice
creator-overlays@creatoroverlays
maplecraft
@@ -8542,7 +8542,7 @@ forgebrainlib
render-360
async-locator@
-minemention|提及 (MineMention)
+minemention@|提及 (MineMention)
umapyoi@|马儿蹦跳*¨@umapyoi-fabric|马儿蹦跳 (Umapyoi)
origins-full-moon|起源:满月 (Origins: Full Moon)
codechickenlib-unofficial@
@@ -8574,7 +8574,7 @@ tales-of-villagers-the-infiltrators|村民之书:渗透者 (Tales of Villagers
@morecullingextra
carpet-fixes@
er-core|ER 核心 (ER Core)
-rings-of-ascension¨fabric-rings-of-ascension
+rings-of-ascension@¨fabric-rings-of-ascension
@@ -8613,14 +8613,14 @@ news-pillagers
rangers-haven
heyberryshutup
destroy-on-death
-yes-steve-model@|是,史蒂夫模型*
+@yes-steve-model|是,史蒂夫模型 (Yes Steve Model)
macaws-roofs-oh-the-biomes-youll-go|Macaw的屋顶:你将去的生物群系附属 (Macaw's Roofs - Oh The Biomes You'll Go)
macaws-roofs-biomes-o-plenty|Macaw的屋顶:超多生物群系附属 (Macaw's Roofs - Biomes O' Plenty)
configured-feature-saplings@
coyote-time@
-macaws-bridges-modding-legacy|Macaw的桥梁:Modding Legacy 附属 (Macaw's Bridges - Modding Legacy)
-macaws-bridges-aurora|Macaw的桥梁:Aurora 附属 (Macaw's Bridges - Aurora)
+macaws-bridges-modding-legacy|Macaw 的桥梁:Modding Legacy 附属 (Macaw's Bridges - Modding Legacy)
+macaws-bridges-aurora@|Macaw的桥梁:Aurora 附属 (Macaw's Bridges - Aurora)
betterlands
koremods@
heart-of-ender
@@ -8641,7 +8641,7 @@ ost-overhaul@
chunk-by-chunk@chunkbychunk
beyond-planets-core|飞越群星:核心 (Planeteer - Core)
webdisplays@|内置网页浏览器 (WebDisplays)
-mcef-forge@mcef|Minecraft Chromium嵌入式框架 (MCEF [Forge])
+mcef@|Minecraft Chromium 嵌入式框架 (Minecraft Chromium Embedded Framework)
@@ -8667,7 +8667,7 @@ well-rested@
raw-input-1-12-2@raw-input
spider-pig
jingames-hair-c@hair-c
-map-tooltip
+map-tooltip@
planetoid
golem-tweaks
yummy-foods
@@ -8699,7 +8699,7 @@ weapon-master@|武器大师*
your-ideas|你的想法*
vanity-ancient-tool-variants
motion-capture-mod-mocap|动作捕捉 (Motion Capture)
-wormhole-portals|虫洞 (Wormhole)
+wormhole-portals@wormhole|虫洞 (Wormhole)
dragon-magic-and-relics@|神龙魔法与遗物*
yummy-foods-forked
content-creator
@@ -8750,7 +8750,7 @@ thaumic-travelers-dream
aetherium-ashen-armor
smoothmenu|平滑菜单 (Smooth Menu)
@cabricality-mod
-unusual-fish|独特鱼类*
+unusual-fish@unusual-fish-mod|独特鱼类 (Unusual Fish Mod)
obscure-tooltips
@@ -8777,7 +8777,7 @@ containersearcher@csearcher
screencapper@
valkyrien-skies-world
-lucky-tnt-lib
+lucky-tnt-lib@
waffles-placeable-foods@
otg-the-void
otg-flatlands
@@ -8805,7 +8805,7 @@ minespaceex
gregious-maximus
shut-up-model-loader
cultural-delights-fabric@|多元乐事(Fabric版) (Cultural Delights [Fabric])
-collectors-reap
+collectors-reap@
bones-and-swords
vanity-shedds-mystical-toolsets-pack
emc-builders-wand
@@ -8815,12 +8815,12 @@ hunger-in-peace
lexicon@¨lexicon-fabric
scaffolding-drops-nearby@¨scaffolding-drops-nearby-fabric
-@fuel-info
+fuel-info@
glacier-ice
gtnhmixins@
dawn-to-dusk
open-tower-defence@|开放式塔防*
-mtr-station-decoration@station-decoration
+mtr-station-decoration@station-decoration|MTR车站装饰 (MTR Station Decoration)
perviaminvenire
silverbirch@silver-birch
@@ -8909,7 +8909,7 @@ spell-power@
morecrashinfo|更多崩溃报告信息 (MoreCrashInfo)
epicfight-saopack@epicacg|史诗战斗:ACG附属包 (EpicFight ACG AddonPack)
-screenshot-viewer|截图查看器*
+screenshot-viewer@|截图查看器*
gml
@futurepack-additions|飞向未来附加 (Futurepack Additions)
bee-fix|蜜蜂修复*
@@ -8928,7 +8928,7 @@ minegooseduck
floating-islands
@qwq-library
-scorched-guns
+scorched-guns@scorched-guns-2
fred-qol@fred
mekanism-ce-unofficial|通用机械社区版:非官方 (Mekanism CE Unofficial)
@@ -8997,14 +8997,14 @@ dialog|对话框*
fix-selected-item-text
dregora-o-plenty
-integrated-api
+integrated-api@
the-betweenlands-eternal-melodies|交错次元:永恒旋律 (The Betweenlands: Eternal Melodies)
frozen-apocalypse|冰封启示录*
-whymap
+whymap@
craftify@
overgrown-cities-fabric
-night-config-fixes
+night-config-fixes@
standardconfigs
armor-adjustment|盔甲调整*
enchanting-max_level@enchanting.max_level
@@ -9066,7 +9066,7 @@ graphutil@
comfy-sky@|舒适空岛*
entropy@
ngv-forge¨ngv-fabric
-world-of-wonder
+world-of-wonder@
full-brightness-toggle@
@your-ideas|你的想法 (Your Ideas)
@@ -9104,7 +9104,7 @@ lwjgl3ify
creates-delight@|机械动力乐事 (Create's Delight)
-mo-villager|更多村民 (Mo' Villager)
+mo-villager@mo-villagers|更多村民 (Mo' Villager)
logunspam
@@ -9134,7 +9134,7 @@ betweencards
-@google-chat
+google-chat@
@resclone
tame-them-all
@@ -9170,7 +9170,7 @@ why-does-my-food-taste-like-that
iron-generators
elytra-swapper-forge|鞘翅切换 (Elytra Swapper)
ftb-team-islands-forge
-nightmare-craft-memeshrooms|梦魇工艺:蘑菇 (Nightmare Craft: MEMESHROOMS)
+
market-crates|集市板条箱*
industrial-renewal-port|工业复兴移植版*
tfcm|群峦合金非官方版 (TFC Metallum U)
@@ -9187,7 +9187,7 @@ create-compact-exp|机械动力:压缩经验*
heat-and-processing
skytheorylib
-ad-astra-giselle-addon
+ad-astra-giselle-addon@
shift-scroll-fix
gim|原神农业 (Genshin Impact Cropper)
oxygen-daily-rewards
@@ -9210,13 +9210,13 @@ create-mechanical-spawner@|机械动力:动力刷怪笼*
amethyst-core@
fzzy-core@
-tnt-breaks-bedrock
-from-the-north
+tnt-breaks-bedrock@
+from-the-north@
spruce-willis-the-xmas-tree@
sweet-potato-core-spc|地瓜核心 (Sweet Potato Core)
merge-enchantments
turkey|火鸡*
-nightmare-craft-legendary-gear|梦魇工艺:传奇装备 (Nightmare Craft: Legendary Gear)
+
snowy-weaponry@
dungeon-mobs-reborn
quickteleports
@@ -9231,7 +9231,7 @@ fat-chicken
snowmancy@
@roadchina|道路中国 (Road China)
-nightmare-craft-decorations|梦魇工艺:装饰品 (Nightmare Craft: Decorations)
+
@immersive-snow
functional_tfc
@@ -9255,7 +9255,7 @@ aa-farmer-compat
better-crates
-nightmare-craft-auto-factory
+
vanillaicecreamfix@
actually-unbreaking-forge@actually-unbreaking¨actually-unbreaking-fabric
handcrafted@|精巧手艺*
@@ -9269,7 +9269,7 @@ lost-cities-potato-edition|失落的城市:土豆版 (Lost Cities: Potato Edit
endless-noend
matmos-2
tfc-item-barrels
-nightmare-craft-super-foods
+
villagersplus-forge¨villagersplus-fabric
data-criteria
japanese-emoji-commands
@@ -9279,14 +9279,14 @@ voxel-latest
the-printer@
flying-cullers@
-timeless-power
+timeless-power@
create-deco-fabric-fixed
calibrated
frozen-memories
-atlantis-api@
+atlantis-api¨@atlantis-api|Atlantis API - 已失效
nutritional-balance
profession-lock
-nightmare-craft-mobs
+
spectrum-jetpacks@
difficult-caves
@@ -9303,20 +9303,20 @@ mysterious-biomes
head-in-the-clouds@
fdmc
rpg-style-more-weapons
-nightmare-craft-guns-explosives
+
easy-experience
full-turtle-armor@
-tokusatsu-hero-completion-plan|特摄英雄补完计划*
+tokusatsu-hero-completion-plan@tokusatsu-hero-instrumentality-project|特摄英雄补完计划 (Tokusatsu Hero Instrumentality Project)
spyglass-astronomy@
mchalo@
-darkmenu-darkrpg-legacy-menu
-nightmare-craft-game-engine
+darkmenu-darkrpg-legacy-menu@darkrpg-menu
+
rl-artifacts|奇异饰品-RLCraft版 (RLArtifacts)
azurelib@
harder-monster-boats-finer-boat-control
@@ -9381,7 +9381,7 @@ bubbles@pop
nan-health-fixer@|假死修复:土豆版 (Potato NaN Health Fix)
@voxelmap-updated
blood-and-stuff@
-yungs-better-nether-fortresses@|YUNG的下界要塞优化 (YUNG's Better Nether Fortresses)¨yungs-better-nether-fortresses-fabric|YUNG的下界要塞优化 (YUNG's Better Nether Fortresses)
+yungs-better-nether-fortresses@|YUNG的下界要塞优化 (YUNG's Better Nether Fortresses)¨yungs-better-nether-fortresses-fabric|YUNG的下界要塞优化 (YUNG's Better Nether Fortresses)¨yungs-better-nether-fortresses-neoforge|YUNG的下界要塞优化 (YUNG's Better Nether Fortresses)
squidless
enders-delight|末影乐事 (Ender's Delight)
@@ -9389,7 +9389,7 @@ decostorage
mahogany
aspen
unmending-potato-edition|经验不修补:土豆版*
-allens-rocket-launcher-arl|简易火箭筒 (Allen's Rocket Launcher)
+mc-modsens-rocket-launcher-arl|简易火箭筒 (Allen's Rocket Launcher)
@item-tributes
assorted-discoveries
not-so-shrimple-forge
@@ -9423,12 +9423,12 @@ gliders@
@no-teleport-cooldown
riding-partners@|双人骑行*
rpgskillable
-extra-discs
+extra-discs@
propertyerizer
waxable-coral@|涂蜡珊瑚*
@fireframe|火焰框架 (FireFrame)
goated@
-morebread
+morebread@
@@ -9488,7 +9488,7 @@ villager-brute
exspiravit-magicae
equiped
limited-chunkloading
-custom-villager-trades-forge|自定义村民交易 (Custom Villager Trades)
+custom-villager-trades-forge@custom-villager-trades|自定义村民交易 (Custom Villager Trades)¨custom-villager-trades-fabric|自定义村民交易 (Custom Villager Trades)
dungeons-more-mod
ancient-trees
extraskills
@@ -9527,7 +9527,7 @@ steamagerevolution|蒸汽时代革命 (SteamAgeRevolution)
brewcraft
zombie-awareness-freeze-fix|僵尸意识冻结修复*
integrated-stronghold@
-grass-overhaul
+grass-overhaul@
@purpurclient
alkimicraft-part-i-project-oasis
@@ -9539,7 +9539,7 @@ vending-block-revived|自动售货机:重生*
assortment
opotato|哦,土豆!*
-contingameime@|游戏内输入法续更版/游戏内输入法Forge重置版 (ContingameIME/IngameIME-Forge/IngameIME-Forged)
+contingameime@|游戏内输入法续更版 / 游戏内输入法 Forge 重置版 (ContingameIME / IngameIME-Forge / IngameIME-Forged)
ccastroadds
aerial-hell@
swashbucklers
@@ -9625,8 +9625,8 @@ delightful-mining
trimmable-tools
@tablesaw|锯木台 (Tablesaw)
-@glowglass
-all-the-fan-made-discs@
+glowglass@
+mc-mods-the-fan-made-discs@all-the-fan-made-discs
from-the-fog
more-ladders@
reblured@
@@ -9662,7 +9662,7 @@ smitheesfoundry@
beach-slimes
rideable-ravagers@|可骑乘的劫掠兽*
-splatcraft@splatcraft-forge|斯普拉遁*
+splatcraft@|斯普拉遁*
beneath-the-snow
sea-creeps
skills-v|技能:香草 (Skills: Vanilla)
@@ -9676,7 +9676,7 @@ alternative-world-save-location@
skills-firearms|技能:枪械 (Skills: Firearms)
tx-loader@
Reacharound@reacharound
-variety-aquatic¨@variety-aquatic|Variety Aquatic - 已失效
+variety-aquatic|Variety Aquatic - 已被续作替代¨@variety-aquatic|Variety Aquatic - 已失效
blocks-booster@
tfc-cast-iron-grill@|群峦铸铁烤架 (TFC Cast Iron Grill)
@@ -9716,7 +9716,7 @@ simple-conveyors
itemupgrader-core
itemupgrader
screenfx@
-dense-ores-abundant
+dense-ores-abundant@dense-ores
tinkers-thinking@|匠心独运 (Tinkers' Thinking)
simple-musket@
cash-ores@
@@ -9748,14 +9748,14 @@ turned-changed-extension
immediatelyfast-reforged@
magic-mirror
magic-mirror-fabric@magic-mirror
-chassis
+chassis@
fast-doll@fastdoll
better-lily-pads@|更好的睡莲*
mo-zombies-wave
almost-all-the-ores
@Geyser
-supplementaries-squared
+supplementaries-squared@
changed-addon-plus
functional-armor-trim
@@ -9799,7 +9799,7 @@ hexal@|咒法拓展*
create-encased@
@treeplacer
-death-knell
+death-knell@
moreiotas@
numismatic-overhaul@¨numismatic-overhaul-reforged
@hexbound|咒法组构学 (Hexbound)
@@ -9817,11 +9817,11 @@ click-for-hot-chicks@
vanity-molten-pack
vanity-spartan-pack
woods-and-mires@
-@suggestion-tweaker
+suggestion-tweaker@
Additional-Redstone@additional-redstone
heartstone@
-dyed
-wireless-redstone-re
+dyed@
+wireless-redstone@wirelessredstone
vanity-steel-pack
vanity-viking
@@ -9844,8 +9844,8 @@ chatimg|图片聊天 (chatImg)
throwable-explosives
@skillmmo
archeon@
-chat-toggle@
-enchancement
+chattoggle@
+enchancement@
useful-spyglass@
@@ -9876,19 +9876,19 @@ l2weaponry@|莱特兰-武器 (L2 Weaponry)
zoom-o-matic@
@broken-tool
@fishing-ruler
-@command-relay
+command-relay@
beasts-bosses
the-one-probe-community-edition|检测器-社区版*
-packageddraconic|封包龙之进化 (PackagedDraconic)
+packageddraconic@|封包龙之进化 (PackagedDraconic)
imitationcore
big-sip@
floating
@blast-travel
skygrid@
disable-new-world-creation-screen-forge@disable-new-create-world-menu-forge¨disable-new-world-creation-screen-fabric@disable-new-create-world-menu-fabric
-packagedmekemicals|封包通用机械 (PackagedMekemicals)
-packagedastral|封包星辉魔法 (PackagedAstral)
+packagedmekemicals@|封包通用机械 (PackagedMekemicals)
+packagedastral@|封包星辉魔法 (PackagedAstral)
mekanism-moresolarpanels@|通用机械-更多太阳能板 (Mekanism-MoreSolarPanels)
paperandquill
@@ -9898,7 +9898,7 @@ universal-bone-meal-forge@universal-bone-meal|通用骨粉 (Universal Bone Meal)
@bottle-of-gender
leave-my-bars-alone@
-all-enchantments-for-trade
+mc-mods-enchantments-for-trade
i-need-block
spiky-spikes@
straw-statues@|稻草雕像*
@@ -9914,7 +9914,7 @@ world-of-bosses
mirabilis-vanilla-biome-overhaul
-energized-power
+energized-power@
carpenter
tolerable-creepers
anchor
@@ -9933,7 +9933,7 @@ inventory-crafter
maxs-armory|Max 的武器库 (Max's Armory)
nefs-farm-decoration
-create-armory
+create-armory@
dangerous-wasps
createfabricreibugfix@|机械动力Fabric版REI配方显示修复 (Create&REIBugFix/CreateFabric&REIBugFix)
seasontweaks
@@ -9942,7 +9942,7 @@ seasontweaks
@automessenger
-padoru
+padoru@
snow-coated
miracle-berry
@@ -9965,7 +9965,7 @@ bring-color-to-my-skies
portal-dungeons
radiant-gear@¨radiant-gear-fabric
-create-teleporters|机械动力:传送器 (Create : Teleporters!)
+create-teleporters@|机械动力:传送器 (Create : Teleporters!)
enchantato
floating-block@floating-cube|浮空立方体 (Floating Cube)
curious-lanterns
@@ -10014,7 +10014,7 @@ boundless-flux
@axolotlclient
energy-nodes
-fog-looks-good-now-fabric@
+fog-looks-good-now-fabric@fog
thirst-was-taken@|口渴*
unlimited-fluidity
@@ -10028,12 +10028,12 @@ oceanic-expanse@|海洋拓展*
origins-vampire|起源:吸血鬼 (Origins: Vampire)
bad-to-the-bone¨bad-to-the-bone-fabric
-workers
+workers@villager-workers
sculk-horde|幽匿部落*
stratospherical-expansion
candlelight-lets-do-a-candlelight-dinner@lets-do-candlelight|烛火晚宴 ([Let's Do] Candlelight)
-let-me-play-iris
+let-me-play-iris@
dimensional-depths
create-molten-vents@
everything-as-a-hat¨@everything-as-a-hat|Everything as a Hat - 已失效
@@ -10045,7 +10045,7 @@ diamond-economy@|钻石经济*
texels-paintings
tinkers-expansion
revelationary@
-fullstack-watchdog
+fullstack-watchdog@
adventure-apparatus
neruina@
@@ -10083,7 +10083,7 @@ mutant-monsters@
@physics-toys
tarot-cards@
-chatmove
+chatmove@
@forgedloaderapi
public-transport-mod
mineral-chance@
@@ -10139,7 +10139,7 @@ ae2_tools
create-compats
dont-drop-it@
nicemod-new-blocks@nicemod
-forgematica@|全息蓝图 (Forgematica/Litematica-Forge)
+forgematica@|全息蓝图 (Forgematica / Litematica-Forge)
framland
@blahaj-legacy|布罗艾:旧版 (Blåhaj:Legacy)
deep-aether@|深入天境*
@@ -10239,7 +10239,7 @@ improved-vanilla@
upgraded-netherite-aetherite
betterwithpatches@
-pickable-orbs
+pickable-orbs@pickable-health-orbs
mobneutralizer
@@ -10251,7 +10251,7 @@ ender-pearl-swap
jer-ore-integration
adorkable-dogs-pocky|DK狗的Pocky (Adorkable dog's Pocky)
-realistic-explosion-physics
+realistic-explosion-physics@
nitwitification
items-to-mobs
@@ -10266,7 +10266,7 @@ new-nether-chest@|下界箱子 (Nether Chested)
plenty-plates@
simple-sponge
new-paper-doll@paper-doll
-ender-zoology@
+ender-zoology@|末影动物学*
vectorientation@
seven-days-to-fix-parasitus
dtm-integrations
@@ -10299,7 +10299,7 @@ extraordinary-extra-totems
@squidfriends
beachparty@lets-do-beachparty|沙滩派对 (Let's Do Beachparty)
-s33r-more-food
+s33r-more-food@
froglight-backport
@@ -10365,7 +10365,7 @@ wildberries
kubejs-powah
@hexkinetics|咒法动力学 (HexKinetics)
-sand_box
+sand_box@sandbox
sublime
spells-shields-x-tinkers-construct
@@ -10396,12 +10396,12 @@ strategic-enchanting
forged-in-fire
lumy-skin-patch
@le0s-spoons
-@redstone-clock
+redstone-clock@
anti-mob-griefing
nbtedit-reborn@|游戏内NBT编辑器重制版 (In-game NBTEdit Reborn)
the-filler-update@
-custom-machinery-create
+custom-machinery-create@
@rightproperguiscale
armor-trims@
revised-phantoms@
@@ -10432,7 +10432,7 @@ kubejs-tfc@
precision-prospecting@
potatoos-custom-structure-for-hbms-nuclear-tech
fabric-seasons-terraformers-compat@
-fabric-seasons-extras@
+fabric-seasons-extras@|Fabric Seasons: 拓展 (Fabric Seasons: Extra)
better-f3-plus@
fabric-seasons-delight-compat@
fabric-seasons-terralith-compat@
@@ -10524,14 +10524,14 @@ stat-check
hit-indication@
multipart-machines-farming
-lotweakr
+
tru-first-person-mod
reduced-music-delay
agers-giant-junkyard-dimension
jsmacros
great-big-world@
armored-mobs
-inversia@
+astrological@
end-expansion-the-lamented-islands
@@ -10558,11 +10558,11 @@ cherry-blossom-grotto
parties
pots-and-mimics-rpg
-@gemspark
+gemspark@
otakomod
wall-jumping
new-life
-reeves-furniture
+reeves-furniture@reevess-furniture
@undying|不朽 (Undying)
creatania
boat-rocked
@@ -10592,13 +10592,13 @@ alphabet-speedrun@|自定义速通挑战 (αβspeedrun)
@symlink-check|符号链接拦截 (Symlink Check)
tis-stringify
-@dismount-entity
+dismount-entity@¨dismount-entity-fabric
dyeable-compasses@|染色指南针*
supercompression|超级压缩 (Super Compression)
better-hungteen-s-plants-vs-zombies|更好的HTPVZ (Better HungTeen's Plants vs. Zombies)
piglinsafety|猪灵:多喝岩浆 (PiglinSafety)
gatewayer
-bocchud@|孤独HUD (BoccHUD/MiniHUD-Forge)
+bocchud@|孤独HUD (BoccHUD / MiniHUD-Forge)
arrowcollector@arrow-collector|你返箭吗 (Arrow Collector)
saplingslayer|鸽子衔枝 (SaplingSlayer)
quality-quails
@@ -10607,8 +10607,8 @@ hydration
halohud@
resourcify@
ioclias@
-twilights-flavors-delight@twilight-delight|暮色风味乐事 (Twilight Flavors & Delight)
-@clean-f3
+twilights-flavors-delight@twilight-delight|暮色风味乐事 (Twilight's Flavors & Delight)
+clean-f3@
enchanted-lib
architect-tools-converter-1-7-10|建筑师工具 - 转换器 (Architect Tools - Converter)
@@ -10623,7 +10623,7 @@ ships-mod-unofficial|船:非官方版 (Cuchaz Ships Unofficial)
storage-overhaul
chorus-warps
aureate-reliquary
-submerged-explosions
+submerged-explosions@
netherite-items
aim-plus
reckless-drilling
@@ -10673,7 +10673,7 @@ wizardy-delight@wizardry-delight
tinyallies@
-all-da-nuggets
+mc-mods-da-nuggets
random-recipes
starks|史塔克一家*
easy-paper
@@ -10715,7 +10715,7 @@ iron-bows-forge¨iron-bows-fabric
filtered-chests
-@anti-xray
+antixray@anti-xray¨antixray-forge
special-strength
armorpoints@
easy-enchanting@|轻松附魔*
@@ -10732,7 +10732,7 @@ suspicious-sand-maker
create-cobblemon-industrialized@
create-pixelfactory
ies-tweaks
-@haunt-furnace
+haunt-furnace@
player-ladder@
orb-of-origin-plus@
@@ -10746,12 +10746,12 @@ classic-minecraft-icon@
some-useful-ores
@stardew-valley-mod
rainy-harvest
-mythic-mobs@
+mythic-mobs@mobs-of-mythology
lost-features@lostfeatures
bagus-lib@
@better-doors
-3178320@server-pack-unlocker¨3178321
+server-pack-unlocker-forge@server-pack-unlocker¨server-pack-unlocker
x-enchant
@blahaj-remake
@@ -10809,7 +10809,7 @@ workshop-for-handsome-adventurer
desert-upgrade
ocean-recovery
more-armor-trims
-all-the-trims@allthetrims
+mc-mods-the-trims@allthetrims
@bamboo-sign-editor|告示牌编辑器 (Bamboo Sign Editor)
revival-orb@
stackable-trims
@@ -10829,7 +10829,7 @@ emogg@
@festival-delicacies|节日佳肴 (Festival Delicacies)
elytra-trims@
benefits-of-reading|雕纹书架注魔/阅页读著 (Benefits of Reading)
-gothic-rpg
+gothic-rpg@
arcadian-dream@|幻想之梦*
dungeon-and-taverns
@@ -10876,7 +10876,7 @@ stackable127@
wanderer-profession
-cataclysmic-combat
+cataclysmic-combat@
persona
create-air-forge
@@ -10892,7 +10892,7 @@ do-api@
@tp-chat-cmd|TP 聊天命令 (TP Chat Command)
grabby-mobs@
pandas-falling-trees@
-iron-ender-chests
+iron-ender-chests@
delightful-creators-fabric@|动力乐事 (Delightful Creators)
deathbutthree@death-but-three|逝不过三 (Death But Three)
@@ -10914,7 +10914,7 @@ overworld-piglins@
waveapi@
modlist
panorama-screens@
-campfire-spawn-and-tweaks
+campfire-spawn-and-tweaks@
ghostz@
better-totem-of-undying@better-totem-of-undying-forge¨better-totem-of-undying-fabric
modonomicon@
@@ -10934,7 +10934,7 @@ skinned-carts
quick-effect@quickeffect
block-log
-equipment-benediction|装备祝福*
+equipmentbenediction@equipment-benediction|装备祝福 (Equipment Benediction)
@gms|现代游戏模式选择器 (Modern Gamemode Switcher)
dimension-localized-inventories
skillcraft-modpack-tool
@@ -10945,7 +10945,7 @@ worldsalads-opulence
@wyrms
pearfection
-enderchests¨enderchests-fabric
+enderchests@¨enderchests-fabric
dragon-rider
create-utilities-fabric@create-utilities|机械动力:实用物品 (Create Utilities)
@@ -10963,7 +10963,7 @@ villagertradefix
bullet-chat|弹幕聊天*
-fishermans-trap
+fishermans-trap@fishermens-trap
removebats@|禁止蝙蝠生成 (RemoveBats)
nabba
enchantdemon|附恶魔 (EnchantDemon)
@@ -10977,7 +10977,7 @@ stellarity
@modern-sound
@polished-gui
-all-bark-all-bite
+mc-mods-bark-all-bite
lively-forests
dynamic-fullbright@
@@ -11028,10 +11028,10 @@ renewable-spore-blossoms
mobs-info@mobsinfo
-@ngrok-api
+ngrok-api@
-@swordunsheather|利刃出鞘:重铸 (Sword Unsheathe Recasting)
+@swordunsheather|利刃出鞘:重铸 (Sword Unsheathe Reforged)
rpgloot
@sus-saver
@@ -11056,12 +11056,12 @@ brown-mooshrooms
@better-log4j-config
@harvest
wooden-hoppers
-skeleton-horse-spawn@
+skeleton-horse-spawn@¨skeleton-horse-spawn-fabric
configanytime@
faster-crouching@
-yeetusexperimentus
+yeetusexperimentus@yeetus-experimentus
xbob@|准星摇晃 (Crosshair Bobbing)
-zombie-horse-spawn@
+zombie-horse-spawn@¨zombie-horse-spawn-fabric
tinkers-katanas
fbp
yeetem-potions@
@@ -11094,7 +11094,7 @@ despawning-eggs-hatch@
mob-death-messages
chunkapi@
@betterwaystonesmenu
-@big-fish
+big-fish@
nulltal@
caffeinefilled@
pet-transfer-trade-your-pets@pet-pass-trade-your-pets!
@@ -11104,7 +11104,7 @@ dixtas-armory@
ingamestats@
hanger-system-overhaul
isaidnosnow@
-jarsauth|客户端验证 (JarsAuth) - 此已不受支持¨@jarsauth|客户端验证 (JarsAuth) - >= 4.0
+jarsauth|客户端管理 (JarsAuth) - 此已不受支持¨@jarsauth|客户端管理 (JarsAuth) - >= 4.0
autoelytrapanic@
more-crossbows-cj
multipart-machines-cooking
@@ -11178,7 +11178,7 @@ remodified|你再造! (Remodifier)
better-fusion-reactor-for-mekanism@
-growableores@
+growableores@¨growableores-ore-cane-forge¨growableores-ore-cane-neoforge
golemsarefriends
@@ -11186,7 +11186,7 @@ keep-command-history@keepcommandhistory
generatorgalore
-@map-shirts
+map-shirts@
fireproof-boats
dyenamicsandfriends
@@ -11197,13 +11197,13 @@ hunger-reworked
armor-status-hud-renewed|耐久信息显示:重生 (Armor Status HUD Renewed)
boblib
placeable-mobs@placeble-mobs
-potion-blender
+potion-blender@
t6-auto-attack-mod@t6-auto-attack
forceasciifont-backport
-@vmupdate|VM汉化更新 (VM Translation Update)
+vmtranslationupdate@vmupdate|VM汉化更新 (VM Translation Update)
trample-no-more@
-jeremyseq-damage-indicator
+jeremyseq-damage-indicator@jeremyseqs-damage-indicator
digs-dnd-origins
superior-flat
@@ -11219,7 +11219,7 @@ gilded-ingot
chatpatches@|聊天补丁 (Chat Patches)
burning-furnace@
shadowizardlib@
-ants-unleashed
+ants-unleashed@
@seaborgium
gold-fish
pipeplus@
@@ -11257,7 +11257,7 @@ dark-matter@
simply-steel-continued@
simple-corinthium
-chidori-origins-collection
+chidori-origins-collection@
enhancedp2p|增强的P2P (EnhancedP2P)
custom-de-upgrade-recipes|自定义 DE 升级配方 (Custom DE Upgrade Recipes)
mode-switch
@@ -11292,7 +11292,7 @@ custom-villagers|自定义村民*
turtlematic
remove-base-origins
@cobblemon-delights|方块宝可梦乐事 (Cobblemon Delights)
-redirectionor|异引定址 (Redirector)¨redirectionor-retro|异引定址 (Redirector)
+redirectionor@redirector|异引定址 (Redirector)¨redirectionor-retro|异引定址 (Redirector)
villager-mantle-fix|村民帽子修复*
rechiseled-create@
xaeroplus@|Xaero的地图增强 (XaeroPlus)
@@ -11315,7 +11315,7 @@ yamato-gun-mod@yamato-gun
ars-mage-fight
-epicfight-pirates
+epic-sanji
kubejs-entity-events-extension
mc-dungeons-enchanting@|我的世界:地下城附魔 (MC Dungeons Enchanting)
rei-custom-command|REI自定义命令 (REI Custom Command)
@@ -11328,7 +11328,7 @@ makecold|冷境 (MakeCold)
sculk-redstone-components@sculkredstonecomponents
-toggle-enchantments
+toggle-enchantments@
unbreakable-enchantment-forge@unbreakable-enchantment
immersive-portal-gun@portal-gun|沉浸式传送枪*
tac-craft-tactical-armor-pack
@@ -11343,23 +11343,23 @@ illager-invasion@|灾厄侵扰*
@touhou-origins-blessings
altorigingui@
-dynamic-trees-pams-harvestcraft-2
-dynamic-trees-hexerei
+dynamic-trees-pams-harvestcraft-2|动态的树:潘马斯农场2 - 果树附属 (Dynamic Trees Pam's Harvestcraft 2: Trees)
+dynamic-trees-hexerei|动态的树:魔法巫师附属 (Dynamic Trees - Hexerei)
minium-stone@
@fastrtp
-tech-decorators@|科技装饰商*¨@tech-decorators-fabric|科技装饰商 (Tech Decorators)
-dynamic-trees-ars-nouveau
+tech-decorators@|科技装饰商*
+dynamic-trees-ars-nouveau|动态的树:元素魔艺附属 (Dynamic Trees - Ars Nouveau)
@kazzmons-magecraft
@metal-bundles
-tidal-towns
+tidal-towns|潮汐小镇*
blossom-blade
cute-kiwi-birds-new-animal
-moremobheads
+moremobheads@
ouchies@
@traditional-asphalt
@thaumic_boots
@@ -11367,7 +11367,7 @@ carpeted-stairs@
just-enough-archaeology
bedrock_world
-world-preview@
+world-preview@|世界预览*
the-five-nights-at-freddys-mod@the-five-nights-at-freddys-mod#all-versions|玩具熊的五夜后宫 (The Five Nights at Freddy's Mod)
easylan@|自定义LAN局域网联机服务器 (EasyLAN)
@@ -11395,7 +11395,7 @@ moogs-end-structures@mes-moogs-end-structures
@oneclickcrafting
@genshin-ui
fenomena-structures@phenomena-structures
-first-join-message
+first-join-message@
expansive-weaponry
wabi-sabi-structures-forge¨wabi-sabi-structures-fabric
jobsaddon@
@@ -11531,7 +11531,7 @@ mother-silverfish
mcretector@
little-botanics
-ex-pattern-provider|AE2扩展 (ExtendedAE)
+ex-pattern-provider@extended-ae|AE2扩展 (ExtendedAE)
@integrated-circuit
creative-disk
engineers-construct
@@ -11553,7 +11553,7 @@ pipe-master-2000|管道专家 2000 (Pipe Master 2000 / Pipe Googles)
command-macros@|命令宏*
@shwetro|上海地铁装饰组件 (The Shanghai Wetro Mod)
yuushya-modelling|方块建模*
-tactical-aid|战术医疗*
+tactical-aid@|战术医疗*
@clear-enchanting
fishing-bobber-detector
@unfix-mc-181190|村民折扣叠加 (Unfix MC-181190)
@@ -11597,11 +11597,11 @@ cozy-foods-milk-tea
opolis-miners@
netherite-but-cheaper
@fabric-hammers
-items-displayed-forge@¨items-displayed-fabric@items-displayed
+items-displayed-fabric@items-displayed¨items-displayed-forge@
wood-converter
hammer-mod
-realisticsleepfabric@realisticsleep
+realisticsleepfabric@stevesrealisticsleep
zombies-actually-siege
hex-gloop@hexgloop|咒法凝浆*
the-void
@@ -11614,7 +11614,7 @@ wither-dimension-whitelist
usefulfood-reborn@
ancient-warfare-2-tweaked@
-cuffed
+cuffed@
rockn-roller@rocknroller
bodies-bodies@
potionparticlepack@|药水粒子包 (Potion Particle Pack)
@@ -11624,7 +11624,7 @@ potion-bundles@|药水捆*
kofi-table@
better-mcdonalds-mod@
@itemframesplus
-sinytra-connector@connector
+sinytra-connector@connector|信雅互联*
noclip@
diamond-in-the-rough-as-in-obsidian@diamond-in-the-rough
factioncraft@
@@ -11665,7 +11665,7 @@ player-stages|玩家阶段*
generation-stages|生成阶段*
ars-oscura@|黑暗魔艺*
bobby-reforged
-shut-up-gl-error
+shut-up-gl-error@
no-spider@
terracart-reloaded
dme
@@ -11778,7 +11778,7 @@ nb_mod
stacked-armor-trims@
@final-beta
-@better-trim-tooltips
+better-trim-tooltips@
totally-enough-pain@
custom-village|村民调教*
animaticareforged
@@ -11847,7 +11847,7 @@ simple-enchantments
simple-weapons-for-better-combat
wither-drops-netherite-templates
@spineless
-immersive-melodies
+immersive-melodies@
theobsidianboat
dragon-survival-compatibility@|龙之生存:兼容*
bettercookedaxolotls
@@ -11949,7 +11949,7 @@ prehistoric-nature-silurian-dimension
grass-seeds@
minecraft-dungeons-weaponry
ahznbs-naruto-mod-addon
-random-village-names@
+random-village-names@¨random-village-names-fabric
mooshroom-tweaks@
grinners-ents
log-cleaner@
@@ -11962,7 +11962,7 @@ souls
real-seasons
eternal-winter
move-boats@
-omnom
+omnom@
forest-x-reborn@
exlines-bark-carpets@bark-carpets
exlines-more-carpets
@@ -12005,9 +12005,9 @@ harvestcraft-tweaker
the-legend-of-the-mudman
mutagenesis
nether-update-backport
-l2hostility|莱特兰-恶意 (L2Hostility)
-packagedthaumic|封包神秘 (PackagedThaumic)
-cat-eyes-night-vision-toggle-mod@cat-eyes
+l2hostility@|莱特兰-恶意 (L2Hostility)
+packagedthaumic@|封包神秘 (PackagedThaumic)
+cat-eyes-night-vision-toggle-mod
vtdownloader@
smithing-mod
@@ -12026,7 +12026,7 @@ prehistoric-nature-triassic-dimension
flower-power
vr-combat@
embeddium@
-no-arrows-in-you@naiy
+no-arrows-in-you@
@unicopia|奇幻小马国 (Unicopia)
ryans-zombies
lights-out-2
@@ -12057,7 +12057,7 @@ deep-dark-regrowth
textrues-embeddium-options@|TexTrue的Embeddium视频界面 (TexTrue's Embeddium Options)
silent-mine
headhunter-mod@shadows-formidable-foes-the-headhunter
-yungs-better-jungle-temples@|YUNG的丛林神庙优化 (YUNG's Better Jungle Temples)¨yungs-better-jungle-temples-fabric|YUNG的丛林神庙优化 (YUNG's Better Jungle Temples)
+yungs-better-jungle-temples@|YUNG的丛林神庙优化 (YUNG's Better Jungle Temples)¨yungs-better-jungle-temples-fabric|YUNG的丛林神庙优化 (YUNG's Better Jungle Temples)¨yungs-better-jungle-temples-neoforge|YUNG的丛林神庙优化 (YUNG's Better Jungle Temples)
forlorn-beasts
harpiccore-mod
poonggis-add-more-bosses
@@ -12087,9 +12087,9 @@ loginar-storage@
night-vision-flash-be-gone
@ancient-return
-allayed
+mc-modsayed
honkai-star-rail-12|星铁12*
-torchflower-relit
+torchflower-relit@
fexs-random-stuff-mod
k9@k9-mod
the-digimod-beta|方块数码宝贝 (The Digimod)
@@ -12110,7 +12110,7 @@ your-log-saw-something-last-night@
tubes-reloaded@
-natures-spirit|自然之灵 (Nature's Spirit) - 已失效¨@natures-spirit|自然之灵 (Nature's Spirit)
+natures-spirit@|自然之灵 (Nature's Spirit)
@natrium
bossominium@
@sort-extension
@@ -12120,7 +12120,7 @@ history-of-middle-earth-legacy|中洲历史:传承 (History of Middle-earth: L
hostile-humans@
classic-and-simple-status-bars@cssb|经典且简易的状态栏 (Classic and simple status bars)
@turtle-charging-station
-@your-reputation
+your-reputation@¨your-reputation-jade@¨your-reputation-wthit@
futurediary|未来日记 (FutureDiary)
infiniverse@
use-item-on-block-event@
@@ -12172,7 +12172,7 @@ netherrocks@
efw-forgotten-place
@vulkanite-mod
-yungs-better-end-island@|YUNG的末地岛屿优化 (YUNG's Better End Island)¨yungs-better-end-island-fabric|YUNG的末地岛屿优化 (YUNG's Better End Island)
+yungs-better-end-island@|YUNG的末地岛屿优化 (YUNG's Better End Island)¨yungs-better-end-island-fabric|YUNG的末地岛屿优化 (YUNG's Better End Island)¨yungs-better-end-island-neoforge|YUNG的末地岛屿优化 (YUNG's Better End Island)
bellsandwhistles@
daniinatorul
@@ -12204,7 +12204,7 @@ prehistoriclegacy
redyed
enchantmentdisabler@enchantment-disabler
miners-glasses
-relics-and-alchemy
+relics-and-alchemy@
@greate
advanced-world-selection
accelerated-decay@
@@ -12223,7 +12223,7 @@ akkamaddis-arsenic-and-lace|Arsenic and Lace - 新
xiyus-exchanted-book|饩雨的附魔书 (xiyu's Exchanted book)
la-abuelita
-rotted-forge
+rotted-forge@rotted
rustic-furniture-compat
@no-realms-button|Realms按钮移除 (No Realms Button)
@benchantments
@@ -12263,9 +12263,9 @@ akkamaddis-simple-cthon@
@heads-hurt-too!
pooping-animals
good-boy@
-nethers-overhaul
+nethers-overhaul@
+better-battle-towers|战斗高塔,启动!*
-gregtech-ce-unofficial-child-happy-edition@|格雷科技社区版非官方版儿童快乐版 (GregTech CE Unofficial : Child Happy Edition)
@axiom
@@ -12290,7 +12290,7 @@ potion-of-armor@
tenebrous-lands@
super-better-grass
configurable-boss-bars@
-nuclearcraft-neoteric
+nuclearcraft-neoteric@
beastly-beacons
creeplets@
thermoo@
@@ -12318,7 +12318,7 @@ haraldsbetterstructures
squake
ae2-uel-extended|应用能源2非官方拓展 (AE2 Unofficial Extended)
terraria-calamity-mod|泰拉瑞亚灾厄 (Terraria Calamity)
-darkrtp-rtp-random-teleport
+darkrtp-rtp-random-teleport@darkrtp
cute-bears
additional-fruits@
bigger-better-end-cities@
@@ -12330,7 +12330,7 @@ persistentcooldowns|物品冷却持久化 (Persistent Cooldowns)
advancement-based-spawning@
heroic-armory-legacy
-yungs-menu-tweaks@|YUNG的菜单调整 (YUNG's Menu Tweaks)¨yungs-menu-tweaks-fabric|YUNG的菜单调整 (YUNG's Menu Tweaks)
+yungs-menu-tweaks@|YUNG的菜单调整 (YUNG's Menu Tweaks)¨yungs-menu-tweaks-fabric|YUNG的菜单调整 (YUNG's Menu Tweaks)¨yungs-menu-tweaks-neoforge|YUNG的菜单调整 (YUNG's Menu Tweaks)
entity-distance-1-12-2|实体距离 (Entity Distance)
coolesthardcore@coolest-hardcore
taxcastlepillager
@@ -12338,9 +12338,9 @@ pesky-pirates@
subterrestrial@
illusioners-tower
bad-npcs
-darkfeather-golden-feather
-darkspawn-teleport-to-spawn
-darksmelting-smelt-armor-and-tools
+darkfeather-golden-feather@darkfeather
+darkspawn-teleport-to-spawn@darkspawn
+darksmelting-smelt-armor-and-tools@darksmelting
fast-build
digi-applimobs|数码宝贝宇宙应用怪兽*
duckies
@@ -12371,7 +12371,7 @@ fizzle
grimoire-api
cristel-lib@
-more-sleeps
+more-sleeps@more_sleeps
o-coracao-da-selva
creative-experience
more-than-50
@@ -12380,7 +12380,7 @@ forge-soul-like-armors-reworked
@meds-and-herbs
soul-like-monsters-epic-fight-addon
souls-like-parry
-@tcdcommons
+tcdcommons@
autotranslation@|自动翻译 (AutoTranslation)
villages-and-pillages@
@@ -12399,7 +12399,7 @@ tw-resurrection
@dice
any-lanterns@any-lanterns!
horse-tack
-darkmobs-increase-mob-difficulty
+darkmobs-increase-mob-difficulty@darkmobs
@apollo-the-parrot
mob-variants
galvanization
@@ -12451,7 +12451,7 @@ just-sword-blocking
mltpojectmonster|銘洛天的怪物增强 (MLTPojectMonster)
@relics-of-the-sky|空岛遗物 (Relics of the Sky)
-ae2-stuff-extended
+ae2-stuff-extended@
butchers-delight-foods@
better-falling@
dmcloot
@@ -12484,7 +12484,7 @@ weapons-of-miracles-epicfight@weapons-of-miracles
mcdar|我的世界:地下城法器 (MC Dungeons Artifacts)
dnt-swamp-hut-overhaul
-jaopcagt
+jaopcagt@
smidgeon-o-bliss
cable-flux@12.3.5
jet-and-elias-armors
@@ -12552,7 +12552,7 @@ better-wake-up-position@|更好的起床位置 (Better Wake-up Position)
railroad-blocks-forge@railroad-blocks¨railroad-blocks
fossilmon@
-opack2reload|资源包惰性重载/抑验怠载 (OPack2Reload)
+opack2reload|资源包惰性重载/抑验怠载 (0Pack2Reload)
@wits
@motleys-music-discs
@@ -12601,7 +12601,7 @@ dynamic-village@
jammies@
dj-villager
ars-energistique
-chatimages|聊天图片 (ChatImage)
+chatimages@chatimageN|聊天图片 (ChatImages)
create-more-drill-heads@|机械动力:更多钻头 (Create: More Drill Heads)
create-liquid-fuel@|机械动力:液体燃料 (Create: Liquid Fuel)
@rays-cool-armor
@@ -12647,7 +12647,7 @@ legendary-origins@
flow@
lit-it-up@
lucky-cat|招财猫*
-all-the-wizard-gear
+mc-mods-the-wizard-gear
better-tools-and-armor
berrfect@|完莓无缺*
mazemanicore
@@ -12657,15 +12657,15 @@ uncanney-valley
@quality-sounds
dolt-compat
embeddium-extension
-@wakes
+wakes@
create-immersive-portal-integration
dangers-in-the-darkness
spookycraft
-kelpie
+kelpie@
@viavanillaplus
dead-mans-abyss
the-leagues-of-the-dead
-@centered-crosshair
+centered-crosshair@
@create-fabric-sodium-fix
realm-rpg-creep-crop
fexcraft-common-library
@@ -12710,7 +12710,7 @@ pick-blockstate@pickblockstate
@epcore|满同态核心 (Epimorphism Core)
oh-my-sherd
archaeology-banners@
-mobvote-2023-crab
+mobvote-2023-crab@
totem-curse
zombies-are-real
@@ -12718,7 +12718,7 @@ timeless-and-classics-guns-lesraisins-append-pack@lesraisins-weapon|TaC:绿葡
permanent-chat-logs@permanent-chatlogs|聊天记录保存 (Permanent ChatLogs)
mob-strength@
catastrophemod
-
+@water-generators|水发电机 (Water Generators)
fishes-undead-rise-ye
nameless-servers@
noisium@
@@ -12732,7 +12732,7 @@ modular-item-api@¨truly-modular-arsenal@¨truly-modular-archery@¨truly-modular
@actionhunger
trafficcraft@
banilla-hammers@
-
+everyx-hotpot|一起火锅 (EveryXHotpot)
@hira-hira
tierability@
soul-collector@
@@ -12781,7 +12781,7 @@ petal@
creatures-of-runeterra@cor
from-another-world@
pumpkin-moon@
-zombie-onslaught
+zombie-onslaught@
neighborly
natural-progressions@natural-progression
charged-explosives@
@@ -12800,7 +12800,7 @@ chat-colours@
mekanism-weapons|通用机械武器 (Mekanism: Weapons)
vanilla-reflex@
flighthud-reborn|鞘翅飞行抬头显示:重生 (FlightHUD: Reborn)
-
+celestial-enchantments|星月附魔*
clearsky|洁净天空 (ClearSky)
educate-nitwit
damage-spawns-mobs
@@ -12808,7 +12808,7 @@ decorative-sniffer-egg@
gilded-sherds@
camps-castles-carriages
rainbow-reef@
-@advancement-no-more
+advancement-no-more@
aqua-geode
medieval-buildings@
@@ -12833,7 +12833,7 @@ advanced-enchantments@|进阶附魔*
oaks-nature@
geophilic-reforged
lglegacy@|延迟监视:移植版 (LagGogglesLegacy)
-@smooth-scrolling-refurbished
+smooth-scrolling-refurbished@
medieval-weapons-pack@
celestial-artifacts|星月遗物*
@@ -12855,7 +12855,7 @@ nbt@
separated-leaves@
pangteens-immortal-adventure@|PangTeen的平凡冒险 (PangTeen's Immortal Adventure)
-simple-shops|简单商店*
+simple-shops@simpleshops|简单商店*
forgiving-border|仁慈的世界边界 (ForgivingBorder)
snow-mercy
@@ -12917,7 +12917,7 @@ speedy-ladders
@youaremyhatnow
-fruits-delight|果园乐事*
+fruits-delight@|果园乐事*
destruction-difficulty@destructiond|破坏困难*
@@ -12928,7 +12928,7 @@ asmc-performance-patch
mrcrayfishs-gun-mod-unofficial|MrCrayfish的枪:非官方版 (MrCrayfish's Gun Mod: Unofficial)
@fish-tanks
4913730@ram-compat
-
+@wcsm|中国式学校 (Chinese School Mod)
zombies-reworked-forge@zombies-reworked
legendary-monsters@
catontoasts-mobs
@@ -13015,7 +13015,7 @@ sakura-cherry-additions
pillagers-gun|掠夺者的枪 (Pillager's Gun)
hammers-and-smithing
-tetra-booster-pack
+tetra-booster-pack@withering-boon-for-tetra
everlasting-skins
legacy-console-sounds@
@@ -13036,15 +13036,15 @@ ore-discovery-broadcast@
alchemists-garden
opolis-strainers
book-eater@
-rotom-phone@
+rotom-phone-cobblemon@
@world-comment|随处随笔 (World Comment)
ultramarine-refabricated|群青:重织*
long-nbt-killer
@curio-attribute|饰品属性 (CurioAttribute)
consistent-aim|持久瞄准/移眼盯住*
-@arrow-pointers
-bareback-horse-riding
+arrow-pointers@
+bareback-horse-riding@
what-the-gecko@
forgotten-pots-forge
explorations@
@@ -13098,7 +13098,7 @@ eugenes-guan-dao@
eugenes-wealthy-plains-village
lets-do-herbal-brews@lets-do-herbalbrews|煨茶酝露 (HerbalBrews)
enchant-icon@|附魔标签*
-vintage-delight|腌渍乐事*
+vintage-delight@|腌渍乐事*
@hotshot
biospherical-expansion@
@serendustry
@@ -13116,7 +13116,7 @@ awesome-magic@awesome_magic
christmas-dweller
create-curio-goggles@
@cobblemon-loot-balls
-dontusecommand|请别用指令 (DontUseCommand)
+dontusecommand@|请别用指令 (DontUseCommand)
beans-backpacks@
randomjs@
@@ -13137,7 +13137,7 @@ metabolism@|新陈代谢*
adv-js|Advancement JS - 更新较慢¨@advancementjs
teleportcraft@
frights-delight@|惊吓乐事 (Fright's Delight)
-travelers-compass
+travelers-compass@
@artemis-thin-logs
configjs@
hardrock-tools-materials
@@ -13157,7 +13157,7 @@ clickmanaita
command-toast|指令面包机*
@hex-research|咒法研究 (Hex Research)
cwg-far-plane-view
-firmacivilization
+firmacivilization@firmaciv|群峦传说:航海文明 (Firma: Civilization)
catbop-things
player-mobs@
@create-trimmed
@@ -13196,10 +13196,10 @@ respite-creators-fabric@
simple-pizzas@|简单比萨*
rapscallions-and-rockhoppers@
pescatore@
-apocalypse-now
+apocalypse-now@
cenozoic-nightmare-the-horror-of-prehistory
-@quickbackupmulti|多槽位备份 (QuickBackupMulti-Fabric)
+quickbackupmulti@|多槽位备份 (QuickBackupMulti-Fabric)
slashblade-japanese-addon-pack-reforked|拔刀剑日系附属重置版 (SlashBlade Japanese Addon Pack Reforked)
@create-fabric-fixes
@@ -13215,7 +13215,7 @@ cerbons-api-forge@cerbons-api
arcane-apprentices
kirara
nether-gold
-create-interactive@interactive
+create-interactive|Create: Interactive - 已放弃¨@interactive
this-tsunami
blendium@
awakened-bosses
@@ -13250,14 +13250,14 @@ digestive
@inventory-binds
octo-lib@
-farmers-utils
+farmers-plus¨farmers-utils|Farmer's Plus - 旧
architects-friend
bagus-cosmetic@
floatingitems
ars-ocultas@
tetracelium@
-create-food-fabric@create-food
+create-food@
a-block-of-charcoal|木炭块 (A Block of Charcoal)
@@ -13304,7 +13304,7 @@ ae2-network-analyser
mxtune
customui|自定义UI (CustomUI)
deadly-monsters-patched
-glodium
+glodium@
aether-delight
dungeonz@
@@ -13330,7 +13330,7 @@ phosphorcrashfix
sound-physics-remixin|籁*
hextended-staves@
aquaculture-delight
-vics-point-blank
+vics-point-blank@
occultism-kubejs
tetra-extras@
anilink
@@ -13359,7 +13359,7 @@ mmm-lib
create-design-n-decor@
-enviromine-lite@
+enviromine-lite@|更多生存要素:精简版 (EnviroMine Lite)
knaves-needs@
azurelib-armor@
@container-tooltips
@@ -13470,7 +13470,7 @@ leftist-potions@
more-delight-fabric@more-delight¨more-delight-forge
mceconomy3
@antique-atlas-4
-
+pollution|污染*
tinted-campfires@
additionalstatus
epic-knights-slavic-armory
@@ -13497,7 +13497,7 @@ mekanismecoenergistics@mekanism-eco-energistics
waila-blacklist|Waila黑名单 (WAILA Blacklist)
item-blacklist|物品黑名单*
continue@
-the-dawn-era@
+the-dawn-era@|黎明纪元*
tridents-n-stuff@
create-hand-crafting@
@@ -13523,7 +13523,7 @@ museum-curator@|琳琅满目*
pixel-hud@
@immibis-macroblocks
@heater
-@natures-melody
+@natures-melody|自然旋律 (Nature's Melody)
astemirlib@
create-unbreakable-tools@create_unbreakable
timeless-heroes@superhero
@@ -13557,7 +13557,7 @@ nether-sheep@|暗黑羊*
light-level-description
set-home-waypoints
leaky
-curse-of-pandora|潘多拉之咒 (Curse of Pandora)
+curse-of-pandora@|潘多拉之咒 (Curse of Pandora)
champions-rotn-edition
tempest@
simpledifficulty-for-underdog
@@ -13575,7 +13575,7 @@ killer-rabbit-transformation|转化杀手兔*
bronze-viking
astikor-carts-redux@astikorcarts-redux
-third-person-shooting|第三人称射击*
+third-person-shooting@third-person-shooting-zero|第三人称射击*
sight|视域*
@the-first-city
threetag-palladium@|钯 (Palladium)
@@ -13584,7 +13584,7 @@ threetag-palladium@|钯 (Palladium)
permanent-status-effect@permanent_status_effect|永久状态效果*
-world-play-time
+world-play-time@
ikwila-i-know-what-im-looking-at
experienced-crops@experienced_crops
medieval-seedbags
@@ -13610,11 +13610,11 @@ no-baby-zombies¨@no-baby-zombies|No Baby Zombies - 已失效
combat-nouveau@
@hanging-on
-
+@lazy-mystical|神秘农业:懒人 (Lazy Mystical)
udlede@|港口*
hammer-time
hammerz
-@pickup
+@pickup|物品框互交优化 (Pickup)
livingadventuretrails
suggestions-api@
colorful-subtitles@
@@ -13624,7 +13624,7 @@ extended-potions
dimension-inventorys|维度物品栏*
dimension-rules|维度规则*
erroring-entity-remover-reforged@eer-reforged
-
+@vs-tournament
fabricated-exchange@
more-variants-and-biomes
badoptimizations@
@@ -13656,7 +13656,7 @@ framed
gear-core@
hideasterisk@hidemodded|隐藏“已修改” (HideModded)
monster-eggs@
-rain-shield@
+rain-shield@|驱雨盾*
cerbons-better-beacons@
@funny-roulette
@worldeditcui-forge
@@ -13699,24 +13699,24 @@ elenai-dodge
xenon@xenon-forge|氙*
riftstorm-rpg
-
+better-babies
morecreativetabs-forge-fabric@morecreativetabs
@shove!
sunflower-delight
-mystias-izakaya|夜雀乐事*
+mystias-izakaya@mystiasizakaya|夜雀乐事*
carpet-everything
lets-do-brewery|盛节精酿 (Let's Do Brewery)
hephaestusplus@
re-dimension-stages|维度阶段重制版 (Re-Dimension Stages)
-lemoned
+lemoned@lemoned-(farmers-delight)
@horizonlimit
fallen-paladins-and-priests
@rgb
@virtualpump
-everymole
+everymole@
mutant-iceologer@mutant-iceologer-mod
@days-gone
@extra-loot|额外战利品 (Extra Loot)
@@ -13729,7 +13729,7 @@ epic-fight-infernal-gainer
prodigy-mechanics
just-an-end-anchor@
-memory-usage-title
+memory-usage-title@|标题显示内存*
sweeper-maid@|清洁女仆*
@@ -13790,14 +13790,14 @@ startinginventory
wireless-speakers|无线扬声器*
-jewelrycraft-2
+jewelrycraft-2|珠宝工艺2*
fallflyinglib
enchantable-spike
xaeros-map-chest-tracker-integration@
warden-horn
too-many-efficiency-losses
-srp-addon-cotesia-glomerata@
+srp-addon-cotesia-glomerata@|SRP:寄生蜂 (Scape and Run Parasites Addon: Cotesia Glomerata)
damage-lock|磁场天锁 (DamageLock)
@@ -13807,7 +13807,7 @@ custom-portals@|自定义传送门*
dirty-lens@
@improved-anvils
styled-player-list@styledplayerlist
-create-love-war
+create-love-war@
chainmailed
serious-player-animations@
@@ -13836,13 +13836,13 @@ thermals-delight
@advanced-hud
better-farmers-combat
-simple-butchery@
+simple-butchery¨@simple-butchery|Simple Butchery - 已失效
butchery
enchantment-reveal@
copycats@
-the-great-alchemical-compendium
+the-great-alchemical-compendium@
desperate-measures@
block-slabs-mod
roost-re-hatched
@@ -13862,10 +13862,10 @@ piglin-army
decorative-ladders@
more-foods
-mordern-kitchen@modern-kitchen|现代厨房 (Modern Kitchen)
+modern-delight@|现代乐事*
better-main-menu@bettermainmenu
-more-wizards
+more-wizards@more-wizards-more-magic-series
oldresearch@
ascension-megamons@
simply-sulphur@
@@ -13948,14 +13948,14 @@ sign-button
startinv@
@server-replay
ftb-stoneblock-companion
-ash-of-sin-custom-anti-enchantment-entity|罪业余烬:自定义反附魔实体 (Ash Of Sin:Custom Anti Enchantment Entity)
-ash-of-sin-anti-high-level-enchantment|罪业余烬:反高级附魔 (Ash Of Sin:Anti High Level Enchantment)
-ash-of-sin-custom-anti-item-entity|罪业余烬:自定义反物品实体 (Ash Of Sin:Custom Anti Item Entity)
-ash-of-sin-custom-anti-seat-entity|罪业余烬:自定义反坐垫实体 (Ash Of Sin:Custom Anti Seat Entity)
-ash-of-sin-custom-entity-anti-effect|罪业余烬:自定义实体反状态效果 (Ash Of Sin:Custom Entity Anti Effect)
-ash-of-sin-custom-entity-effect|罪业余烬:自定义实体状态效果 (Ash Of Sin:Custom Entity Effect)
-ash-of-sin-custom-entity-item|罪业余烬:自定义实体装备 (Ash Of Sin:Custom Entity Item)
-ash-of-sin-eternal-entity|罪业余烬:永恒实体 (Ash Of Sin:Eternal Entity)
+ash-of-sin-custom-anti-enchantment-entity|罪业余烬:自定义反附魔实体 (Ash Of Sin: Custom Anti Enchantment Entity)
+ash-of-sin-anti-high-level-enchantment|罪业余烬:反高级附魔 (Ash Of Sin: Anti High Level Enchantment)
+ash-of-sin-custom-anti-item-entity|罪业余烬:自定义反物品实体 (Ash Of Sin: Custom Anti Item Entity)
+ash-of-sin-custom-anti-seat-entity|罪业余烬:自定义反坐垫实体 (Ash Of Sin: Custom Anti Seat Entity)
+ash-of-sin-custom-entity-anti-effect|罪业余烬:自定义实体反状态效果 (Ash Of Sin: Custom Entity Anti Effect)
+ash-of-sin-custom-entity-effect|罪业余烬:自定义实体状态效果 (Ash Of Sin: Custom Entity Effect)
+ash-of-sin-custom-entity-item|罪业余烬:自定义实体装备 (Ash Of Sin: Custom Entity Item)
+ash-of-sin-eternal-entity|罪业余烬:永恒实体 (Ash Of Sin: Eternal Entity)
fundamental@
wendigo
@@ -14014,7 +14014,7 @@ armortip@
true-herobrine@
oam-by-choupiclou2007@ore-and-more-(oam)
squat-grow@
-backported-wolves
+backported-wolves@
betweenlands-extended-config
deeper-caves@deeper_caves
@@ -14055,7 +14055,7 @@ crystalline-ender-eye|晶化末影之眼*
ars-caelum@
elytra-chestplates|鞘翅之甲*
variants-and-ventures@
-horseshoes@
+horseshoes@|马掌*
questlines@
endofherobrine@
thirstcanteen@thirst-canteen|口渴-水壶 (ThirstCanteen)
@@ -14065,7 +14065,7 @@ thaumic-energistics-extended-life-fork
prehistoric-nature-decorations
tinyfoes
pyradium
-anvilcraft@|铁砧工艺:原版科技 (AnvilCraft)
+anvilcraft@|铁砧工艺:重力科技 (AnvilCraft)
tiny-mob-farm-remastered@
create-aquatic-ambitions@
ffl-trinkets-compat
@@ -14074,7 +14074,7 @@ mc-vr-playground
cosmopolis-mod@cosmopolis
caveopolis-mod@caveopolis_mod
flexipause@
-geysers|间歇泉*
+geysers@|间歇泉*
@moar-enchantments
@lose-your-touch
man-of-many-planes@
@@ -14103,10 +14103,10 @@ respackopts@
fortuitous-feasts
monazite@|独居石*
music-control|音乐控制* - 不再更新¨@music-control|音乐控制 (Music Control)
+stellarcore|星核 (StellarCore)
-
-ash-of-sin-custom-entity-attack-effect|罪业余烬:自定义实体攻击状态效果 (Ash Of Sin:Custom Entity Attack Effect)
-ash-of-sin-soul-like-boss-battle|罪业余烬:类魂BOSS战 (Ash Of Sin:Soul Like Boss Battle)
+ash-of-sin-custom-entity-attack-effect|罪业余烬:自定义实体攻击状态效果 (Ash Of Sin: Custom Entity Attack Effect)
+ash-of-sin-soul-like-boss-battle|罪业余烬:类魂BOSS战 (Ash Of Sin: Soul Like Boss Battle)
wh40kmc-project
pixelmon-bank|Pixelmon 银行*
@@ -14138,7 +14138,7 @@ mace-backport
@steve-eat-stew
imaginary
kuvalich|赤毒玄骸 (KuvaLich)
-ae2-insert-export-card@
+ae2-import-export-card@
@magick-experience
@repairable-disc-11
@@ -14154,7 +14154,7 @@ torches-in-water|水中火把 (Torches in Water)
pigs-with-fireworks
infinityspell|无限魔咒 (InfinitySpell)
multipart-machines-grinding
-ash-of-sin-custom-anti-high-atk-entity|罪业余烬:自定义反高攻击力实体 (Ash Of Sin:Custom Anti High ATK Entity)
+ash-of-sin-custom-anti-high-atk-entity|罪业余烬:自定义反高攻击力实体 (Ash Of Sin: Custom Anti High ATK Entity)
@bioforge
quad@
@@ -14179,7 +14179,7 @@ tectonic-tweak
forge-essentials-client@
@world-host
-spit-splat@
+spit-splat@|唾溅兽*
maced|重锤一击*
nether-villager-trader
@no-exp-enchanting-reimagined
@@ -14227,7 +14227,7 @@ aquatweaks|水下微调 (AquaTweaks)
aquatweaks-compat|水下微调:兼容 (AquaTweaks Compat)
@potions-re-glint
simpletextoverlay@
-bountiful-fares@|丰饶食记*
+bountiful-fares|丰饶食记* - 已失效¨@bountiful-fares|丰饶食记 (Bountiful Fares)
@ancient-debris-tweak|远古残骸微调 (Ancient Debris Tweak)
@@ -14274,7 +14274,7 @@ biome-decoration-fix
simply-tools@
immersive-snowgen@isg|沉浸式雪生成*
the-wandering-gambler
-cheatdetector@|作弊检测器 (CheatDetector)
+cheatdetector|作弊检测器 (CheatDetector)¨@cheatdetector|作弊检测器 (CheatDetector) - 已失效
just-another-spawner
stack-size-edit-fabric@stack-size-edit
@remote-resource-pack|远程资源包 (Remote Resource Pack)
@@ -14290,7 +14290,7 @@ apotheotic-creation@apotheoticcreation
eiorecipesteinductionsmelter
-ash-of-sin-better-ai|罪业余烬:更好的AI (Ash Of Sin:Better AI)
+ash-of-sin-better-ai|罪业余烬:更好的AI (Ash Of Sin: Better AI)
dimensional-cake-rebuilt@dimensional-cake-rebaked
medieval-village-dimension
create-big-contraptions@big-contraptions
@@ -14303,7 +14303,7 @@ pantheonsent@
@moddetectionpreventer
dramatic-spawning
-all-mobs-attack-villagers
+mc-mods-mobs-attack-villagers
cicada@
immersive-cvm
@@ -14330,7 +14330,7 @@ semi-hardcore
placeables@
bigbanana|🍌大香蕉🍌 (BigBanana)
@dabaosword|大宝刀 (DabaoSword)
-@look
+look-eye-of-cthulhu@look
@salmonberry-addition
pet-collecting@
@yummy_glass
@@ -14392,7 +14392,7 @@ lhmob-difficulty-increase|变强的怪物 (LH Mob Difficulty Increase)
from-the-shadow-reborn
@life-crystals
-the-slumbering-omen@
+the-slumbering-omen@|沉睡的预兆*
ftb-guides-forge¨ftb-guides-legacy-forge|FTB Guides - 旧版
@@ -14417,7 +14417,7 @@ andromeda@|群星*
mobdisguises@
inventory-generators
creating-space-gravity-addon
-alexs-caves-torpedoes@alexscaves-torpedoes
+alexs-caves-torpedoes@alexscaves-torpedoes|Alex 的洞穴:物品 & 鱼雷 (Alex's Caves: Stuff & Torpedoes)
@slavic-cuisine
@@ -14428,7 +14428,7 @@ tfc-fresh-water-everywhere
tfc-more-swords
galleria@
constructs-casting@
-
+@tinkersinnovation|工匠创新 (Tinkers' Innovation)
delicious-delights
@vietnamsdelight
@@ -14483,8 +14483,8 @@ additional-attributes@
suicide-key
-@mcrconvertlib
-@annotationlib
+uranus@
+annotationlib@
@waxed
nether-overload
ender-relay@ender-relay-ff
@@ -14513,8 +14513,8 @@ hearty-meals@
enderfake
@alwaysonline
-
-
+@awakenedsilverfish|蠹虫觉醒了 (AwakenedSilverfish)
+rawore-on-1-12-2@rawore_on_1.12.2|1.12.2的粗矿 (rawOre_on_1.12.2)
entityjs@
@poem-of-star-wars
@hex-ways
@@ -14537,7 +14537,7 @@ valentines-blessing@valentines-blessing-lilypads-roses
decent-biomes@
d-placeable-food-fabric-forge@3d-placeable-food
fan-shaped-cake@fan-shaped-cake-mod
-dried-spice@
+bitter-brews@
richards-coffee-tea-mod@richards-coffee-and-tea-mod
ribes-adventures@
@@ -14566,7 +14566,7 @@ biome-cows@
simple-stopwatch
liolib@
giacomos-better-dye
-ash-of-sin-custom-anti-trap-cage-entity|罪业余烬:自定义反捕捉笼实体 (Ash Of Sin:Custom Anti Trap Cage Entity)
+ash-of-sin-custom-anti-trap-cage-entity|罪业余烬:自定义反捕捉笼实体 (Ash Of Sin: Custom Anti Trap Cage Entity)
elementus@
dedicated-bud
@@ -14575,7 +14575,7 @@ tfc-barrels
melter@
armour
speedometer-and-more
-ash-of-sin-anti-same-modifier|罪业余烬:反重复修饰符 (Ash Of Sin:Anti Same Modifier)
+ash-of-sin-anti-same-modifier|罪业余烬:反重复修饰符 (Ash Of Sin: Anti Same Modifier)
giacomos-automatable-cauldrons
giacomos-bookshelf
no-outbreaks@
@@ -14597,7 +14597,7 @@ cafes-birding@
kafs-valentine-special@
create-deepfried@
sleepable-create
-create-railways-navigator@
+create-railways-navigator@|机械动力:铁路导航*
speed-drifter@speed_drifters|MC飞车 (MCSpeed)
rearmour
@@ -14622,12 +14622,12 @@ create-optical
mob-battle-music@|战斗音乐*
-
+@concerto|协奏曲/一起听 (Concerto)
@invisible-frames-for-forge
-factions-and-curiosities@
+factions-and-curiosities@|派系与奇遇*
@anyfps
-@create-amazing-trading
+create-amazing-trading@
westeroscraft-worldeditcui
@@ -14645,7 +14645,7 @@ back-up-beds@
-
+mountain-sea-and-continent-two|山海大陆2 (Mountain Sea and Continent Two)
vinery-tfc
tkbs-campfires
@@ -14671,11 +14671,11 @@ better-one-block|更好的单方块*
the-fletching-table-mod@
@create-militarized
-
-sword-soaring|御剑飞行*
+customemoji|自定义表情 (CustomEmoji)
+sword-soaring|史诗战斗:御剑飞行 (Epic Fight - Sword Soaring)
bigger-ae2@
scalar
-trials-towers@|试炼高塔*
+trials-towers@|试炼高塔 (Trials Chambers)
blus-sign-pack-mts-iv
alexs-mediumcore@
sherdsapi@
@@ -14703,12 +14703,12 @@ marbleds-api-mapi@
magma-bucket|岩浆桶*
ropes
paniclecraft
-cpmpvc@|自定义玩家名称Plasmo语音兼容 (Customizable Player Models Plasmo Voice compat)
+cpmpvc@|自定义玩家模型Plasmo语音兼容 (Customizable Player Models Plasmo Voice compat)
ydms-gunblades-mod@ydms-gunblades
warp-pads@warppads
marbleds-arsenal@marbledsarsenal
@inventory-tabs
-mob-spawning-fix
+mob-spawning-fix|生物生成修复*
lh-miracle-road|奇迹之路之魂系加点 (LH Miracle Road)
compatskills-fork
@@ -14716,7 +14716,7 @@ reskillable-fork
@subtick
electroblobs-wizardry-continuation|巫术学:延续 (Electroblob's Wizardry Continuation)
-agricraft-continuation
+agricraft-continuation|农业工艺:延续*
create-nuke@
egg-particle-fix|鸡蛋粒子修复*
chicken-chunk-patcher
@@ -14725,16 +14725,16 @@ achievement-detection-fix|成就检测修复*
@chais-inventory-sorter
-
+@mysteriumlibunofficial
witcherypatch@|巫术补丁 (WitcheryPatch)
pin
simple-pings@
-great-scrollable-tooltips
+great-scrollable-tooltips@
waterframes@
eugenes-whistle-spur|友止殷的马哨和马刺 (Eugene's Whistle & Spur)
-
+quickquark|畅启速始 (QuickQuark)
minecraft-mineralogy
seed-delight|种子乐事*
transmog@|幻化*
@@ -14749,8 +14749,8 @@ stewing-baking@|炖与烤 (Stewing & Baking)
am2playground@
@astrocraft
-neat-shaders-fix@|极简血量显示 - 光影修复 (Neat - Shaders-Fix)
-worldtooltips-shadersfix@|掉落物信息显示 - 光影修复 (WorldTooltips - ShadersFix)
+neat-shaders-fix@|极简血量显示 - 光影修复版 (Neat - Shaders-Fix)
+worldtooltips-shadersfix@|掉落物信息显示 - 光影修复版 (WorldTooltips - ShadersFix)
options-enforcer@
macaws-bridges-biome-o-plenty@|Macaw的桥梁:超多生物群系附属 (Macaw's Bridges - Biomes O' Plenty)
@@ -14758,10 +14758,10 @@ renhider@
itemframeremover@|物品展示框移除器 (ItemFrameRemover)
@legacy-debug-pause
trick-or-treat
-ninjin-entities-by-hedaox
+ninjin-entities-by-hedaox@ninjinentities
dangerrpg-continuation@|危险RPG:延续 (DangerRPG Continuation)
zelda-sword-skills-continuation@|塞尔达剑技:延续*
-@forgotten-relics-unofficial|失落遗物学:非官方 (Forgotten Relics Unofficial)
+@forgotten-relics-unofficial|失落遗物学:非官方版 (Forgotten Relics Unofficial)
mc-mods-enhanced|截图增强 (Screenshots Enhanced)
the-rings-of-power@|力量之戒/魔戒众戒 (The Rings of Power)
@@ -14774,10 +14774,10 @@ ivtoolkit-arcana-rpg-continuation-edition|IvToolkit:延续 (IvToolkit Arcana R
@byzh-picgen|byzh's 麦块画图 (BYZH's Picgen)
tropicraft-continuation|热带世界:延续*
battle-tower-continuation|战斗高塔:延续*
-kswitch
+kswitch@
tfc-lumberjack
tfc-better-stone-tools
-protons-additions
+protons-additions@
kinetic-anti-cheat@kac
where-are-the-ores@
underp-hangables@
@@ -14786,7 +14786,7 @@ mod-observer@
mineralogy-continuation@
ubc-ore-registrar|科学地质:矿石注册 (UBC Ore Registrar)
genesis-2d|创世纪 (Genesis)
-
+@non-update-reloaded|不再有更新重制版 (NonUpdate Reloaded)
radiation-zone|辐辽地带*
adventure-backpacks-patched|探索者背包:延续*
@@ -14795,16 +14795,1290 @@ adventure-backpacks-patched|探索者背包:延续*
bhops@
from-spores
just-dire-things
-hit-feedback|攻击反馈*
+hit-feedback@|攻击反馈*
@hasoook
middle-earth@|中洲 (Middle-earth)
windows-keyboard-fixes-fixes-sticky-keys@|Windows 键盘修复 - 粘滞键 (Windows Keyboard Fixes - Fixes sticky keys)
statuesmod-fix@statuesmodfix|雕像模组-修复 (StatuesMod Fix)
@numericaltabping
-
+ninjinentities-unofficial@|Ninjin Entities-非官方版 (ninjinentities-Unofficial)
sanguine-arsenal-reforged|血染武装重铸版*
-respawn-obelisks
-flintandsteel-improve
-forge-zombie-plague-mod-2-wip@zombie-plague-2-hardcore-zombie-apocalypse
+respawn-obelisks@
+flintandsteel-improve@
+forge-zombie-plague-mod-2-wip@zombie-plague-2-hardcore-zombie-apocalypse|僵尸瘟疫2 (Zombie Plague 2)
colored-grasses
-more-default-options
\ No newline at end of file
+more-default-options
+@livelydanmaku|缤纷弹幕
+
+treecapitator-updated|砍树更新版*
+@offhandlights|副手光源 (Offhand Lights)
+keep-your-mouth-healthy|保持口腔健康*
+prehistoric-nature-jurassic-dimension
+
+many-more-structures@¨many-more-structures-depricated@more-structures
+mobs-are-friends@
+polytone@
+@calcium-fps|钙 (Calcium)
+delightful-burgers@
+cinderloe-project
+lotweakr|魔戒微调 (LOTweakR)
+lotr-renewed-extended|魔戒:复兴-拓展 (LOTR: Renewed Extended)
+lotr-companions-renewed-addon|魔戒:同伴 (LOTR: Companions)
+dvs|自定义魔戒小建筑 (DVS)
+mffs
+lotr-extended|魔戒大陆拓展 (LOTR Extended)
+bitcrafting
+fart-shit-pee
+statuseffecthud-updated|状态信息显示更新版 (StatusEffectHUD Updated)
+capejs@
+advanced-machines-patcher
+@immersive-tooltip|沉浸式的工具提示 (Immersive:Tooltip)
+
+sound-controller|Sound Controller - 已弃用¨@sound-controller
+cagerium
+advanced-inventory-mod@
+rolling-down-in-the-deep@
+dwarven-realm|矮人诸国*
+renewed-eras-of-arda-addon|阿尔达纪元:复兴 (Eras of Arda: Renewed Addon (First and Second Age))
+legendary-item@|魔戒传说物品*
+lotr-middleearth-tweaks|中洲微调 (MiddleEarth Tweaks)
+thaumcraft-integration
+reach-display@
+gravitation-suite-patcher
+anti-rat-dungeon
+modchu_defaultmodelset
+create-storage@fxnt-create-storage
+avaritia-item|无尽特效物品*
+kingdom-of-rin-regions
+durability-speed-legacy-backport
+inventory-on-death-mod
+berries-cherries-delight@berries-and-cherries
+silents-delight@|幽匿乐事 (Silent's Delight)
+darwin-sprinting-system|达尔文疾跑系统*
+camera-overhaul-reforged@
+monolib@
+@pyrofrost
+animal-armor-trims@
+
+better-safe-bed@
+modchu_models
+ice-and-fire-spellbooks@
+exlines-fishing@
+cavernous-delight
+@steep-surface-fix
+
+arthropocolypse@
+@kaleido
+
+
+combat-skill|战斗技巧*
+life-is-precious|生命是宝贵的 (Life is precious)
+
+advanced-skills@|进阶技能*
+nuts-delight
+@vegetables-delight
+enderpack@
+ingame-mod-configs|游戏内模组配置 (InGame Mod Configs)
+playertag|玩家标签 (PlayerTag)
+hide-names|隐藏名称*
+camo-suits|迷彩套装*
+vtubruh-lotr-mobs-new@vtubruh-lotr-mobs|Vtubruh的魔戒生物 (vtubruh LOTR Mobs)
+
+
+@create-more-features
+armadillo-scute-armor@
+new-shield-variants@
+
+
+way-much-faster-oxidize-reborn@
+bn-blood-particles@
+bn-weapons@
+ecotones@
+froglins
+create-armor-trim
+slashblade-resharped@|拔刀剑:重锋 (SlashBlade: Resharped)
+spawn-mod@
+@smooth-swapping-1.20.4-port
+@create-tab-fix
+@srp-origins
+origins-extra-keybinds@origins-extra-keybinds-fabric
+epic-knights-addon
+
+@arknights-skadi-orca-plushie|【明日方舟】斯卡蒂的虎鲸抱枕 ([Arknights] Skadi Orca Plushie)
+sona-survival-101|唢呐生存指南*
+@more_villagers
+cult-of-the-wither
+clochetweaks
+
+
+@multiproto
+frostbytes-improved-inventory@
+mekanism-extras@mekanism_extra|通用机械:扩展*
+leaf-beds@
+unidentified-enchantments@unidentified_enchantments
+protection-pixel@|机素防护*
+
+
+createdpcompat@
+
+lava-waterblock
+
+constant-music@
+supercore
+extreme-reactors-create-compat
+modchu_playerformlittlemaid
+totally-lit@
+mo-shiz-mod
+aetheric-tetranomicon
+
+arda-addon|阿尔达拓展*¨lotr-arda|阿尔达拓展 (Arda Addon) - Snow的阿尔达拓展
+@potionwarning
+a-good-place@
+aether-protect-your-moa@
+advanced-rocketry-2
+compostimprove@
+superb-steeds@
+coal-piece
+
+
+@mechmonstrosity|机械巨兽 (MechMonstrosity)
+slash-illager@
+@create-spawnerboxer
+skeletalband|骷髅乐队乐谱 (SkeletalBand)
+alexs-caves-entropy|Alex 的洞穴:熵 (Alex's Caves:Entropy)
+mekanism-explosives|通用机械:炸药*
+@minimal-coords-hud
+
+
+
+avaritiareborn@|无尽贪婪:复兴 (AvaritiaReborn)
+cherry-shrimp@
+pick-command@|俺拾的指令*
+regalliv
+extra-addition-s@extra-additions
+
+@amethyst-shield|紫水晶盾 (Amethyst Shield)
+@plateplate|板板 (PlatePlate)
+
+
+@difficulty-tweak|难度调整 (Difficulty Tweak)
+
+@herbal-delight
+
+
+@compatlib
+warriors-of-past-epoch
+the-ghast-cow@
+@alternate-current-unofficial
+birds-on-a-wire
+no-hurt-animation
+incense
+wild-lands-2
+hullabaloo@
+invinci-dogs-ssp
+@noglow|禁止发光 (noglow)
+timeless-and-classics-zero@|永恒枪械工坊:零 (Timeless and Classics Zero)
+
+@concentration|专注 (Concentration)
+terra-curio@|泰拉饰品*
+
+cobblemon-counter@
+cobblemon-move-inspector@
+cobblemon-spawn-notification@
+cobblemon-pokenav@
+cobblemontrainers@
+the-ink-arena@
+
+epicfight-integration|史诗战斗·集成 (EpicFight Integration)
+@stop-spiders-from-climbing
+kubejs-enderio@
+polymorphic-energistics@
+war-of-the-ring-mc|魔戒大战 (The War of the Ring MC)
+redstone-clock-mod@|红石钟 (Redstone Clock)
+create-cobblestone@
+@another-pickaxe
+@selfexpression
+electricalcraft
+@elecfurn
+what-is-stone-colorful-caves@what-is-stone-(colorful-caves)
+vtones
+heavy-inventories|物品负重*
+vs-addition@
+gravity-torch
+lifesteal-forge-fabric@
+mores-by-its-infinite
+dragonite-gear
+lets-do-addon-fluids@
+
+
+@just-glowing-buttons
+rats-hats
+biome-reactors
+mystical-agriculture-tiered-crystals@
+tpaplusplus@tpa++
+warlerys-hq
+call-of-yucutan@|尤卡坦的呼唤 (Call of Yucatán)
+redman@|红超人
+lets-do-addon-compat@
+
+worldeditcui-forge-edition
+slime-delight|粘液乐事*
+darkcap@
+@ryoamium
+quality-equipment
+seals
+nocubes-better-smoker
+@shutdown-on-death
+mekanism-energistics
+ae2-network-visualiser
+ahznb-sword-plus
+anbu-bingo-book-for-ahznbs-shinobicraft
+ahznbs-naruto-mod-reroll
+xycraft-override
+xycraft-machines
+xycraft-world
+battlemusic@
+
+@embyui
+engineered-golems
+axifier@
+renderjs
+@enchantment-compat
+dehand@
+jadecolonies
+@cobblemon-mike-skills
+diamond-star-combat
+modern-ae2-additions@
+create-metallurgy@|机械动力:冶金学 (Create: Metallurgy)
+@client-info-fix
+the-shy-guy
+@tea-time
+@cobbreeding
+@cobblemon-myths-and-legends-addon
+@rctmod
+create-klinks-n-klangs@klinksnklangs
+mo-than-enough-guns@
+
+forge-creeper-heal|Forge 苦力怕坑修复*
+
+
+@momos-skiphand|莫莫的折跃之手 (Momo's SkipHand)
+curse-of-disintegration
+adventure-backport|冒险模式向后移植*
+@oreganized-refabricated|井然有矿:重织 (Oreganized Refabricated)
+yosby
+@zundamod
+common-network@
+addurdisc@|自定义唱片 (AddurDisc/Add your disc)
+enigmatic-addons|神秘遗物扩展*
+
+@bloodscythe
+dungeons-delight@
+stronger-potions@|更强的药水*
+
+
+@particular
+
+reforgedplay-mod
+sqript
+natures-delight@|生灵乐事 (Nature's Delight)
+reimagining-potatoes@
+@legacy-resource-pack-adapter
+insane-stamina
+bren@
+@power-hud
+plushables@|毛绒玩偶*
+
+
+
+@rcspeedbuild
+@staff-of-the-king-orange|橙王的权杖 (Staff of the King Orange)
+
+path-under-gates
+ojs-guilds
+command-macro-key@|命令宏键*
+realm-rpg-quests-rewards
+@roadworks
+unlucky-tnt@
+fastboot@
+
+tardis-refined@
+ocean-villager-trader@
+@precise-manufacturing|机械动力:精制工艺 (Create: Precise Manufacturing)
+@create-new-age-alexs-caves-integration
+create-kryeit@
+animationoverhaul@
+starbunclemania
+
+
+display-qien@
+@village-healthcare
+cubic-villager
+@morecursors|更多光标 (MoreCursors)
+true-infinity
+nukateams-gun-lib@ntgl
+fantastic-biomes-cave@
+nukacraft@thenukacraft
+enchantment-limiter
+emi-ores@
+@bread-skin-mite|面包皮 (Bread Skin)
+extra-gore
+chassiscore@
+@spit-splat-fabric
+@moderation
+normalcore@
+appliede@
+waystones-teleport-pets@
+@sneaky-link
+create-mortar@
+forgelin-continuous@
+@ripples-of-the-past-killer-queen-addon
+ninjin-knockback-dbc-by-hedaox
+wings-3
+dstathud@
+opticmanager@
+ribbits@
+@actually-camel
+
+
+
+raws-visual-keybinder
+
+
+@scoreboardtweaks
+rsinfinitewireless
+rustic-engineer@
+artsandcrafts@
+mermaid-legend|人鱼传说*
+endcake|末影蛋糕 (EndCake)
+
+@mcsudo
+
+scp-remake
+@scp-fallen-foundation
+
+create-heat-js@
+createaddoncompatibility@
+more-difficulty-levels
+alternacraft
+sheep-squeak@
+fabric-simple-animated-guns
+a-v-a-in-minecraft@a.v.a-alliance-of-valiant-arms-guns
+coordinates-display@
+@acrylicraft|亚克力窗口 (AcryliCraft)
+towelette@
+shc-pvz-zengarden@
+unusual-foods-delight|奇食乐事 (Unusual food's Delight)
+re-fruitful
+dark-rites-2
+advitam-addon-for-requiem@memento-mori
+potheads
+
+skyfall-meteorites@
+fancyclear
+pathfinders-spade
+legacy-minecraft@legacy4j
+festive-creepers
+essential-features
+piston-control-forge¨piston-control
+
+blahaj-restitched@|布罗艾重制版*
+@tabbychat-2-reforged
+lithostitched@
+pogfish
+launch-time@|启动耗时*
+killer-table
+trading-table
+winter-decorations
+fancy-snowy-weather
+winter-ambience
+dralards-rock-candy-mod
+
+
+
+@explosion-breaks-no-block|爆炸不破坏方块 (Explosion Breaks No Block)
+via-romana@
+lithic-coins|石质硬币*
+dynamic-trees-for-natures-spirit@|动态的树:自然之灵附属 (Dynamic Trees for Nature's Spirit)
+gore-edition
+christmas-wish-in-a-bottle
+chiseled-bricks
+unethly-origin@
+dimensional-totem@
+placeable-gunpowder
+library-for-ar-reworked
+
+
+
+
+craftdev-core
+costume
+
+borzoi-dogs@
+
+nether-exorcism@nethers-exorcism
+integrated-villages@
+taxdeepvillager
+@voxelprints-desert
+music-on-demand
+leadable-bats
+canes-wonderful-spiders
+
+
+@scribble
+@text-formatting-everywhere
+extended-item-information
+mod-sound-volume-options@mod-volume-options
+
+teams-hud
+@tpm|传送管理器 (TeleportManager)
+@camera-obscura
+wzorescanner
+@potion-recipes
+wither-totem@wither-skeleton-totems
+@player-bones
+
+more-apples-hyj|更多苹果 (More Apples)
+fancy-enchantments|奇异附魔*
+ash-of-sin-adventure-dimension|罪业余烬:冒险维度 (Ash Of Sin: Adventure Dimension)
+push-forward@|猪突猛进*
+ymn@|你现在是我的了! (You're Mine Now!)
+thermal-endergy@
+mekanism-turrets-fences
+nuka-cola-classic
+draconic-machinery
+@voxelprints-halloween
+iap-gobber@
+iap-botania@
+iap-industrial-foregoing@
+iap-silents-gems@iap-powah
+
+iap-omega-craft
+iap-mekanism
+industrial-agriculture-plugin-silents-mechanisms
+
+roads-and-roofs-tfc
+taxvillagearchitect
+taxoceanarchitect
+nethers-flora
+
+microcosm
+chinese-flying-island-tower
+@netherite-tools-for-crackers-witherstorm-mod
+better-maces
+jack-o-launcher
+the-otherworld-mod
+craftingxp@
+
+dmmttba@
+fzzy-config@
+no-shield-delay@
+musicpower@|音乐之力 (MusicPower)
+macrocraft@
+camerapture@
+simple-voice-radio@
+
+adorned
+fence-on-slab
+monochromatic-blocks@
+
+
+
+
+@inventiveinventory
+boxlib@
+mokels-bossfight-saphyra
+resource-explorer@resource_explorer
+@patcher
+autoreconnectrf@
+disable-accessibility-screen@
+@fly-high
+
+@fly-apple|飞苹果 (Fly Apple)
+
+@hoyoi
+rogues-and-warriors@
+
+
+
+@tfc-support-indicator
+tfc-poisoned-drinks
+smartercontraptionstorage|智能动态结构存储 (SmarterContraptionStorage)
+lexiconfig@
+
+@advancementsfullscreen
+luckys-wardrobe@
+@forkkit
+@more-affordable-than-ever
+what-am-i
+
+@camoverlay
+autoplant
+@skip-backup-screen
+@polysprint
+@crashpatch
+@vanillahud
+@damagetint
+@polyblur
+@colorsaturation
+@hitbox
+lains-random-creation|LAIN的随意创作 (Lain's random creation)
+autochefs-delight@
+
+bindcommands@
+short-grass@
+stairs-but-chairs@
+@yumo-compactmachines-por|压缩空间:产量推演 (yumo compactmachines por)
+dynamic-trees-for-fruit-trees|动态的树:妙趣果园 🍊附属 (Dynamic Trees for Fruitful Fun 🍊)
+dynamic-trees-for-better-end|动态的树:更好的末地附属 (Dynamic Trees for BetterEnd)
+dynamic-trees-autumnity|动态的树:秋原附属 (Dynamic Trees - Autumnity)
+dynamic-trees-for-bloomingnature|动态的树:BloomingNature附属 (Dynamic Trees for BloomingNature)
+dynamic-trees-terralith|动态的树:Terralith附属 (Dynamic Trees - Terralith)
+dynamic-trees-for-meadow|动态的树:青青草甸附属 (Dynamic Trees for Meadow)
+dynamic-trees-for-beachparty|动态的树:沙滩派对附属 (Dynamic Trees for Beachparty)
+dynamic-trees-for-vinery|动态的树:葡园酒香附属 (Dynamic Trees for Vinery)
+tfc-aesthetics@tfc-plus-aesthetics
+smooth-gui@
+offershud@
+perspektive@
+ore-harvester@
+flightassistant@
+biomefog@
+edgeless-chat-screen@|无边界聊天框*
+villager-death-messages@
+@smooth-skies
+clist@
+tothestarsremake@
+galacticraft-gravity
+dragon-mounts-even-more-dragons|龙骑士附属:附加龙 (Dragon Mounts: Even More Dragons)
+xplus-contingameime@|游戏内输入法 XPlus 版 (XPlus ContingameIME)
+@watersource2|水源 2 (Water Source 2)
+radomraidspawn|随机袭击生成 (Random Raid Spawn)
+enigmatic-legacy-legacy|神秘²遗物*
+
+nco-java-legacy-lib
+forge-souls-like-universe@souls-like-universe
+
+
+
+neutral-animals@
+create-upgraded-armor
+fbp-renewed@
+chat-impressive-animation@|聊动魅影*
+
+pianocraft@
+jazzymusicality@musicality
+@boids
+buckshotroulette@|恶魔轮盘赌 (BuckshotRoulette)
+customnpcs-unofficial@
+@fast-trading
+simple-wooden-pipes
+simplywalk@
+persistent-stuff@
+lan-operators@
+compatdatapacks@
+the-luminous-mod@
+
+
+@burst-door-open|破门而入 (Burst Door Open)
+
+
+chain-suspension-forge@chain-suspension¨chain-suspension
+cui@
+emi-enchanting@
+clientsort@
+immersive-ui@
+
+curios-continuation@
+@minekimi
+blind-accessibility@minecraft-access
+enchanting-tree@enchantingtree
+dragon-enchants
+item-placer@
+expandedworld
+monster-hunter-villager@
+jcraft-eyes-of-ender
+@return-dirt-background
+
+@reset-keys-confirmation-screen
+idle-boost@
+fabricbettergrass@|更好的草地 (FabricBetterGrass)
+@lightweight-inventory-sorting
+@stonecutter-gui-remastered
+@loom-gui-remastered
+@unseaworthy
+@chromaanvils
+thermal-and-space@
+create-curios-jetpack
+epic-knights-antique-legacy
+viking-samurai-knight-items
+barely-simple-staffs@barely-simple-staff
+
+
+alexs-caves-delight@
+alexs-caves-adventure@
+divine-weaponry
+
+hook@hoook|抓钩*
+fix-guard|格挡修复 (FixGuard)
+@greg-caves|格雷的洞穴 (Greg Caves)
+better-mob-combat@
+mob-player-animator@
+depression@|抑郁症*
+more-rpg-classes@
+minimalism-leaf-decay@minimalism_leaf_decay|极简快速落叶*
+biome-modifier-for-fabric@|Fabric版群系编辑器 (Biome Modifier for Fabric)
+chunkloader-simple
+apollyon
+worldweaver@
+netherite-compass@
+the-darkness-will-find-you@
+silent-screenshots@
+cr3stal-updatet@crestal
+toggle-subtitles@
+ok-boomer-zoom@ok-boomer
+
+@forcegl2.0-remapped
+
+rendi@|重生:伤害免疫机制移除 (ReNDI)
+create-questing@
+@create-train-perspective
+elainalike@|魔女之绘 重生:重生 (ElainaLike Reborn:Reborn)
+take-back-your-sword@|收回你的剑!*
+
+
+
+travel-friendly-food-fabric-forge@travel-friendly-food
+stardew-valley-food@
+minecolonies-compatibility
+bettergamma@
+more-lectern-variants@
+@ase
+lush-cave-trader@
+oceans-enhancements@
+xp-jellies
+aromatic
+onekeyminerforge|一键连锁Forge版 (OneKeyMinerForge)
+
+retargetato@|约谊敌众 (ReTargetato)
+iceandfire-fabric@|冰火传说Fabric版 (IceAndFire Fabric)
+tomanos-vehicle-mod
+ancient-sands@
+hs-bosses
+chubby-mobs
+repair-gem|修复宝石*
+better-weaponry-compatible-with-better-combat
+disable-front-perspective@
+
+
+thaumcraft-6-aspects-for-jei@
+@up-and-away
+
+@ripples-of-the-past-hermit-purple-addon
+nc-steam-additions@nuclearcraft-steam-additions
+aura-cascade|气场流注*
+rac-compat@
+spartan-weaponry-addon-toolkit@
+
+sneaky-tree-growing-forge@sneaky-tree-growing¨sneaky-tree-growing-fabric
+hungry-zombies
+@gravity-gourds
+usa-delight
+experience-farm
+@ad_extendra-continuation
+nebulus-juice-trader@
+cthulhu-fishing@
+large-super-potato|大型超级马铃薯*
+@craft-time
+the-orcs
+made-in-abyss-shroombears
+squinkers
+mokels-bossfight-kinora
+@create-high-pressure
+create-framed@
+trackwork@
+oritech@
+the-impossible-library@
+perspective-mod-redux@
+more-cartography-tables@
+more-barrel-variants@
+wheelbarrow@
+simple-automation
+better-paragliders@
+fallen-wizards-more-magic-series@
+
+@whiffowisp
+mango-cats
+tax-tree-giant
+taxskyvillager
+compostable-rotten-flesh
+villager-in-a-bucket@
+nebulus-trader-for-the-desert
+nebulus-jungle-trader@nebulus-trader-for-the-jungle
+mushroom-villager-trader@
+nebulus-better-portals@
+resource-ghouls
+
+create-legacy@
+@create-bronze-age
+wind-bottle@|风瓶 (wind bottle)
+lc-tech@
+minecolonies-tweaks
+text-placeholder-api@placeholder-api|文本占位符 API (Text Placeholder API)
+@gravity-api-fork
+
+@tt20
+
+
+
+kubejs-mekanism-unofficial
+@mediaplayer|媒体播放器 (MediaPlayer)
+bakery-villager-trader
+nebulus-trader-for-the-plains
+mokels-more-spiders
+
+exposure-catalog@
+skinchanger
+
+@halflifemenu
+sitting@sitting+
+forgotten-east@
+brazil-legends
+
+custom-item-despawn-duration@|自定义掉落物消失时间*
+your-items-to-new-worlds@
+enhanced-boss-bars@enhanced-boss-bars-mod|更好的Boss血条*
+cutetrade@
+
+smoothmenu-refabricated@|平滑菜单:重制版 (SmoothMenu Refabricated)
+
+toexistingstacks|添加到现有堆叠 (ToExistingStacks)
+@postmortal-particles
+@give-me-a-new-splash-text
+@less-annoying-fire
+treasuredistance
+affinity@
+chaos-moon
+@healthindicator
+
+@auto-sprint-fix
+lets-do-emi-compat@
+health-indicator@health-indicators
+aiming-fix@
+compasshud@|指南针HUD (CompassHUD)
+mini-boss-boss-bars@
+berserker-rpg-class@
+fromanotherlibrary@
+mounted-pearl-bring-your-mount-along-when-you
+biome-id-fixer
+immortal-coral@
+immersive-guns@
+
+additional-rpg-jewelry@
+mekanism-ad-astra-ores@
+question-ducks-ambient-fireflies
+travelerz@
+the-rise-of-minerals|矿石崛起*
+gregtech-steam-additions
+gregtech-nomifactory-edition
+create-ethium
+create-contraption-terminals@
+
+strata-recipes
+strayed-fates-forsaken
+snowyleavesplus@
+shield-overhaul@
+g-weapons-mod-gargantuan-weapons-mods|G武器 (G-Weapons)
+backtools@|工具后置/后背工具展示:重制版 (BackTools)
+epic-fight-guandao-moveset|史诗战斗:关刀 (Epic Fight - Guandao Moveset)
+epicfight-dual-greatsword
+spell-checker@
+sparkle@
+@visible-traders
+villagers-inventory
+removehud@
+@orthocamera
+third-person-crosshair-fabric
+@hitrange
+black-moon@
+dynamic-fire-overlay@
+firorize@improved-fire-overlay
+smoke-extender
+@nohotbarlooping
+@higher-chat
+mekanism-cardboard-tooltip@
+durability-notifier@
+gregtech-extended-chemistry
+centrifuge-tiers
+distant-friends@
+the-world-of-herobrine
+primal-storage@primalstorage
+@potioncorereloaded|药水核心重制 (PotionCoreReloaded)
+yamazakura-reforked|山樱之刃重置版 (Yamazakura reforked)
+
+
+apothic-spawners
+
+sinocore|华夏核心 (SinoCore)
+tinted-dyes@
+dynamic-trees-ecologics@|动态的树:丰富的生态附属 (Dynamic Trees - Ecologics)
+craftablecapes@|可合成的披风 (Craftable Capes)
+tamago@
+@clickthrough2.0
+cat-jammies-fabric@cat-jammies
+open-computer-resurrected
+@advancements-reloaded
+oc2r
+eu-p2p-tunnel@eup2p|EU能源P2P通道 (EU P2P Tunnel)
+@hold-onto-everything
+ardagrass@
+geocluster@
+
+@knives-construct
+
+updating-world-icon@
+shared-resources@
+tech-dimension@
+tilt-break@
+item-frament@
+water-vision@
+randomized-default-fireworks@randomizeddefaultfireworks
+glowing-torchflower@glowing-torchflower#all-versions
+@clock-hud-renew
+cameranoclip
+barriers-dont-block-rain@
+no-render
+
+runningshoes|跑鞋 (Running Shoes)
+fluid-void-fading@fluidvoidfading
+@movement-in-gui
+glowing-eyes@glowing-eyes#all-versions
+youarch
+true-darkness-fabric@
+esf-entity-sound-features@esf|实体声音特性 (Entity Sound Features)
+nomoreglowingpots@
+smooth-particles@
+
+5544292@unloaded-activity
+@improperui
+neverenoughanimation
+reds-stagger-parry
+additional-placements@¨additional-placements-fabric@
+akicaters-shelves@akicaters-shelf-mod
+refurbished-furniture|MrCrayfish 的家具:重制 (MrCrayfish's Furniture Mod: Refurbished)
+improved-stations-forge¨improved-stations¨improved-stations-for-1-19
+elemental-wizards-rpg-class@elemental-wizards-rpg
+pov-that-one-short-friend
+onward-and-upward
+weapon-case-loot|武器箱战利品*
+mace-but-3d@
+@healthindicators
+smoothcoasters@
+do-a-flip@
+@no-death-animation
+veindigging@
+too-many-entities@
+
+
+
+
+datapack-breakpoint@datapack-debugger|断点调试 (Datapack Debugger)
+
+
+frosted-heart|冬季救援:寒霜之心 (The Winter Rescue: Frosted Heart)
+create-planetary-tweaks@cp-tweaks
+entris@
+@sushi-bar
+lumi@lumi1710
+pet-the-frog@frog-petting
+ex-nihilo-extras@
+cycle-title-screen-splash@
+hide-invisible-armor@
+inventory-tweaks-refoxed
+bigshot@
+more-immersive-aircraft
+legendary-survival-overhaul|传说生存*
+mineral-delight
+not-just-sandwich@notjustsandwich
+fantasyfood|幻想食物 (FantasyFood)
+mc-modsthefood@allthefood
+villager-names-fabric@villager-names
+trial-vault-restock@trialchamberrestock
+hot-green-fire
+phantom-flames
+darktitlebar@
+cubes-without-borders@
+block-parry-dodge
+fargos-enchantments
+toostrongmonster
+simplystronger
+tacz-durability
+bigger-lightning-storms
+eternal-limbo
+legoman
+petcreepers-mod
+tugkandemans-weaponry@
+
+
+
+
+
+
+
+@noanysus
+rekusaeater@|Re艹 (ReKusaEater)
+jsg@
+@potion-mixing|药水混合 (Potion Mixing)
+sandfilter@|砂滤器 (Sand Filter)
+resaplingslayer@|雁雅得枝 (ReSaplingslayer)
+cerberu@|狱牙抵战 (Cerberus)
+remoreloyaltrident@|远亦得珍 (ReMoreloyaltrident)
+potionlevelfix@|药引对注 (PotionLevelFix)
+reunmending@|以验垫砧 (ReUnmending)
+reghostjump@|引殃髑至 (ReGhostJump)
+rebroken-blade@|隐影刀珍 (Mowzie's Mobs: ReBroken Blade)
+attackagain@|又御刀追/追击 (AttackAgain)
+@sectionsign
+@allow-chat
+retro-damage-indicators@
+@impropers-3d-minimap
+beddium@
+create-thermal-compat
+create-lagless@
+create-ironworks@
+@create-vibrant-vaults
+steam-power
+kevs-library@
+remove-purpleprison-ads
+timeoutfixes
+forgeskyboxes@
+
+
+crust@
+
+sc-structurecraft@structurecraft
+minehop@|Minehop - 主¨minehoplite@
+placeabletools
+rlfoliage@
+bc-remastered
+@deepdrilling
+copperworks
+
+
+miner-villager
+villager-venture
+alekiships@
+alekishipsbop@
+antique-trading-ship
+small-horse-stable
+shrek-the-ogre@shrek
+
+the-anomaly
+desert-behemoths-sandworms
+
+vermintide-rising
+armor-of-the-ages@|时代铠甲 (Armor of the Ages)
+
+
+
+@betterf3-stationapi
+ftb-quest-localizer|FTB Quest 本地化 (FTB Quest Localizer)
+modpack-update-checker@
+minimotd-fabric
+effecttimerplus@
+thaumic-concilium@
+equivalentexchange
+
+coral-up@
+plushie-buddies@
+@the-aethers-delight
+@wheelchairs
+dnt-pillager-outpost-overhaul
+mage-flame@
+@totem-party-popper
+@powerless-refined-storage
+forgotten-graves@
+day-zombies
+morecoal|更多煤炭
+jjku
+
+immersive-combat-feathers
+ghosties-monocle
+ender-dragon-loot
+
+oh-the-trees-youll-grow@
+oh-the-biomes-weve-gone@|我们走过的生物群系 (Oh The Biomes We've Gone)
+@dblockbusterdisplays
+
+
+@waygl
+no-sneaking-over-magma@
+harmonia@wasabiwhisper-harmonia
+configurable-head-drop@
+@connectored-c2me-(c2me-fork-for-connector)|C^3M 引擎 (Connectored Concurrent Chunk Management Engine)
+structure-expansion@
+armored-doggo@
+the-newest-goatman
+epic-mob-siege-nightmare
+jupiter@
+airport
+just-dandy@
+@uk-roads
+my-totem-doll@my_totem_doll
+
+
+dis-enchanting-table@
+
+
+gt-top-addition|格雷信息显示拓展 (GT TOP Addition)
+gt-steam-tech|格雷蒸汽科技 (GT Steam Tech)
+simpleanimator¨@simpleanimator
+tianjin-metro@|天津地铁*
+modular-flower-pots|模组化花盆*
+repurposed-structures-floralis-compat-mod|结构变体:Floralis 兼容模组 (Repurposed Structures - Floralis Compat Mod)
+
+balanced-shield@
+@more-potion-effects|更多药水效果 (More Potion effects)
+jungle-villages
+truecherry
+@revamped-trades
+creeper-fireworks@creeper-fireworks-mod|烟花苦力怕 (Creeper Fireworks Mod)
+@word-overflow
+chatnotify@
+
+nbt-tool
+
+
+
+
+dglab-x-minecraft@
+twintails|双马尾 (TwinTails)¨twin-tails|双马尾 (TwinTails)
+gt-wireless|格雷无线科技 (GT Wireless)
+forcejava21@|强制 Java21 (ForceJava21)
+blessings@|祝福*
+crafted-core@
+call-from-the-depths@|深渊召唤*
+@clover-fabric|四叶草Fabric版 (Clover Fabric)
+champions-unofficial|冠军/强敌再续 (Champions-Unofficial)
+aetherworks-refracted@
+eidolon-repraised@eidolonrepraised
+create-northstar@
+create-pattern-schematics@
+magic-merchant
+aether-villages@|天境村庄*
+tricky-trials@tricky-trials-1.21
+
+
+abilities-the-boys|黑袍纠察队 (abilities-the boys)
+
+
+better-creative-tabs-forge-neoforge|更好的创造标签页 (Better Creative Tabs)
+
+
+
+avaritia-unofficial
+stellaris@
+command-o-matic
+
+realistic-physics
+cia@|自定义物品属性 (Custom Item Attributes)
+item-wheel@
+data-attributes-directors-cut@
+better-walls@betterwalls
+the-pillager-legion
+the-frozen-kingdom
+stardew-fishing@
+lets-do-a-jumpscare@letsdoajumpscare
+
+
+the-quackening
+better-trial-chambers@
+coldsweat-tfc
+deeper-nether-biomes
+adventurers-beyond@
+mss-moogs-soaring-structures@
+goblins-tyranny@
+no-32768-limit|没有32768限制*
+
+
+
+
+reairdrop-supply@|空投供应:重生 (ReAirdrop Supply)
+@minequery|MC宝 (MineQuery)¨@minequery-legacy|MC宝 (MineQuery)
+
+@simply-create-model-mod|简单动力 (Simply Create Model)¨@simply-create-model|简单动力 (Simply Create Model) - 资源包
+mountains-poem
+@playtime-reborn|游戏时长计数器:重生 (Playtime Reborn)
+
+moon-between-medicine|在月亮之间:药学拓展 (Moon Between : medicine)
+craftable-chainmail-reborn|可制作的锁链甲:重生*
+
+thaumcraftfix|神秘时代6修复 (Thaumcraft Fix)
+
+extended-industrialization@
+small-tetra-additions
+lets-do-furniture@
+tesseract-api-neoforge@tesseract-api
+
+spectrelib
+
+tfc-artisanal
+
+@the-real-time|现实时间
+
+dragonoptifix|DragonBlockC 与 OptiFine 的兼容修复 (DragonOptiFix)
+@effortless
+@barriers-dont-block-rain-1.21
+
+@nochathide
+inventory-tweaks-extrafoamy
+automatic-infinite-elytra@
+re-translator@
+yank-it-out@
+vintage-kubejs@
+emi-professions-emip@emi-professions-(emip)
+grindstone-enchantments
+@starlight-legacy
+themetip@
+woodwalkers@
+peaceful-moon@
+to-tweaks-irons-spells@
+horde-moon@
+
+laser-mod-2
+mekanism-lasers
+wizards-reborn
+
+customnpc-contentback
+debug-stick
+useful-bat
+runic-inscription
+bamboo-stuff@
+@moai-update
+junk-drawers@
+playerex-directors-cut@
+lets-do-camping@
+@startuptime-unoffical|启动时间非官方版 (StartupTime Unoffical)
+serverconfig-updater
+@epiczoomer
+
+agenta@
+
+more-beehive-variants@
+
+persistent-creative-inventory@
+lets-do-wildernature@
+@quitconfirm
+@ressourcepackcommand
+
+neodymium-unofficial@nd1710|钕:非官方版*
+@carbon-performance|碳 (Carbon)
+coloredglowlib@
+@better-snow-coverage|更好的雪覆盖
+
+trade-enchantment-display@|交易附魔显示*
+eternal-starlight@|永恒星光*
+astral-patch|星辉补丁*
+fast-scrolling-fabric@fast-scrolling¨fast-scrolling
+galoblender-updated
+more-tetra-materials
+ageing-mobs
+warm-ice-block
+smoke-signals@
+wunderreich@
+
+ames-mobs-renew
+refreshdisplaylists
+vulkanmod-android-libs
+@black-bar-concealer
+building-shift@
+mob-ai-tweaks
+the-masquerade-illager-boss
+better-armory-x
+sweetys-horse-armor-tweaks@
+fired-pots@
+under-the-moon
+coffeegs-colorful-world
+jeb_-wool@|jeb_羊毛 (jeb_ Wool)
+illage-and-spillage-finally-ported
+more-runes-more-magic-series@|更多符文 (More Runes)
+battlemages-more-magic-series
+eidolon-rebrewed-data-recipes
+elemental-metals-magical-metallurgy-series
+dragonsteel-more-magic-series
+dragon-scale
+scholar@
+@elytraswimfix
+tacz-bullet-proof-enchant-add-on@¨tacz-bullet-proof-enchant-fabric-add-on
+no-screen-bobbing@viewbobbingmod
+more-spell-attributes-more-magic-series
+minos-particle-presets
+somewhat-hardcore-fabric-forge@you-die-you-lose-a-heart
+@blurred-window
+player-list-heads
+@antighost-fork
+environs-mod
+
+
+unique-magic
+
+
+epic-projectile-reflection|史诗弹射物反射
+zombie-island
+@stratagems
+solar-hardcore@
+i-hate-flesh-reborn-ihfr@i-hate-flesh-reborn-(ihfr)
+
+@particle-unlimit|粒子上限解除 (Particle Unlimit)
+aaa-particles@
+@anno
+compass3d@
+@clockin
+diggus-maximus-reborn
+satisfying-buttons@
+item-on-chest-fabric@item-on-chest
+industrialreborn@
+@ntmspace|HBM的核科技航天 (HBM's Nuclear Tech Mod Space)
+
+several-food-craft@
+cakes-cosmetics@
+boks-butterflies@
+@immersive-winds
+reef-redux@
+simple-quiver@
+too-many-paintings-forge-fabric@too-many-paintings
+building-but-better@
+exchange-fuels@
+more-craftings-of-runes
+mega-evolve
+pixeltweaks@
+hrbs-drills
+index-librorum-prohibitorum|禁书目录 (Index-Librorum-Prohibitorum)
+bft
+heartbond
+breakerplacer@
+iron-ladders@|更多梯子*
+crumbs-deepslate-button|Crumbs 的深板岩按钮 (Crumbs' Deepslate Button)
+
+cl0uds-paxels
+unique-weaponry
+
+boss-keys
+
+mace-variants
+shortswords
+bbs-mod@
+
+move-ui@
+terrafly
+achievements-mod-200@mysticrift-achievements
+
+saturation-plus
+mod-and-resource-pack-checker-abras-additions
+createstuffadditions-fix
+warden-slayer-enchantment
+mods-optimizer
+glowy-players-renewed@|玩家高亮:重置版
+
+epic-fight-kenjis-combat-forms
+mekanism-unleashed@
\ No newline at end of file
diff --git a/Plain Craft Launcher 2/Resources/java-wrapper.jar b/Plain Craft Launcher 2/Resources/java-wrapper.jar
index 7793ff9..29d7632 100644
Binary files a/Plain Craft Launcher 2/Resources/java-wrapper.jar and b/Plain Craft Launcher 2/Resources/java-wrapper.jar differ
diff --git a/README.md b/README.md
index d5b2391..8c12114 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
[](https://github.com/Hex-Dragon/PCL2/)
[](https://github.com/Hex-Dragon/PCL2/issues)
-[](https://afdian.net/@LTCat)
+[](https://afdian.com/@LTCat)
@@ -16,7 +16,7 @@ PCL 的代码绝大多数其实都是几年前学生时代的产物了……那
## 相关内容
- [PCL 功能投票](https://github.com/Hex-Dragon/PCL2/discussions/2):来参加投票吧,开发者会优先处理票数较高的帖子!
-- [程序下载](https://afdian.net/p/0164034c016c11ebafcb52540025c377):下载免费的正式版 PCL。
+- [程序下载](https://afdian.com/p/0164034c016c11ebafcb52540025c377):下载免费的正式版 PCL。
- [帮助文档库](https://github.com/LTCatt/PCL2Help):PCL 帮助文档在 GitHub 上的存储库(是的,帮助库在另一个 Repo……)
diff --git a/最新正式版.zip b/最新正式版.zip
index 22f5cc6..f4ca635 100644
Binary files a/最新正式版.zip and b/最新正式版.zip differ