大家好这里是皇鱼
这是本blog的第一篇文章
在这篇文章中,我将教会各位如何下载并安装一个Minecraft版本,并挖掘背后的运行逻辑。
阅读本文前,若您是为了制作一个Minecraft启动器而来,可以查找您的编程语言是否有对应的sdk,这可以帮助您简化工作。
如果你想自己写一个启动核心,那么将会需要本文内容。
本文以C#为例,那么开始。
特别感谢:bmclapi源让我的下载速度提升
获取版本列表
打开Mojang提供的VersionManifest,里面列出了可用的所有版本信息(bmclapi镜像)
基本格式为:
{
"latest": {
"release": "1.21",
"snapshot": "1.21"
},
"versions": [
{
"id": "1.21",
"type": "release",
"url": "https://piston-meta.mojang.com/v1/packages/177e49d3233cb6eac42f0495c0a48e719870c2ae/1.21.json",
"time": "2024-06-13T08:32:38+00:00",
"releaseTime": "2024-06-13T08:24:03+00:00"
},
{
...
}
]
}
我们需要使用json库提取其中的内容,其中latest
中记录了最新的正式版和预览版的版本编号;versions
这个json数组里每个json对象都包含id
type
url
time
releaseTime
这几项,id
是这个版本的版本编号,type
的值可能为release
snapshot
old_beta
old_alpha
,其中release
代表这个版本是正式版,snapshot
代表是快照版,old_beta
和old_alpha
都是早期远古版。
C#示例代码:
public static string getVersionManifest()
{
using (var client = new HttpClient())
{
var response = client.GetAsync("https://bmclapi2.bangbang93.com/mc/game/version_manifest.json").Result;
response.EnsureSuccessStatusCode();
var responseContent = response.Content.ReadAsStringAsync().Result;
return responseContent;
}
}
public static void ParseVersionManifest() {
string vm = getVersionManifest();
string lastRelease = GetValueFromJson(vm, "latest.release");
string lastSnapshot = GetValueFromJson(vm, "latest.snapshot");
string versionsStr = GetValueFromJson(vm, "versions");
JsonArray versions = JsonArray.Parse(versionsStr).AsArray();
Console.WriteLine(lastRelease);
Console.WriteLine(lastSnapshot);
foreach ( var version in versions)
{
string id = GetValueFromJson(version.ToJsonString(), "id");
string type = GetValueFromJson(version.ToJsonString(), "type");
string url = GetValueFromJson(version.ToJsonString(), "url");
Console.WriteLine($"Version:{id};{type};{url}");
}
}
(GetVaueFromJson
是一个可以通过json和点分path获取具体string值的函数,这里就不放了)
输出:
版本索引
你可能注意到,我们平常游玩时的Minecraft版本是一个包含版本json、版本jar、natives等的文件夹,但上述版本列表中只有一个json的下载链接,那么我们应该如何获得其他的内容的下载链接呢?这就要用到版本索引文件了。
上述链接里的全都是版本索引文件的下载链接,它是一个json,里面包含的内容可以参考wiki
我们需要下载这个json,并将其存储到.minecraft/versions/版本名称(不是id)/版本名称(不是id).json中,例如1.14.4/1.14.4.json
。
(bmclapi源 将版本信息内的URL中的https://launchermeta.mojang.com/ 和 https://launcher.mojang.com/ 替换为 https://bmclapi2.bangbang93.com)
接下来,我们需要下载依赖库文件。
下载游戏启动所需的文件
依赖库
依赖库文件的信息存储于版本索引文件中的libraries这个数组中,原版json里,数组的每一项都包含如下内容:
{
"downloads": {
"artifact": {
"path": "com/github/oshi/oshi-core/6.2.2/oshi-core-6.2.2.jar",
"sha1": "54f5efc19bca95d709d9a37d19ffcbba3d21c1a6",
"size": 947865,
"url": "https://libraries.minecraft.net/com/github/oshi/oshi-core/6.2.2/oshi-core-6.2.2.jar"
}
},
"name": "com.github.oshi:oshi-core:6.2.2"
}
(部分可能带有classifiers
或者rules
键,那些是native库,放到后面讲,目前遇到了可以直接存储起来)
我们需要提取出其中的path
和url
,如果你想验证文件完整性的话也可以保存size
和sha1
。path
指的是文件保存的路径,以上面为例,那么这个依赖库保存的路径就应该是.minecraft/libraries/com/github/oshi/oshi-core/6.2.2/oshi-core-6.2.2.jar
url
就是下载的链接,可以使用bmclapi源下载,即将https://libraries.minecraft.net替换为https://bmclapi2.bangbang93.com/maven。
C#示例代码(别抄,这个是同步单线程下载,速度极慢):
Console.WriteLine("Creating Dirs...");
Directory.CreateDirectory(@".\.minecraft\versions\1.21");
Directory.CreateDirectory(@".\.minecraft\libraries");
if(!File.Exists(@".\.minecraft\versions\1.21\1.21.json")) {
using (WebClient client = new WebClient())
{
client.DownloadFile("https://bmclapi2.bangbang93.com/v1/packages/177e49d3233cb6eac42f0495c0a48e719870c2ae/1.21.json", @".\.minecraft\versions\1.21\1.21.json");
}
}
Console.WriteLine("Downloaded Version Index Json");
Console.WriteLine("Parsing json to get libraries...");
string indexJson = File.ReadAllText(@".\.minecraft\versions\1.21\1.21.json");
string librariesStr = GetValueFromJson(indexJson, "libraries");
JsonArray larr = JsonArray.Parse(librariesStr).AsArray();
foreach ( var lib in larr )
{
string libStr = lib.ToJsonString();
string url = GetValueFromJson(libStr, "downloads.artifact.url");
string path = GetValueFromJson(libStr, "downloads.artifact.path");
if (!File.Exists(@$".\.minecraft\libraries\{path}"))
{
Directory.CreateDirectory(Path.GetDirectoryName(@$".\.minecraft\libraries\{path}"));
using (WebClient client = new WebClient())
{
client.DownloadFile(url.Replace("https://libraries.minecraft.net", "https://bmclapi2.bangbang93.com/maven"), $@".\.minecraft\libraries\{path}");
Console.WriteLine($"Downloading library {path} from {url.Replace("https://libraries.minecraft.net", "https://bmclapi2.bangbang93.com/maven")}");
}
}
}
Console.WriteLine("Libraries Downloaded.");
输出:
目录截图:
至此,依赖库的下载就完成了。
native库
native库只有在游戏启动时才应该被解压,将libraries
中含有rules
或classifiers
的项下载完成后的对这些文件挨个解压(只解压对应操作系统的,linux就是linux,osx是macos,windows就是windows)里面的所有.dll文件(不需要带上路径),解压到versions/版本名/版本名-natives文件夹中。
C#示例:
Directory.CreateDirectory(@".\.minecraft\versions\1.21\1.21-natives");
string indexJson = File.ReadAllText(@".\.minecraft\versions\1.21\1.21.json");
string librariesStr = GetValueFromJson(indexJson, "libraries");
JsonArray larr = JsonArray.Parse(librariesStr).AsArray();
foreach (var lib in larr)
{
string libStr = lib.ToJsonString();
string path = GetValueFromJson(libStr, "downloads.artifact.path");
if(GetValueFromJson(libStr, "rules[0].os") != null)
{
string os = GetValueFromJson(libStr, "rules[0].os");
if (os.Contains("win"))
{
Console.WriteLine($"Found a windows native {path}, unzipping...");
using (ZipArchive archive = ZipFile.OpenRead($@".\.minecraft\libraries\{path}"))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
{
string dPath = Path.Combine(@".\.minecraft\versions\1.21\1.21-natives", entry.Name);
entry.ExtractToFile(dPath, overwrite: true);
}
}
}
Console.WriteLine("unzipped");
}
}
}
解压完后的截图:
这样,natives库也准备好了。
资源索引文件
回到版本索引文件中,里面包含了如下内容:
"assetIndex": {
"id": "17",
"sha1": "fab15439bdef669e389e25e815eee8f1b2aa915e",
"size": 447033,
"totalSize": 799252591,
"url": "https://piston-meta.mojang.com/v1/packages/fab15439bdef669e389e25e815eee8f1b2aa915e/17.json"
}
这就是资源索引文件的下载方式,同样可以使用上文中的bmclapi来加速下载,我们需要将其存储到.minecraft/assets/indexes
中。
由于编写本文时时间太晚了,故下篇文章接着讲下载资源文件。
最后修改:2024-07-26 22:17
本文链接:https://blog.huangyu.win/index.php/archives/3/
版权声明:本文 如何编写一个Minecraft Java版启动器 | Part 1 下载&安装依赖库 | 1-1 为 皇鱼 原创。著作权归作者所有,如无特殊声明,本文将依据CC BY-NC-SA 3.0 CN发布,请注意版权。
转载说明:请依据CC BY-NC-SA 3.0 CN进行转载。
1 条评论
参考资料:
Minecraft Wiki:https://zh.minecraft.wiki
BMCLAPI:bmclapidoc.bangbang93.com
HMCL源代码:https://github.com/HMCL-dev/HMCL/
PCL2源代码:https://github.com/Hex-Dragon/PCL2/