This commit is contained in:
龙腾猫跃
2026-01-15 03:20:43 +08:00
parent 87f5cc2ea9
commit 52b4c87fbc
24 changed files with 530 additions and 2212 deletions
@@ -743,9 +743,9 @@ Public Module ModAnimation
''' <param name="AniGroup">由 Aa 开头的函数初始化的 AniData 对象集合。</param>
''' <param name="Name">动画组的名称。如果重复会直接停止同名动画组。</param>
Public Sub AniStart(AniGroup As IList, Optional Name As String = "", Optional RefreshTime As Boolean = False)
If RefreshTime Then AniLastTick = GetTimeTick() '避免处理动画时已经造成了极大的延迟,导致动画突然结束
If RefreshTime Then AniLastTick = GetTimeMs() '避免处理动画时已经造成了极大的延迟,导致动画突然结束
'添加到正在执行的动画组
Dim NewEntry As New AniGroupEntry With {.Data = GetFullList(Of AniData)(AniGroup), .StartTick = GetTimeTick()}
Dim NewEntry As New AniGroupEntry With {.Data = GetFullList(Of AniData)(AniGroup), .StartTick = GetTimeMs()}
If Name = "" Then
Name = NewEntry.Uuid
Else
@@ -788,7 +788,7 @@ Public Module ModAnimation
''' </summary>
Public Sub AniStart()
'初始化计时器
AniLastTick = GetTimeTick()
AniLastTick = GetTimeMs()
AniFPSTimer = AniLastTick
AniRunning = True '标记动画执行开始
@@ -798,9 +798,9 @@ Public Module ModAnimation
Log("[Animation] 动画线程开始")
Do While True
'两帧之间的间隔时间
Dim DeltaTime As Long = MathClamp(GetTimeTick() - AniLastTick, 0, 100000)
Dim DeltaTime As Long = MathClamp(GetTimeMs() - AniLastTick, 0, 100000)
If DeltaTime < 3 Then GoTo Sleeper
AniLastTick = GetTimeTick()
AniLastTick = GetTimeMs()
'记录 FPS
If ModeDebug Then
If MathClamp(AniLastTick - AniFPSTimer, 0, 100000) >= 500 Then
+42 -27
View File
@@ -14,13 +14,13 @@ Public Module ModBase
#Region "声明"
'下列版本信息由更新器自动修改
Public Const VersionBaseName As String = "2.12.1" '不含分支前缀的显示用版本名
Public Const VersionStandardCode As String = "2.12.1." & VersionBranchCode '标准格式的四段式版本号
Public Const VersionBaseName As String = "2.12.2" '不含分支前缀的显示用版本名
Public Const VersionStandardCode As String = "2.12.2." & VersionBranchCode '标准格式的四段式版本号
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
#If BETA Then
Public Const VersionCode As Integer = 372 'Release
Public Const VersionCode As Integer = 379 'Release
#Else
Public Const VersionCode As Integer = 378 'Snapshot
Public Const VersionCode As Integer = 380 'Snapshot
#End If
'自动生成的版本信息
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
@@ -62,7 +62,7 @@ Public Module ModBase
''' <summary>
''' 程序的打开计时。
''' </summary>
Public ApplicationStartTick As Long = GetTimeTick()
Public ApplicationStartTick As Long = GetTimeMs()
''' <summary>
''' 程序打开时的时间。
''' </summary>
@@ -1284,27 +1284,31 @@ Re:
''' <summary>
''' 尝试根据后缀名判断文件种类并解压文件,支持 gz 与 zip,会尝试将 jar 以 zip 方式解压。
''' 会尝试创建,但不会清空目标文件夹。
''' 会先使用 UTF-8 解压,失败后换用 GB18030 解压。
''' </summary>
Public Sub ExtractFile(CompressFilePath As String, DestDirectory As String, Optional Encode As Encoding = Nothing,
Optional ProgressIncrementHandler As Action(Of Double) = Nothing)
Public Sub ExtractCompressedFile(CompressFilePath As String, DestDirectory As String, Optional ProgressIncrementHandler As Action(Of Double) = Nothing)
Directory.CreateDirectory(DestDirectory)
'解压 gz(gz 不需要考虑编码)
If CompressFilePath.EndsWithF(".gz", True) Then
'以 gz 方式解压
Dim stream As New GZipStream(New FileStream(CompressFilePath, FileMode.Open, FileAccess.ReadWrite), CompressionMode.Decompress)
Dim decompressedFile As New FileStream(DestDirectory & GetFileNameFromPath(CompressFilePath).ToLower.Replace(".tar", "").Replace(".gz", ""), FileMode.OpenOrCreate, FileAccess.Write)
Dim data As Integer = stream.ReadByte()
While data <> -1
decompressedFile.WriteByte(data)
data = stream.ReadByte()
End While
decompressedFile.Close()
stream.Close()
Else
'以 zip 方式解压
Using Archive = ZipFile.Open(CompressFilePath, ZipArchiveMode.Read, If(Encode, Encoding.GetEncoding("GB18030")))
Dim TotalCount As Long = Archive.Entries.Count
For Each Entry As ZipArchiveEntry In Archive.Entries
If ProgressIncrementHandler IsNot Nothing AndAlso TotalCount > 0 Then ProgressIncrementHandler(1 / TotalCount)
Using stream As New GZipStream(New FileStream(CompressFilePath, FileMode.Open, FileAccess.Read, FileShare.Read), CompressionMode.Decompress)
Using decompressedFile As New FileStream(DestDirectory & GetFileNameFromPath(CompressFilePath).ToLower.Replace(".tar", "").Replace(".gz", ""),
FileMode.OpenOrCreate, FileAccess.Write)
Dim data As Integer = stream.ReadByte()
While data <> -1
decompressedFile.WriteByte(data)
data = stream.ReadByte()
End While
End Using
End Using
Return
End If
'解压 zip
Dim TryExtractZip =
Sub(Encoding As Encoding)
Using Archive = ZipFile.Open(CompressFilePath, ZipArchiveMode.Read, Encoding)
Dim EntryCount = Archive.Entries.Count
For Each Entry In Archive.Entries
If ProgressIncrementHandler IsNot Nothing AndAlso EntryCount > 0 Then ProgressIncrementHandler(1 / EntryCount)
Dim DestinationFullPath As String = IO.Path.Combine(DestDirectory, Entry.FullName)
If Not IO.Path.GetFullPath(DestinationFullPath).StartsWithF(IO.Path.GetFullPath(DestDirectory), True) Then Continue For 'ZipSlip 漏洞修复
If DestinationFullPath.EndsWithF("\") OrElse DestinationFullPath.EndsWithF("/") Then Continue For '不创建空文件夹
@@ -1313,7 +1317,17 @@ Re:
Entry.ExtractToFile(DestinationFullPath.Replace(DestinationDirectory, ShortenPath(DestinationDirectory)), True) '#7329
Next
End Using
End If
End Sub
Try
TryExtractZip(Encoding.UTF8)
Catch ex As Exception
Log(ex, $"首次解压尝试失败,将更换编码并重试({CompressFilePath} → {DestDirectory})")
Try
TryExtractZip(Encoding.GetEncoding("GB18030"))
Catch
Throw
End Try
End Try
End Sub
''' <summary>
@@ -1609,6 +1623,7 @@ RetryDir:
End Function
''' <summary>
''' 分割字符串。
''' 若原始字符串为空,则返回 {""}。
''' </summary>
<Extension> Public Function Split(FullStr As String, SplitStr As String) As String()
If SplitStr.Length = 1 Then
@@ -2297,10 +2312,10 @@ NextElement:
Return Date.Now.ToString("HH':'mm':'ss'.'fff")
End Function
''' <summary>
''' 获取系统运行时间(毫秒),保证为正 Long 且大于 1,但可能突变减小。
''' 获取一个单调递增时间值(毫秒)。
''' </summary>
Public Function GetTimeTick() As Long
Return My.Computer.Clock.TickCount + 2147483651L
Public Function GetTimeMs() As Long
Return Stopwatch.GetTimestamp() \ (Stopwatch.Frequency \ 1000L)
End Function
''' <summary>
''' 将时间间隔转换为类似“5 分 10 秒前”的易于阅读的形式。
@@ -295,7 +295,7 @@
If (State = LoadState.Loading OrElse State = LoadState.Finished) AndAlso '正在加载或已结束…
(IgnoreReloadTimeout OrElse ReloadTimeout = -1 OrElse
LastFinishedTime = 0 OrElse GetTimeTick() - LastFinishedTime < ReloadTimeout) Then '…且没有超时…
LastFinishedTime = 0 OrElse GetTimeMs() - LastFinishedTime < ReloadTimeout) Then '…且没有超时…
Return False '…则不重试
Else
Return True '否则需要重启
@@ -328,7 +328,7 @@
If ModeDebug AndAlso Not LogBlackList.Contains(Name) Then Log($"[Loader] 加载线程 {Name} ({Thread.CurrentThread.ManagedThreadId}) 已完成")
RaisePreviewFinish()
State = LoadState.Finished
LastFinishedTime = GetTimeTick() '未中断,本次输出有效
LastFinishedTime = GetTimeMs() '未中断,本次输出有效
Catch ex As CancelledException
If ModeDebug Then Log(ex, $"加载线程 {Name} ({Thread.CurrentThread.ManagedThreadId}) 已触发取消中断,已完成 {Math.Round(Progress * 100)}%")
If Not IsAborted Then State = LoadState.Aborted
+32 -32
View File
@@ -52,7 +52,7 @@ Public Module ModNet
Optional Encoding As Encoding = Nothing, Optional SimulateBrowserHeaders As Boolean = False) As String
Dim RetryCount As Integer = 0
Dim RetryException As Exception = Nothing
Dim StartTime As Long = GetTimeTick()
Dim StartTime As Long = GetTimeMs()
Try
Retry:
Select Case RetryCount
@@ -62,7 +62,7 @@ Retry:
Thread.Sleep(500)
Return NetRequestByClient(Url, Method, Content, ContentType, Accept, 30000, Headers, RequireJson, Encoding, SimulateBrowserHeaders)
Case Else '快速重试
If GetTimeTick() - StartTime > 5500 Then
If GetTimeMs() - StartTime > 5500 Then
'若前两次加载耗费 5 秒以上,才进行重试
Thread.Sleep(500)
Return NetRequestByClient(Url, Method, Content, ContentType, Accept, 4000, Headers, RequireJson, Encoding, SimulateBrowserHeaders)
@@ -586,7 +586,7 @@ RequestFinished:
''' <summary>
''' 上次记速时的时间。
''' </summary>
Private SpeedLastTime As Long = GetTimeTick()
Private SpeedLastTime As Long = GetTimeMs()
''' <summary>
''' 上次记速时的已下载大小。
''' </summary>
@@ -596,8 +596,8 @@ RequestFinished:
''' </summary>
Public ReadOnly Property Speed As Long
Get
If GetTimeTick() - SpeedLastTime > 200 Then
Dim DeltaTime As Long = GetTimeTick() - SpeedLastTime
If GetTimeMs() - SpeedLastTime > 200 Then
Dim DeltaTime As Long = GetTimeMs() - SpeedLastTime
_Speed = (DownloadDone - SpeedLastDone) / (DeltaTime / 1000)
SpeedLastDone = DownloadDone
SpeedLastTime += DeltaTime
@@ -610,7 +610,7 @@ RequestFinished:
''' <summary>
''' 线程初始化时的时间。
''' </summary>
Public InitTime As Long = GetTimeTick()
Public InitTime As Long = GetTimeMs()
''' <summary>
''' 上次接受到有效数据的时间,-1 表示尚未有有效数据。
''' </summary>
@@ -773,7 +773,7 @@ RequestFinished:
''' <summary>
''' 上次记速时的时间。
''' </summary>
Private SpeedLastTime As Long = GetTimeTick()
Private SpeedLastTime As Long = GetTimeMs()
''' <summary>
''' 上次记速时的已下载大小。
''' </summary>
@@ -783,8 +783,8 @@ RequestFinished:
''' </summary>
Public ReadOnly Property Speed As Long
Get
If GetTimeTick() - SpeedLastTime > 200 Then
Dim DeltaTime As Long = GetTimeTick() - SpeedLastTime
If GetTimeMs() - SpeedLastTime > 200 Then
Dim DeltaTime As Long = GetTimeMs() - SpeedLastTime
_Speed = (DownloadDone - SpeedLastDone) / (DeltaTime / 1000)
SpeedLastDone = DownloadDone
SpeedLastTime += DeltaTime
@@ -1079,7 +1079,7 @@ NotSupportRange:
SyncLock NetTaskSpeedLimitLeftLock
If NetTaskSpeedLimitHigh > 0 Then NetTaskSpeedLimitLeft -= RealDataCount
End SyncLock
Dim DeltaTime = GetTimeTick() - Th.LastReceiveTime
Dim DeltaTime = GetTimeMs() - Th.LastReceiveTime
If DeltaTime > 1000000 Then DeltaTime = 1 '避免时间刻反转导致出现极大值
If RealDataCount > 0 Then
'有数据
@@ -1091,7 +1091,7 @@ NotSupportRange:
End SyncLock
SyncLock LockCount
ConnectCount += 1
ConnectTime += GetTimeTick() - Th.InitTime
ConnectTime += GetTimeMs() - Th.InitTime
End SyncLock
End If
SyncLock LockCount
@@ -1113,7 +1113,7 @@ NotSupportRange:
Th.Source.SingleThread Is Nothing Then '且并非单线程下载
Throw New TimeoutException("由于速度过慢断开链接,下载 " & RealDataCount & " B,消耗 " & DeltaTime & " ms。")
End If
Th.LastReceiveTime = GetTimeTick()
Th.LastReceiveTime = GetTimeMs()
ElseIf Th.LastReceiveTime > 0 AndAlso DeltaTime > Timeout Then
'无数据,且已超时
Throw New TimeoutException("操作超时,无数据。")
@@ -1346,6 +1346,7 @@ Retry:
If State >= NetState.Finished Then Return
If RaiseEx IsNot Nothing Then Ex.Add(RaiseEx)
'凉凉
Log($"[Download] {LocalName}:已失败,当前状态 {State}")
State = NetState.Interrupted
End SyncLock
AbortInternal()
@@ -1363,6 +1364,7 @@ Retry:
'确认中断
SyncLock LockState
If State >= NetState.Finished Then Return
Log($"[Download] {LocalName}:已中断,当前状态 {State}")
State = NetState.Interrupted
End SyncLock
AbortInternal()
@@ -1373,7 +1375,6 @@ Retry:
SyncLock NetManager.LockRemain
NetManager.FileRemain -= 1
End SyncLock
Log($"[Download] {LocalName}:已终止,当前状态 {State}")
End Sub
'状态改变接口
@@ -1584,14 +1585,8 @@ FinishExCatch:
For Each File As NetFile In Files
Dim Target As String = CheckExistingFile(FolderList, VersionFolders, File)
If File.State >= NetState.WaitingToDownload Then Return '中断
If Target Is Nothing Then
'未找到相同文件
SyncLock LockState
File.State = NetState.WaitingToDownload
File.IsCopy = False
End SyncLock
Else
'已找到相同文件
'已找到相同文件
If Target IsNot Nothing Then
File.IsCopy = True
Dim RetryCount As Integer = 0
Retry:
@@ -1601,20 +1596,21 @@ Retry:
CopyFile(Target, File.LocalPath)
End If
File.Finish(False)
Continue For
Catch ex As Exception
RetryCount += 1
Log(ex, $"复制已存在的文件失败,第 {RetryCount} 次重试({Target} → {File.LocalPath})")
If RetryCount < 3 Then
Thread.Sleep(200)
Thread.Sleep(2000)
GoTo Retry
End If
'失败,回退到下载
SyncLock LockState
File.State = NetState.WaitingToDownload
File.IsCopy = False
End SyncLock
End Try
End If
'回退到下载
SyncLock LockState
File.State = NetState.WaitingToDownload
File.IsCopy = False
End SyncLock
Next
Catch ex As Exception
OnFail(New List(Of Exception) From {New Exception("下载已存在文件查找失败", ex)})
@@ -1639,6 +1635,7 @@ Retry:
End If
Dim Type = TypeIndexes.MaxOf(Function(kv) kv.Item2).FolderName.TrimStart("\"c)
'根据类别进行查找
Static Sizes As New SafeDictionary(Of String, Long)
Select Case Type
Case "assets\", "libraries\"
'assets/libraries:查找 MC 文件夹下的相同路径
@@ -1651,6 +1648,10 @@ Retry:
For Each VersionFolder In VersionFolders
For Each Candidate In Directory.GetFiles(VersionFolder,
"*." & GetFileNameFromPath(File.LocalPath).AfterLast(".").ToLower, SearchOption.TopDirectoryOnly)
'快速进行大小校验
If Not Sizes.ContainsKey(Candidate) Then Sizes(Candidate) = New FileInfo(Candidate).Length
If File.Check.ActualSize <> Sizes(Candidate) Then Continue For
'Hash 校验
If File.Check.Check(Candidate) Is Nothing Then Return Candidate
Next
Next
@@ -1662,7 +1663,6 @@ Retry:
If Not Directory.Exists(TargetFolder) Then Continue For
For Each Candidate In Directory.GetFiles(TargetFolder)
'快速进行大小校验
Static Sizes As New SafeDictionary(Of String, Long)
If Not Sizes.ContainsKey(Candidate) Then Sizes(Candidate) = New FileInfo(Candidate).Length
If File.Check.ActualSize <> Sizes(Candidate) Then Continue For
'Hash 校验
@@ -1803,7 +1803,7 @@ Retry:
''' </summary>
Private Sub RefreshStat()
Try
Dim DeltaTime As Long = GetTimeTick() - RefreshStatLast
Dim DeltaTime As Long = GetTimeMs() - RefreshStatLast
If DeltaTime = 0 Then Return
RefreshStatLast += DeltaTime
#Region "刷新整体速度"
@@ -1905,7 +1905,7 @@ Retry:
RunInNewThread(
Sub()
Try
Dim NextTick As Long = GetTimeTick()
Dim NextTick As Long = GetTimeMs()
While True
'增加限速余量
If NetTaskSpeedLimitHigh > 0 Then NetTaskSpeedLimitLeft = NetTaskSpeedLimitHigh / 10
@@ -1913,11 +1913,11 @@ Retry:
RefreshStat()
'等待 100 ms
NextTick += 100
Dim SleepTime = NextTick - GetTimeTick()
Dim SleepTime = NextTick - GetTimeMs()
If SleepTime > 0 Then
Thread.Sleep(SleepTime)
Else
NextTick = GetTimeTick() '超时,直接追帧,不等待
NextTick = GetTimeMs() '超时,直接追帧,不等待
End If
End While
Catch ex As Exception
@@ -72,7 +72,7 @@ Public Class MyBitmap
End If
Else
'使用这种自己接管 FileStream 的方法加载才能解除文件占用
Using InputStream As New FileStream(FilePathOrResourceName, FileMode.Open)
Using InputStream As New FileStream(FilePathOrResourceName, FileMode.Open, FileAccess.Read, FileShare.Read)
'判断是否为 WebP 文件头
Dim Header(1) As Byte
InputStream.Read(Header, 0, 2)
@@ -48,9 +48,9 @@
#Region "CompDatabase | Mod 数据库"
Private _CompDatabase As List(Of CompDatabaseEntry) = Nothing
Private ReadOnly Property CompDatabase As List(Of CompDatabaseEntry)
Get
Static _CompDatabase As List(Of CompDatabaseEntry) = Nothing
If _CompDatabase IsNot Nothing Then Return _CompDatabase
'初始化数据库
_CompDatabase = New List(Of CompDatabaseEntry)
@@ -881,7 +881,7 @@ NoSubtitle:
Case CompType.ResourcePack
Address += "&classId=12"
End Select
Address += "&categoryId=" & If(Tag = "", "0", Tag.BeforeFirst("/"))
If Tag <> "" Then Address += "&categoryId=" & Tag.BeforeFirst("/")
If ModLoader <> CompModLoaderType.Any Then Address += "&modLoaderType=" & CType(ModLoader, Integer)
If Not String.IsNullOrEmpty(GameVersion) Then Address += "&gameVersion=" & GameVersion
If Not String.IsNullOrEmpty(SearchText) Then Address += "&searchFilter=" & Net.WebUtility.UrlEncode(SearchText)
@@ -1355,6 +1355,10 @@ Retry:
''' </summary>
Public ReadOnly Hash As String = Nothing
''' <summary>
''' 文件大小。不可用时为 -1。
''' </summary>
Public ReadOnly Size As Integer = -1
''' <summary>
''' 该文件的所有依赖工程的原始 ID。
''' 这些 ID 可能没有加载,在加载后会添加到 Dependencies 中(主要是因为 Modrinth 返回的是字符串 ID 而非 Slug,导致 Project.Id 查询不到)。
''' </summary>
@@ -1368,7 +1372,7 @@ Retry:
''' </summary>
''' <param name="LocalAddress">目标本地文件夹,或完整的文件路径。会自动判断类型。</param>
Public Function ToNetFile(LocalAddress As String) As NetFile
Return New NetFile(DownloadUrls, LocalAddress & If(LocalAddress.EndsWithF("\"), FileName, ""), New FileChecker(Hash:=Hash), SimulateBrowserHeaders:=True)
Return New NetFile(DownloadUrls, LocalAddress & If(LocalAddress.EndsWithF("\"), FileName, ""), New FileChecker(Hash:=Hash, ActualSize:=Size), SimulateBrowserHeaders:=True)
End Function
'实例化
@@ -1390,6 +1394,7 @@ Retry:
If Data.ContainsKey("FileName") Then FileName = Data("FileName").ToString
If Data.ContainsKey("DownloadUrls") Then DownloadUrls = Data("DownloadUrls").ToObject(Of List(Of String))
If Data.ContainsKey("ModLoaders") Then ModLoaders = Data("ModLoaders").ToObject(Of List(Of CompModLoaderType))
If Data.ContainsKey("Size") Then Size = Data("Size").ToObject(Of Integer)
If Data.ContainsKey("Hash") Then Hash = Data("Hash").ToString
If Data.ContainsKey("GameVersions") Then GameVersions = Data("GameVersions").ToObject(Of List(Of String))
If Data.ContainsKey("RawDependencies") Then RawDependencies = Data("RawDependencies").ToObject(Of List(Of String))
@@ -1407,6 +1412,7 @@ Retry:
Status = CType(Data("releaseType").ToObject(Of Integer), CompFileStatus)
DownloadCount = Data("downloadCount")
FileName = Data("fileName")
Size = Data("fileLength")
Hash = CType(Data("hashes"), JArray).ToList.FirstOrDefault(Function(s) s("algo").ToObject(Of Integer) = 1)?("value")
If Hash Is Nothing Then Hash = CType(Data("hashes"), JArray).ToList.FirstOrDefault(Function(s) s("algo").ToObject(Of Integer) = 2)?("value")
'DownloadAddress
@@ -1453,6 +1459,7 @@ Retry:
Dim File As JToken = Data("files")(0)
FileName = File("filename")
DownloadUrls = New List(Of String) From {File("url"), DlSourceModGet(File("url"))}.Distinct.ToList '同时添加了镜像源
Size = File("size")
Hash = File("hashes")("sha1")
End If
'ModLoaders
@@ -1531,6 +1538,7 @@ Retry:
If FileName IsNot Nothing Then Json.Add("FileName", FileName)
If DownloadUrls IsNot Nothing Then Json.Add("DownloadUrls", New JArray(DownloadUrls))
If Hash IsNot Nothing Then Json.Add("Hash", Hash)
If Size >= 0 Then Json.Add("Size", Size)
Json.Add("RawDependencies", New JArray(RawDependencies))
Json.Add("Dependencies", New JArray(Dependencies))
Return Json
@@ -98,7 +98,7 @@
Try
Dim Info As New FileInfo(FilePath)
If Info.Exists AndAlso Info.Length > 0 AndAlso Not FilePath.EndsWithF(".jar", True) Then
ExtractFile(FilePath, TempFolder & "Temp\")
ExtractCompressedFile(FilePath, TempFolder & "Temp\")
Log("[Crash] 已解压导入的日志文件:" & FilePath)
GoTo Extracted
End If
@@ -712,11 +712,11 @@ NextStack:
Dim Word As String = Splited(i)
If Word.Length <= 2 OrElse Word.StartsWithF("func_") Then Continue For
If {"com", "org", "net", "asm", "fml", "mod", "jar", "sun", "lib", "map", "gui", "dev", "nio", "api", "dsi", "top", "mcp",
"core", "init", "mods", "main", "file", "game", "load", "read", "done", "util", "tile", "item", "base", "oshi", "impl", "data", "pool", "task",
"forge", "setup", "block", "model", "mixin", "event", "unimi", "netty", "world", "lwjgl",
"gitlab", "common", "server", "config", "mixins", "compat", "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", "neoforge",
"core", "init", "mods", "main", "file", "game", "load", "read", "done", "util", "tile", "item", "base", "fake", "oshi", "impl", "data", "pool", "task",
"forge", "setup", "block", "model", "mixin", "event", "unimi", "netty", "world", "lwjgl", "fakes",
"gitlab", "common", "server", "config", "mixins", "compat", "loader", "launch", "script", "entity", "assist", "client", "plugin", "modapi", "mojang", "shader", "events", "github", "recipe", "render", "packet", "events",
"preinit", "preload", "machine", "reflect", "channel", "general", "handler", "content", "systems", "modules", "service", "scripts", "network",
"fastutil", "optifine", "internal", "platform", "override", "fabricmc", "neoforge", "external",
"injection", "listeners", "scheduler", "minecraft", "universal", "multipart", "neoforged", "microsoft",
"transformer", "transformers", "minecraftforge", "blockentity", "spongepowered", "electronwill", "concurrent"
}.Contains(Word.ToLower) Then Continue For
@@ -222,14 +222,14 @@
''' </summary>
Public DlClientListMojangLoader As New LoaderTask(Of String, DlClientListResult)("DlClientList Mojang", AddressOf DlClientListMojangMain)
Private Sub DlClientListMojangMain(Loader As LoaderTask(Of String, DlClientListResult))
Dim StartTime As Long = GetTimeTick()
Dim StartTime As Long = GetTimeMs()
Dim Json As JObject = GetJson(NetRequestByClientRetry("https://launchermeta.mojang.com/mc/game/version_manifest.json", RequireJson:=True))
Try
Dim Versions As JArray = Json("versions")
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
'确定官方源是否可用
If Not DlPreferMojang Then
Dim DeltaTime = GetTimeTick() - StartTime
Dim DeltaTime = GetTimeMs() - StartTime
DlPreferMojang = DeltaTime < 4000
Log($"[Download] Mojang 官方源加载耗时:{DeltaTime}ms,{If(DlPreferMojang, "可优先使用官方源", "不优先使用官方源")}")
End If
@@ -844,7 +844,7 @@
Public Sub New(ApiName As String)
IsNeoForge = True
Me.ApiName = ApiName
IsBeta = ApiName.Contains("beta") OrElse ApiName.Contains("alpha")
IsBeta = ApiName.ContainsF("beta", True) OrElse ApiName.ContainsF("alpha", True)
If ApiName.Contains("1.20.1") Then '1.20.1-47.1.99
VersionName = ApiName.Replace("1.20.1-", "")
Version = New Version("19." & VersionName)
@@ -465,9 +465,10 @@ NoUserJava:
If Not Left.IsJre AndAlso Right.IsJre Then Return False
'4. Java 大版本
If Left.MajorVersion <> Right.MajorVersion Then
' Java 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23...
Dim Weight = {0, 1, 2, 3, 4, 5, 6, 14, 30, 10, 12, 15, 13, 9, 8, 7, 11, 31, 29, 16, 17, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18}
Return Weight.ElementAtOrDefault(Left.MajorVersion) >= Weight.ElementAtOrDefault(Right.MajorVersion)
' Java 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Dim Weight = {0, 1, 2, 3, 4, 5, 6, 14, 30, 10, 12, 15, 13, 9, 8, 7, 11, 31, 29, 16, 17} '更高的版本指定为 20,且越低越好
Return If(Left.MajorVersion > 20, 20 - Left.MajorVersion * 0.0001, Weight.ElementAtOrDefault(Left.MajorVersion)) >=
If(Right.MajorVersion > 20, 20 - Right.MajorVersion * 0.0001, Weight.ElementAtOrDefault(Right.MajorVersion))
End If
'5. 最次级版本号更接近 51
Return Math.Abs(Left.Version.Revision - 51) <= Math.Abs(Right.Version.Revision - 51)
@@ -544,7 +544,7 @@ NextInner:
'检查是否已经登录完成
If Not Data.IsForceRestarting AndAlso '不要求强行重启
Input.AccessToken <> "" AndAlso '已经登录过了
(McLoginMsRefreshTime > 0 AndAlso GetTimeTick() - McLoginMsRefreshTime < 1000 * 60 * 10) Then '完成时间在 10 分钟内
(McLoginMsRefreshTime > 0 AndAlso GetTimeMs() - McLoginMsRefreshTime < 1000 * 60 * 10) Then '完成时间在 10 分钟内
Data.Output = New McLoginResult With
{.AccessToken = Input.AccessToken, .Name = Input.UserName, .Uuid = Input.Uuid, .Type = "Microsoft", .ClientToken = Input.Uuid, .ProfileJson = Input.ProfileJson}
GoTo SkipLogin
@@ -591,7 +591,7 @@ Relogin:
Setup.Set("LoginMsJson", MsJson.ToString(Newtonsoft.Json.Formatting.None))
Data.Output = New McLoginResult With {.AccessToken = AccessToken, .Name = Result(1), .Uuid = Result(0), .Type = "Microsoft", .ClientToken = Result(0), .ProfileJson = Result(2)}
'结束
McLoginMsRefreshTime = GetTimeTick()
McLoginMsRefreshTime = GetTimeMs()
McLaunchLog("微软登录完成")
SkipLogin:
Setup.Set("HintBuy", True) '关闭正版购买提示
@@ -1771,7 +1771,7 @@ NextInstance:
If Not Native.IsNatives Then Continue For
Dim Zip As ZipArchive
Try
Zip = New ZipArchive(New FileStream(Native.LocalPath, FileMode.Open))
Zip = New ZipArchive(New FileStream(Native.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read))
Catch ex As InvalidDataException
Log(ex, "打开 Natives 文件失败(" & Native.LocalPath & ")")
File.Delete(Native.LocalPath)
@@ -426,8 +426,8 @@ Public Module ModMinecraft
End Try
#End Region
VersionSearchFinish:
_Version.VanillaName = _Version.VanillaName.Replace("_unobfuscated", "").Replace(" Unobfuscated", "")
'获取版本号
_Version.VanillaName = _Version.VanillaName.Replace("_unobfuscated", "").Replace(" Unobfuscated", "")
If _Version.VanillaName.StartsWithF("1.") Then
Dim Segments = _Version.VanillaName.Split(" _-.".ToCharArray)
_Version.Vanilla = New Version(
@@ -1,7 +1,7 @@
Imports System.IO.Compression
Public Module ModMod
Private Const LocalModCacheVersion As Integer = 10
Private Const LocalModCacheVersion As Integer = 11
Public Class McMod
@@ -137,7 +137,7 @@ Public Module ModMod
'基础可用性检查、打开 Jar 文件
If Path.Length < 2 Then Throw New FileNotFoundException("错误的 Mod 文件路径(" & If(Path, "null") & ")")
If Not File.Exists(Path) Then Throw New FileNotFoundException("未找到 Mod 文件(" & Path & ")")
Jar = New ZipArchive(New FileStream(Path, FileMode.Open))
Jar = New ZipArchive(New FileStream(Path, FileMode.Open, FileAccess.Read, FileShare.Read))
'信息获取
LoadMetadataFromJar(Jar)
Catch ex As UnauthorizedAccessException
@@ -424,7 +424,7 @@ Finished:
''' </summary>
Public ReadOnly Property CanUpdate As Boolean
Get
Return Not Setup.Get("UiHiddenFunctionModUpdate") AndAlso Not Setup.Get("VersionAdvanceDisableModUpdate", Instance:=PageInstanceLeft.Instance) AndAlso ChangelogUrls.Any()
Return Not Setup.Get("UiHiddenFunctionModUpdate") AndAlso Not Setup.Get("VersionAdvanceDisableModUpdate", Instance:=PageInstanceLeft.Instance) AndAlso UpdateFile IsNot Nothing
End Get
End Property
@@ -604,7 +604,7 @@ Finished:
For Each ModFile As FileInfo In ModFileList
If Loader.IsAborted Then Return
Dim ModEntry As New McMod(ModFile.FullName)
Dim DumpMod As McMod = ModList.FirstOrDefault(Function(m) m.RawFileName = ModEntry.RawFileName)
Dim DumpMod As McMod = ModList.FirstOrDefault(Function(m) m.RawFileName = ModEntry.RawFileName) '存在两个文件,名称相同,但一个启用一个禁用
If DumpMod IsNot Nothing Then
Dim DisabledMod As McMod = If(DumpMod.State = McMod.McModState.Disabled, DumpMod, ModEntry)
Log($"[Mod] 重复的 Mod 文件:{DumpMod.FileName} 与 {ModEntry.FileName},已忽略 {DisabledMod.FileName}", LogLevel.Debug)
@@ -619,10 +619,7 @@ Finished:
Log($"[Mod] 共发现 {ModList.Count} 个 Mod")
'排序
ModList = ModList.SortByComparison(
Function(Left, Right) As Boolean
Return Not Right.FileName.CompareTo(Left.FileName)
End Function)
ModList = ModList.OrderBy(Function(m) m.FileName).ToList
'回设
If Loader.IsAborted Then Return
@@ -112,19 +112,14 @@ Public Module ModModpack
Private Sub ExtractModpackFiles(InstallTemp As String, FileAddress As String, Loader As LoaderBase, ProgressIncrement As Double)
'解压文件
Dim RetryCount As Integer = 1
Dim Encode = Encoding.GetEncoding("GB18030")
Dim InitialProgress = Loader.Progress
Try
Retry:
Loader.Progress = InitialProgress
DeleteDirectory(InstallTemp)
ExtractFile(FileAddress, InstallTemp, Encode, ProgressIncrementHandler:=Sub(Delta) Loader.Progress += Delta * ProgressIncrement)
ExtractCompressedFile(FileAddress, InstallTemp, ProgressIncrementHandler:=Sub(Delta) Loader.Progress += Delta * ProgressIncrement)
Catch ex As Exception
Log(ex, "第 " & RetryCount & " 次解压尝试失败")
If TypeOf ex Is ArgumentException Then
Encode = Encoding.UTF8
Log("[ModPack] 已切换压缩包解压编码为 UTF8")
End If
'完全不知道为啥会出现文件正在被另一进程使用的问题,总之加个重试
If RetryCount < 5 Then
Thread.Sleep(RetryCount * 2000)
+1 -1
View File
@@ -647,7 +647,7 @@ NextFile:
DeleteDirectory(PathTemp & "Help")
Directory.CreateDirectory(PathTemp & "Help")
WriteFile(PathTemp & "Cache\Help.zip", GetResources("Help"))
ExtractFile(PathTemp & "Cache\Help.zip", PathTemp & "Help", Encoding.UTF8)
ExtractCompressedFile(PathTemp & "Cache\Help.zip", PathTemp & "Help")
Setup.Set("SystemHelpVersion", VersionCode)
Log("[Help] 已解压内置帮助文件,目前状态:" & File.Exists(PathTemp & "Help\启动器\备份设置.xaml"), LogLevel.Debug)
End If