大家好这里是皇鱼
本文将接着上一篇文章的内容继续下载版本资源文件
本文以C#为例,那么开始。
特别感谢:bmclapi源让我的下载速度提升
解析资源文件
将资源索引文件中的objects这个json对象的每个value都访问一遍,里面会有
{
"hash": "b62ca8ec10d07e6bf5ac8dae0c8c1d2e6a1e3356", "size": 9101
}
你需要提取其中的hash
,这不仅是用于校验,还用于获取下载链接以及存储路径。
下载链接是
https://resources.download.minecraft.net/hash的前两位/hash
以上述例子为例,下载链接就是
https://resources.download.minecraft.net/b6/b62ca8ec10d07e6bf5ac8dae0c8c1d2e6a1e3356
存储路径就是
.minecraft/assets/objects/hash的前两位/hash
这里就不写例子了
由于objects中有很多小文件,且都是在mojang服务器上存储,强烈建议搭配镜像源与多线程进行下载
http://resources.download.minecraft.net -> https://bmclapi2.bangbang93.com/assets
C#代码示例:
async public static void downloadAssets()
{
Directory.CreateDirectory("./.minecraft/assets/indexes");
Console.WriteLine("Downloading assetIndex...");
string indexJson = File.ReadAllText(@".\.minecraft\versions\1.21\1.21.json");
string assetIndextUrl = GetValueFromJson(indexJson, "assetIndex.url");
string aiid = GetValueFromJson(indexJson, "assetIndex.id");
using (WebClient client = new WebClient())
{
client.DownloadFile(assetIndextUrl.Replace("piston-meta.mojang.com", "bmclapi2.bangbang93.com"), $"./.minecraft/assets/indexes/{aiid}.json");
}
Console.WriteLine("Parsing assets...");
string objects = GetValueFromJson(File.ReadAllText($"./.minecraft/assets/indexes/{aiid}.json"), "objects");
Dictionary<string, string> assets = new Dictionary<string, string>();
using (JsonDocument doc = JsonDocument.Parse(objects))
{
JsonElement root = doc.RootElement;
if (root.ValueKind == JsonValueKind.Object)
{
foreach (JsonProperty property in root.EnumerateObject())
{
string hash = GetValueFromJson(property.Value.ToString(), "hash");
string url = $"https://bmclapi2.bangbang93.com/assets/{hash.Substring(0, 2)}/{hash}";
string path = $"./.minecraft/assets/objects/{hash.Substring(0, 2)}/{hash}";
assets.TryAdd(url, path);
}
}
}
Console.WriteLine("Downloading assets");
await DownloadFilesAsync(assets);
}
static async Task DownloadFilesAsync(Dictionary<string, string> files)
{
using (HttpClient client = new HttpClient())
{
List<Task> downloadTasks = new List<Task>();
foreach (var file in files)
{
string url = file.Key;
string filePath = file.Value;
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
downloadTasks.Add(DownloadFileAsync(client, url, filePath));
}
await Task.WhenAll(downloadTasks);
}
}
static async Task DownloadFileAsync(HttpClient client, string url, string filePath)
{
int i = 0;
while (true)
{
if(i >= 50){
Console.WriteLine($"download failed:{url}");
break;
}
try
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
byte[] fileBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync(filePath, fileBytes);
Console.WriteLine($"Downloaded {url} to {filePath}");
break;
}
catch
{
i++
continue;
}
}
}
运行截图:
查看路径
资源文件下载完成
下次讲启动游戏
参考资料
Minecraft Wiki - https://zh.minecraft.wiki
BMCLAPI - https://bmclapidoc.bangbang93.com
HMCL源代码 - https://github.com/HMCL-dev/HMCL/
PCL2源代码 - https://github.com/Hex-Dragon/PCL2
最后修改:2024-07-27 13:08
本文链接:https://blog.huangyu.win/index.php/archives/13/
版权声明:本文 如何编写一个Minecraft Java版启动器 | Part 2 下载资源文件 | 1-2 为 皇鱼 原创。著作权归作者所有,如无特殊声明,本文将依据CC BY-NC-SA 3.0 CN发布,请注意版权。
转载说明:请依据CC BY-NC-SA 3.0 CN进行转载。
1 条评论
我没意见