俗话说得好,分而治之。既然我们已经将脚本一分为五了,那么接下来就只需要一项一项地再分析,研究写法,就能取得辉煌的阶段性研究成果了~
参考资料:

Java路径


首先贴出来:

  1. "C:\\Program Files\\Java\\jdk-15.0.2\\bin\\java.exe"

这一部分需要使用英文引号括起来,内容为一个指向java.exe的绝对路径(指向javaw.exe也可以)。例如,这里指向的是jdk 15的路径。
对于Minecraft 1.8.9来说,这项参数也可以指向Java 8, jdk 11, jdk 16, jdk 17,都是可以正常启动的。
比如说,很多启动器都拥有查找已安装Java版本的功能。Java的默认安装目录为C:\Program Files\Java,只要让启动器在此默认目录内递归搜索,寻找名为“java.exe”的可执行程序即可。
不过,作为一款入门级别的启动器,我们可以跳过自动查询的部分,毕竟相比于后面的部分——自动查询也不算很难。作为替代,我们可以把电脑里常用于启动Minecraft的Java版本路径存储起来。

  1. java_path = "C:\\Program Files\\Java\\jdk-15.0.2\\bin\\java.exe"

或者,我建议您将Java路径存储在一个配置文件中,然后让Python读取此配置文件即可。配置文件不一定需要是conf格式或yaml格式,您大可以用JSON格式的文档来存储——反正Python原生支持读取写入JSON,而且相对来说比较简单。

  1. "java_list":
  2. [
  3. {"version": "8", "path": "C:/Program Files/Java/jre1.8.0_261/bin/java.exe"},
  4. {"version": "11", "path": "C:/Program Files/Java/jdk-11.0.13.8-hotspot/bin/java.exe"},
  5. {"version": "17", "path": "C:/Program Files/Java/jdk-17.0.1.12-hotspot/bin/java.exe"}
  6. ]

下面是Python中,读取JSON文档所需的代码。

  1. import json # Python中处理JSON文档所用的库,为内置库,不需另外安装。
  2. def java_versions_list():
  3. """
  4. 此函数将从本地缓存的目录中取出已保存的Java版本。
  5. :return: 返回缓存中的Java版本列表,请注意:列表中的版本以字典形式存储。
  6. """
  7. with open(file=config.game_versions_json_path, encoding="utf-8") as game_local_dict:
  8. java_versions_list: list = json.load(game_local_dict)["java_list"]
  9. for i in java_versions_list:
  10. j: str = i["path"]
  11. n: list = j.split("/")
  12. m: str = "\\"
  13. l: str = m.join(n)
  14. i["path"] = l
  15. return java_versions_list
  16. # config.game_versions_json_path是该配置文件的路径。
  17. # 在JSON中,路径里的斜杠为/,下方将其替换成了\\。使用\\而不是\是为了防止Python将其转义。

您可以在此时测试此代码:

  1. java_version_list = java_versions_list()
  2. for i in java_version_list:
  3. print(i)
  4. # 不要用一样的名字嗷
  1. {"version": "8", "path": "C:/Program Files/Java/jre1.8.0_261/bin/java.exe"}
  2. {"version": "11", "path": "C:/Program Files/Java/jdk-11.0.13.8-hotspot/bin/java.exe"}
  3. {"version": "17", "path": "C:/Program Files/Java/jdk-17.0.1.12-hotspot/bin/java.exe"}

然后在需要时,读取此列表,遍历其中每一个字典的“version”键,就可以获得Java的版本列表;在选择一个版本之后,再从中找到对应的字典,读取“path”键的值,就是路径了。
当然还有其他写法,记得读取方式要与写法相对应。至于如何向JSON存入数据,我们将在以后说明。您可以暂时手动输入一些信息来应应急(?)

JVM参数


JVM参数,先上模板。

  1. -Dminecraft.client.jar=D:\FCL\.minecraft\versions\1.8.9\1.8.9.jar -Xmn128m -Xmx5858m -Djava.library.path=D:\FCL\.minecraft\versions\1.8.9\natives-windows-x86_64
-Dminecraft.client.jar= 指定版本的client.jar所在目录。
-Djava.library.path= 指定版本的natives库解压到的目录(后续介绍)。
-Xmn -Xmx 允许Minecraft运行的最小和最大内存。

指定版本的client.jar所在目录,就是该版本jar文件的绝对目录。版本jar文件一般位于.minecraft\versions\中。
natives库将在之后进行介绍。
Xmn是最小内存,Xmx是最大内存。
将这些参数依次拼接,就是JVM参数。在前文HMCL生成的启动脚本中还有更多的参数,那些我们暂不做深入研究。
现在,在Python中,您可以使用以下方案来获得上面的这些参数。我们假设您已经拥有一个完整的Minecraft 1.8.9的游戏(包括assets文件夹中、libraries文件夹中、versions文件夹中的所有文件全部完整,并且已经由HMCL、PCL等启动器启动过至少一次),那么您可以将您的Python工程源码与.minecraft文件夹按如下目录存放:

  • .minecraft[游戏根目录]
    • assets(子目录不再展开)
    • libraries(子目录不再展开)
    • versions
      • 1.8.9
        • 1.8.9.jar
        • 1.8.9.json
    • (其他目录不再展示)
  • FCL[启动器附加文件目录](方便扔一些奇怪的东西进去给启动器当外部资源调用)
  • 《您的启动器源码》

在这里面找找,有没有哪个文件夹的名字里包含“natives”,这个文件夹大概率就是“-Djava.library.path=”需要的参数路径,把文件夹的路径填进去吧。
下面的Python代码可以让您获取您的项目源码绝对路径。在打包成exe文件之后,该代码可以得出此exe文件的绝对路径。然后您可以用其来拼接成.minecraft的路径,这也是启动器在同目录下管理.minecraft文件夹的方式。

  1. import os
  2. self_path = os.getcwd()
  3. print(self_path)

-cp库路径


这可不是你们爱磕的cp,这里是很多很多很多的jar文件,就是跟client.jar一个格式的文件。在启动参数中需要拼接很多个指向这些jar文件的绝对路径,包括client.jar也不例外地要再来一遍。

  1. -cp D:\FCL\.minecraft\libraries\com\mojang\netty\1.8.8\netty-1.8.8.jar;D:\FCL\.minecraft\libraries\oshi-project\oshi-core\1.1\oshi-core-1.1.jar;D:\FCL\.minecraft\libraries\net\java\dev\jna\jna\3.4.0\jna-3.4.0.jar;D:\FCL\.minecraft\libraries\net\java\dev\jna\platform\3.4.0\platform-3.4.0.jar;D:\FCL\.minecraft\libraries\com\ibm\icu\icu4j-core-mojang\51.2\icu4j-core-mojang-51.2.jar;D:\FCL\.minecraft\libraries\net\sf\jopt-simple\jopt-simple\4.6\jopt-simple-4.6.jar;D:\FCL\.minecraft\libraries\com\paulscode\codecjorbis\20101023\codecjorbis-20101023.jar;D:\FCL\.minecraft\libraries\com\paulscode\codecwav\20101023\codecwav-20101023.jar;D:\FCL\.minecraft\libraries\com\paulscode\libraryjavasound\20101123\libraryjavasound-20101123.jar;D:\FCL\.minecraft\libraries\com\paulscode\librarylwjglopenal\20100824\librarylwjglopenal-20100824.jar;D:\FCL\.minecraft\libraries\com\paulscode\soundsystem\20120107\soundsystem-20120107.jar;D:\FCL\.minecraft\libraries\io\netty\netty-all\4.0.23.Final\netty-all-4.0.23.Final.jar;D:\FCL\.minecraft\libraries\com\google\guava\guava\17.0\guava-17.0.jar;D:\FCL\.minecraft\libraries\org\apache\commons\commons-lang3\3.3.2\commons-lang3-3.3.2.jar;D:\FCL\.minecraft\libraries\commons-io\commons-io\2.4\commons-io-2.4.jar;D:\FCL\.minecraft\libraries\commons-codec\commons-codec\1.9\commons-codec-1.9.jar;D:\FCL\.minecraft\libraries\net\java\jinput\jinput\2.0.5\jinput-2.0.5.jar;D:\FCL\.minecraft\libraries\net\java\jutils\jutils\1.0.0\jutils-1.0.0.jar;D:\FCL\.minecraft\libraries\com\google\code\gson\gson\2.2.4\gson-2.2.4.jar;D:\FCL\.minecraft\libraries\com\mojang\authlib\1.5.21\authlib-1.5.21.jar;D:\FCL\.minecraft\libraries\com\mojang\realms\1.7.59\realms-1.7.59.jar;D:\FCL\.minecraft\libraries\org\apache\commons\commons-compress\1.8.1\commons-compress-1.8.1.jar;D:\FCL\.minecraft\libraries\org\apache\httpcomponents\httpclient\4.3.3\httpclient-4.3.3.jar;D:\FCL\.minecraft\libraries\commons-logging\commons-logging\1.1.3\commons-logging-1.1.3.jar;D:\FCL\.minecraft\libraries\org\apache\httpcomponents\httpcore\4.3.2\httpcore-4.3.2.jar;D:\FCL\.minecraft\libraries\org\apache\logging\log4j\log4j-api\2.0-beta9\log4j-api-2.0-beta9.jar;D:\FCL\.minecraft\libraries\org\apache\logging\log4j\log4j-core\2.0-beta9\log4j-core-2.0-beta9.jar;D:\FCL\.minecraft\libraries\org\lwjgl\lwjgl\lwjgl\2.9.4-nightly-20150209\lwjgl-2.9.4-nightly-20150209.jar;D:\FCL\.minecraft\libraries\org\lwjgl\lwjgl\lwjgl_util\2.9.4-nightly-20150209\lwjgl_util-2.9.4-nightly-20150209.jar;D:\FCL\.minecraft\libraries\tv\twitch\twitch\6.5\twitch-6.5.jar;D:\FCL\.minecraft\versions\1.8.9\1.8.9.jar

这么多东西是怎么来的呢?
是在该版本的JSON文档内。
一个完整的1.8.9JSON文档包含的内容应当如下:

  1. {
  2. "assetIndex": {
  3. "id": "1.8",
  4. "sha1": "f6ad102bcaa53b1a58358f16e376d548d44933ec",
  5. "size": 78494,
  6. "totalSize": 114885064,
  7. "url": "https://launchermeta.mojang.com/v1/packages/f6ad102bcaa53b1a58358f16e376d548d44933ec/1.8.json"
  8. },
  9. "assets": "1.8",
  10. "complianceLevel": 0,
  11. "downloads": {
  12. "client": {
  13. "sha1": "3870888a6c3d349d3771a3e9d16c9bf5e076b908",
  14. "size": 8461484,
  15. "url": "https://launcher.mojang.com/v1/objects/3870888a6c3d349d3771a3e9d16c9bf5e076b908/client.jar"
  16. },
  17. "server": {
  18. "sha1": "b58b2ceb36e01bcd8dbf49c8fb66c55a9f0676cd",
  19. "size": 8320755,
  20. "url": "https://launcher.mojang.com/v1/objects/b58b2ceb36e01bcd8dbf49c8fb66c55a9f0676cd/server.jar"
  21. },
  22. "windows_server": {
  23. "sha1": "5143618265b8a2d1d28bcadf206b7327738c2670",
  24. "size": 8714995,
  25. "url": "https://launcher.mojang.com/v1/objects/5143618265b8a2d1d28bcadf206b7327738c2670/windows_server.exe"
  26. }
  27. },
  28. "id": "原版1.8.9",
  29. "javaVersion": {
  30. "component": "jre-legacy",
  31. "majorVersion": 8
  32. },
  33. "libraries": [
  34. {
  35. "downloads": {
  36. "artifact": {
  37. "path": "com/mojang/netty/1.8.8/netty-1.8.8.jar",
  38. "sha1": "0a796914d1c8a55b4da9f4a8856dd9623375d8bb",
  39. "size": 15966,
  40. "url": "https://libraries.minecraft.net/com/mojang/netty/1.8.8/netty-1.8.8.jar"
  41. }
  42. },
  43. "name": "com.mojang:netty:1.8.8"
  44. },
  45. {
  46. "downloads": {
  47. "artifact": {
  48. "path": "oshi-project/oshi-core/1.1/oshi-core-1.1.jar",
  49. "sha1": "9ddf7b048a8d701be231c0f4f95fd986198fd2d8",
  50. "size": 30973,
  51. "url": "https://libraries.minecraft.net/oshi-project/oshi-core/1.1/oshi-core-1.1.jar"
  52. }
  53. },
  54. "name": "oshi-project:oshi-core:1.1"
  55. },
  56. {
  57. "downloads": {
  58. "artifact": {
  59. "path": "net/java/dev/jna/jna/3.4.0/jna-3.4.0.jar",
  60. "sha1": "803ff252fedbd395baffd43b37341dc4a150a554",
  61. "size": 1008730,
  62. "url": "https://libraries.minecraft.net/net/java/dev/jna/jna/3.4.0/jna-3.4.0.jar"
  63. }
  64. },
  65. "name": "net.java.dev.jna:jna:3.4.0"
  66. },
  67. {
  68. "downloads": {
  69. "artifact": {
  70. "path": "net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar",
  71. "sha1": "e3f70017be8100d3d6923f50b3d2ee17714e9c13",
  72. "size": 913436,
  73. "url": "https://libraries.minecraft.net/net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar"
  74. }
  75. },
  76. "name": "net.java.dev.jna:platform:3.4.0"
  77. },
  78. {
  79. "downloads": {
  80. "artifact": {
  81. "path": "com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar",
  82. "sha1": "63d216a9311cca6be337c1e458e587f99d382b84",
  83. "size": 1634692,
  84. "url": "https://libraries.minecraft.net/com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar"
  85. }
  86. },
  87. "name": "com.ibm.icu:icu4j-core-mojang:51.2"
  88. },
  89. {
  90. "downloads": {
  91. "artifact": {
  92. "path": "net/sf/jopt-simple/jopt-simple/4.6/jopt-simple-4.6.jar",
  93. "sha1": "306816fb57cf94f108a43c95731b08934dcae15c",
  94. "size": 62477,
  95. "url": "https://libraries.minecraft.net/net/sf/jopt-simple/jopt-simple/4.6/jopt-simple-4.6.jar"
  96. }
  97. },
  98. "name": "net.sf.jopt-simple:jopt-simple:4.6"
  99. },
  100. {
  101. "downloads": {
  102. "artifact": {
  103. "path": "com/paulscode/codecjorbis/20101023/codecjorbis-20101023.jar",
  104. "sha1": "c73b5636faf089d9f00e8732a829577de25237ee",
  105. "size": 103871,
  106. "url": "https://libraries.minecraft.net/com/paulscode/codecjorbis/20101023/codecjorbis-20101023.jar"
  107. }
  108. },
  109. "name": "com.paulscode:codecjorbis:20101023"
  110. },
  111. {
  112. "downloads": {
  113. "artifact": {
  114. "path": "com/paulscode/codecwav/20101023/codecwav-20101023.jar",
  115. "sha1": "12f031cfe88fef5c1dd36c563c0a3a69bd7261da",
  116. "size": 5618,
  117. "url": "https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"
  118. }
  119. },
  120. "name": "com.paulscode:codecwav:20101023"
  121. },
  122. {
  123. "downloads": {
  124. "artifact": {
  125. "path": "com/paulscode/libraryjavasound/20101123/libraryjavasound-20101123.jar",
  126. "sha1": "5c5e304366f75f9eaa2e8cca546a1fb6109348b3",
  127. "size": 21679,
  128. "url": "https://libraries.minecraft.net/com/paulscode/libraryjavasound/20101123/libraryjavasound-20101123.jar"
  129. }
  130. },
  131. "name": "com.paulscode:libraryjavasound:20101123"
  132. },
  133. {
  134. "downloads": {
  135. "artifact": {
  136. "path": "com/paulscode/librarylwjglopenal/20100824/librarylwjglopenal-20100824.jar",
  137. "sha1": "73e80d0794c39665aec3f62eee88ca91676674ef",
  138. "size": 18981,
  139. "url": "https://libraries.minecraft.net/com/paulscode/librarylwjglopenal/20100824/librarylwjglopenal-20100824.jar"
  140. }
  141. },
  142. "name": "com.paulscode:librarylwjglopenal:20100824"
  143. },
  144. {
  145. "downloads": {
  146. "artifact": {
  147. "path": "com/paulscode/soundsystem/20120107/soundsystem-20120107.jar",
  148. "sha1": "419c05fe9be71f792b2d76cfc9b67f1ed0fec7f6",
  149. "size": 65020,
  150. "url": "https://libraries.minecraft.net/com/paulscode/soundsystem/20120107/soundsystem-20120107.jar"
  151. }
  152. },
  153. "name": "com.paulscode:soundsystem:20120107"
  154. },
  155. {
  156. "downloads": {
  157. "artifact": {
  158. "path": "io/netty/netty-all/4.0.23.Final/netty-all-4.0.23.Final.jar",
  159. "sha1": "0294104aaf1781d6a56a07d561e792c5d0c95f45",
  160. "size": 1779991,
  161. "url": "https://libraries.minecraft.net/io/netty/netty-all/4.0.23.Final/netty-all-4.0.23.Final.jar"
  162. }
  163. },
  164. "name": "io.netty:netty-all:4.0.23.Final"
  165. },
  166. {
  167. "downloads": {
  168. "artifact": {
  169. "path": "com/google/guava/guava/17.0/guava-17.0.jar",
  170. "sha1": "9c6ef172e8de35fd8d4d8783e4821e57cdef7445",
  171. "size": 2243036,
  172. "url": "https://libraries.minecraft.net/com/google/guava/guava/17.0/guava-17.0.jar"
  173. }
  174. },
  175. "name": "com.google.guava:guava:17.0"
  176. },
  177. {
  178. "downloads": {
  179. "artifact": {
  180. "path": "org/apache/commons/commons-lang3/3.3.2/commons-lang3-3.3.2.jar",
  181. "sha1": "90a3822c38ec8c996e84c16a3477ef632cbc87a3",
  182. "size": 412739,
  183. "url": "https://libraries.minecraft.net/org/apache/commons/commons-lang3/3.3.2/commons-lang3-3.3.2.jar"
  184. }
  185. },
  186. "name": "org.apache.commons:commons-lang3:3.3.2"
  187. },
  188. {
  189. "downloads": {
  190. "artifact": {
  191. "path": "commons-io/commons-io/2.4/commons-io-2.4.jar",
  192. "sha1": "b1b6ea3b7e4aa4f492509a4952029cd8e48019ad",
  193. "size": 185140,
  194. "url": "https://libraries.minecraft.net/commons-io/commons-io/2.4/commons-io-2.4.jar"
  195. }
  196. },
  197. "name": "commons-io:commons-io:2.4"
  198. },
  199. {
  200. "downloads": {
  201. "artifact": {
  202. "path": "commons-codec/commons-codec/1.9/commons-codec-1.9.jar",
  203. "sha1": "9ce04e34240f674bc72680f8b843b1457383161a",
  204. "size": 263965,
  205. "url": "https://libraries.minecraft.net/commons-codec/commons-codec/1.9/commons-codec-1.9.jar"
  206. }
  207. },
  208. "name": "commons-codec:commons-codec:1.9"
  209. },
  210. {
  211. "downloads": {
  212. "artifact": {
  213. "path": "net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar",
  214. "sha1": "39c7796b469a600f72380316f6b1f11db6c2c7c4",
  215. "size": 208338,
  216. "url": "https://libraries.minecraft.net/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar"
  217. }
  218. },
  219. "name": "net.java.jinput:jinput:2.0.5"
  220. },
  221. {
  222. "downloads": {
  223. "artifact": {
  224. "path": "net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar",
  225. "sha1": "e12fe1fda814bd348c1579329c86943d2cd3c6a6",
  226. "size": 7508,
  227. "url": "https://libraries.minecraft.net/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar"
  228. }
  229. },
  230. "name": "net.java.jutils:jutils:1.0.0"
  231. },
  232. {
  233. "downloads": {
  234. "artifact": {
  235. "path": "com/google/code/gson/gson/2.2.4/gson-2.2.4.jar",
  236. "sha1": "a60a5e993c98c864010053cb901b7eab25306568",
  237. "size": 190432,
  238. "url": "https://libraries.minecraft.net/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar"
  239. }
  240. },
  241. "name": "com.google.code.gson:gson:2.2.4"
  242. },
  243. {
  244. "downloads": {
  245. "artifact": {
  246. "path": "com/mojang/authlib/1.5.21/authlib-1.5.21.jar",
  247. "sha1": "aefba0d5b53fbcb70860bc8046ab95d5854c07a5",
  248. "size": 64412,
  249. "url": "https://libraries.minecraft.net/com/mojang/authlib/1.5.21/authlib-1.5.21.jar"
  250. }
  251. },
  252. "name": "com.mojang:authlib:1.5.21"
  253. },
  254. {
  255. "downloads": {
  256. "artifact": {
  257. "path": "com/mojang/realms/1.7.59/realms-1.7.59.jar",
  258. "sha1": "9c6c59b742d8e038a15f64c1aa273a893a658424",
  259. "size": 1198123,
  260. "url": "https://libraries.minecraft.net/com/mojang/realms/1.7.59/realms-1.7.59.jar"
  261. }
  262. },
  263. "name": "com.mojang:realms:1.7.59"
  264. },
  265. {
  266. "downloads": {
  267. "artifact": {
  268. "path": "org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar",
  269. "sha1": "a698750c16740fd5b3871425f4cb3bbaa87f529d",
  270. "size": 365552,
  271. "url": "https://libraries.minecraft.net/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar"
  272. }
  273. },
  274. "name": "org.apache.commons:commons-compress:1.8.1"
  275. },
  276. {
  277. "downloads": {
  278. "artifact": {
  279. "path": "org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar",
  280. "sha1": "18f4247ff4572a074444572cee34647c43e7c9c7",
  281. "size": 589512,
  282. "url": "https://libraries.minecraft.net/org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar"
  283. }
  284. },
  285. "name": "org.apache.httpcomponents:httpclient:4.3.3"
  286. },
  287. {
  288. "downloads": {
  289. "artifact": {
  290. "path": "commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar",
  291. "sha1": "f6f66e966c70a83ffbdb6f17a0919eaf7c8aca7f",
  292. "size": 62050,
  293. "url": "https://libraries.minecraft.net/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar"
  294. }
  295. },
  296. "name": "commons-logging:commons-logging:1.1.3"
  297. },
  298. {
  299. "downloads": {
  300. "artifact": {
  301. "path": "org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar",
  302. "sha1": "31fbbff1ddbf98f3aa7377c94d33b0447c646b6e",
  303. "size": 282269,
  304. "url": "https://libraries.minecraft.net/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar"
  305. }
  306. },
  307. "name": "org.apache.httpcomponents:httpcore:4.3.2"
  308. },
  309. {
  310. "downloads": {
  311. "artifact": {
  312. "path": "org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar",
  313. "sha1": "1dd66e68cccd907880229f9e2de1314bd13ff785",
  314. "size": 108161,
  315. "url": "https://libraries.minecraft.net/org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar"
  316. }
  317. },
  318. "name": "org.apache.logging.log4j:log4j-api:2.0-beta9"
  319. },
  320. {
  321. "downloads": {
  322. "artifact": {
  323. "path": "org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar",
  324. "sha1": "678861ba1b2e1fccb594bb0ca03114bb05da9695",
  325. "size": 681134,
  326. "url": "https://libraries.minecraft.net/org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar"
  327. }
  328. },
  329. "name": "org.apache.logging.log4j:log4j-core:2.0-beta9"
  330. },
  331. {
  332. "downloads": {
  333. "artifact": {
  334. "path": "org/lwjgl/lwjgl/lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar",
  335. "sha1": "697517568c68e78ae0b4544145af031c81082dfe",
  336. "size": 1047168,
  337. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar"
  338. }
  339. },
  340. "name": "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209",
  341. "rules": [
  342. {
  343. "action": "allow"
  344. },
  345. {
  346. "action": "disallow",
  347. "os": {
  348. "name": "osx"
  349. }
  350. }
  351. ]
  352. },
  353. {
  354. "downloads": {
  355. "artifact": {
  356. "path": "org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/lwjgl_util-2.9.4-nightly-20150209.jar",
  357. "sha1": "d51a7c040a721d13efdfbd34f8b257b2df882ad0",
  358. "size": 173887,
  359. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/lwjgl_util-2.9.4-nightly-20150209.jar"
  360. }
  361. },
  362. "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209",
  363. "rules": [
  364. {
  365. "action": "allow"
  366. },
  367. {
  368. "action": "disallow",
  369. "os": {
  370. "name": "osx"
  371. }
  372. }
  373. ]
  374. },
  375. {
  376. "downloads": {
  377. "artifact": {
  378. "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar",
  379. "sha1": "b04f3ee8f5e43fa3b162981b50bb72fe1acabb33",
  380. "size": 22,
  381. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar"
  382. },
  383. "classifiers": {
  384. "natives-linux": {
  385. "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar",
  386. "sha1": "931074f46c795d2f7b30ed6395df5715cfd7675b",
  387. "size": 578680,
  388. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar"
  389. },
  390. "natives-osx": {
  391. "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar",
  392. "sha1": "bcab850f8f487c3f4c4dbabde778bb82bd1a40ed",
  393. "size": 426822,
  394. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"
  395. },
  396. "natives-windows": {
  397. "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar",
  398. "sha1": "b84d5102b9dbfabfeb5e43c7e2828d98a7fc80e0",
  399. "size": 613748,
  400. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar"
  401. }
  402. }
  403. },
  404. "extract": {
  405. "exclude": [
  406. "META-INF/"
  407. ]
  408. },
  409. "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
  410. "natives": {
  411. "linux": "natives-linux",
  412. "osx": "natives-osx",
  413. "windows": "natives-windows"
  414. },
  415. "rules": [
  416. {
  417. "action": "allow"
  418. },
  419. {
  420. "action": "disallow",
  421. "os": {
  422. "name": "osx"
  423. }
  424. }
  425. ]
  426. },
  427. {
  428. "downloads": {
  429. "artifact": {
  430. "path": "org/lwjgl/lwjgl/lwjgl/2.9.2-nightly-20140822/lwjgl-2.9.2-nightly-20140822.jar",
  431. "sha1": "7707204c9ffa5d91662de95f0a224e2f721b22af",
  432. "size": 1045632,
  433. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.2-nightly-20140822/lwjgl-2.9.2-nightly-20140822.jar"
  434. }
  435. },
  436. "name": "org.lwjgl.lwjgl:lwjgl:2.9.2-nightly-20140822",
  437. "rules": [
  438. {
  439. "action": "allow",
  440. "os": {
  441. "name": "osx"
  442. }
  443. }
  444. ]
  445. },
  446. {
  447. "downloads": {
  448. "artifact": {
  449. "path": "org/lwjgl/lwjgl/lwjgl_util/2.9.2-nightly-20140822/lwjgl_util-2.9.2-nightly-20140822.jar",
  450. "sha1": "f0e612c840a7639c1f77f68d72a28dae2f0c8490",
  451. "size": 173887,
  452. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.2-nightly-20140822/lwjgl_util-2.9.2-nightly-20140822.jar"
  453. }
  454. },
  455. "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.2-nightly-20140822",
  456. "rules": [
  457. {
  458. "action": "allow",
  459. "os": {
  460. "name": "osx"
  461. }
  462. }
  463. ]
  464. },
  465. {
  466. "downloads": {
  467. "classifiers": {
  468. "natives-linux": {
  469. "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-linux.jar",
  470. "sha1": "d898a33b5d0a6ef3fed3a4ead506566dce6720a5",
  471. "size": 578539,
  472. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-linux.jar"
  473. },
  474. "natives-osx": {
  475. "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar",
  476. "sha1": "79f5ce2fea02e77fe47a3c745219167a542121d7",
  477. "size": 468116,
  478. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar"
  479. },
  480. "natives-windows": {
  481. "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-windows.jar",
  482. "sha1": "78b2a55ce4dc29c6b3ec4df8ca165eba05f9b341",
  483. "size": 613680,
  484. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-windows.jar"
  485. }
  486. }
  487. },
  488. "extract": {
  489. "exclude": [
  490. "META-INF/"
  491. ]
  492. },
  493. "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.2-nightly-20140822",
  494. "natives": {
  495. "linux": "natives-linux",
  496. "osx": "natives-osx",
  497. "windows": "natives-windows"
  498. },
  499. "rules": [
  500. {
  501. "action": "allow",
  502. "os": {
  503. "name": "osx"
  504. }
  505. }
  506. ]
  507. },
  508. {
  509. "downloads": {
  510. "classifiers": {
  511. "natives-linux": {
  512. "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar",
  513. "sha1": "7ff832a6eb9ab6a767f1ade2b548092d0fa64795",
  514. "size": 10362,
  515. "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar"
  516. },
  517. "natives-osx": {
  518. "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar",
  519. "sha1": "53f9c919f34d2ca9de8c51fc4e1e8282029a9232",
  520. "size": 12186,
  521. "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar"
  522. },
  523. "natives-windows": {
  524. "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar",
  525. "sha1": "385ee093e01f587f30ee1c8a2ee7d408fd732e16",
  526. "size": 155179,
  527. "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar"
  528. }
  529. }
  530. },
  531. "extract": {
  532. "exclude": [
  533. "META-INF/"
  534. ]
  535. },
  536. "name": "net.java.jinput:jinput-platform:2.0.5",
  537. "natives": {
  538. "linux": "natives-linux",
  539. "osx": "natives-osx",
  540. "windows": "natives-windows"
  541. }
  542. },
  543. {
  544. "downloads": {
  545. "artifact": {
  546. "path": "tv/twitch/twitch/6.5/twitch-6.5.jar",
  547. "sha1": "320a2dfd18513a5f41b4e75729df684488cbd925",
  548. "size": 55977,
  549. "url": "https://libraries.minecraft.net/tv/twitch/twitch/6.5/twitch-6.5.jar"
  550. }
  551. },
  552. "name": "tv.twitch:twitch:6.5"
  553. },
  554. {
  555. "downloads": {
  556. "classifiers": {
  557. "natives-osx": {
  558. "path": "tv/twitch/twitch-platform/6.5/twitch-platform-6.5-natives-osx.jar",
  559. "sha1": "5f9d1ee26257b3a33f0ca06fed335ef462af659f",
  560. "size": 455359,
  561. "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/6.5/twitch-platform-6.5-natives-osx.jar"
  562. },
  563. "natives-windows-32": {
  564. "path": "tv/twitch/twitch-platform/6.5/twitch-platform-6.5-natives-windows-32.jar",
  565. "sha1": "206c4ccaecdbcfd2a1631150c69a97bbc9c20c11",
  566. "size": 474225,
  567. "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/6.5/twitch-platform-6.5-natives-windows-32.jar"
  568. },
  569. "natives-windows-64": {
  570. "path": "tv/twitch/twitch-platform/6.5/twitch-platform-6.5-natives-windows-64.jar",
  571. "sha1": "9fdd0fd5aed0817063dcf95b69349a171f447ebd",
  572. "size": 580098,
  573. "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/6.5/twitch-platform-6.5-natives-windows-64.jar"
  574. }
  575. }
  576. },
  577. "extract": {
  578. "exclude": [
  579. "META-INF/"
  580. ]
  581. },
  582. "name": "tv.twitch:twitch-platform:6.5",
  583. "natives": {
  584. "linux": "natives-linux",
  585. "osx": "natives-osx",
  586. "windows": "natives-windows-${arch}"
  587. },
  588. "rules": [
  589. {
  590. "action": "allow"
  591. },
  592. {
  593. "action": "disallow",
  594. "os": {
  595. "name": "linux"
  596. }
  597. }
  598. ]
  599. },
  600. {
  601. "downloads": {
  602. "classifiers": {
  603. "natives-windows-32": {
  604. "path": "tv/twitch/twitch-external-platform/4.5/twitch-external-platform-4.5-natives-windows-32.jar",
  605. "sha1": "18215140f010c05b9f86ef6f0f8871954d2ccebf",
  606. "size": 5654047,
  607. "url": "https://libraries.minecraft.net/tv/twitch/twitch-external-platform/4.5/twitch-external-platform-4.5-natives-windows-32.jar"
  608. },
  609. "natives-windows-64": {
  610. "path": "tv/twitch/twitch-external-platform/4.5/twitch-external-platform-4.5-natives-windows-64.jar",
  611. "sha1": "c3cde57891b935d41b6680a9c5e1502eeab76d86",
  612. "size": 7457619,
  613. "url": "https://libraries.minecraft.net/tv/twitch/twitch-external-platform/4.5/twitch-external-platform-4.5-natives-windows-64.jar"
  614. }
  615. }
  616. },
  617. "extract": {
  618. "exclude": [
  619. "META-INF/"
  620. ]
  621. },
  622. "name": "tv.twitch:twitch-external-platform:4.5",
  623. "natives": {
  624. "windows": "natives-windows-${arch}"
  625. },
  626. "rules": [
  627. {
  628. "action": "allow",
  629. "os": {
  630. "name": "windows"
  631. }
  632. }
  633. ]
  634. }
  635. ],
  636. "logging": {
  637. "client": {
  638. "argument": "-Dlog4j.configurationFile=${path}",
  639. "file": {
  640. "id": "client-1.7.xml",
  641. "sha1": "50c9cc4af6d853d9fc137c84bcd153e2bd3a9a82",
  642. "size": 966,
  643. "url": "https://launcher.mojang.com/v1/objects/50c9cc4af6d853d9fc137c84bcd153e2bd3a9a82/client-1.7.xml"
  644. },
  645. "type": "log4j2-xml"
  646. }
  647. },
  648. "mainClass": "net.minecraft.client.main.Main",
  649. "minecraftArguments": "--username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} --assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} --accessToken ${auth_access_token} --userProperties ${user_properties} --userType ${user_type}",
  650. "minimumLauncherVersion": 14,
  651. "releaseTime": "2015-12-03T17:24:39+08:00",
  652. "time": "2015-12-03T17:24:39+08:00",
  653. "type": "release",
  654. "clientVersion": "1.8.9"
  655. }

不要慌,真的只是看起来这么多而已。
image.png
我们要的是里面的“libraries”键对应的内容,但是这里面存放着两种不同类型的东西,统称为Minecraft运行所需的“库文件”。
下面是其中一种键的格式:

  1. {
  2. "downloads": {
  3. "artifact": {
  4. "path": "tv/twitch/twitch/6.5/twitch-6.5.jar",
  5. "sha1": "320a2dfd18513a5f41b4e75729df684488cbd925",
  6. "size": 55977,
  7. "url": "https://libraries.minecraft.net/tv/twitch/twitch/6.5/twitch-6.5.jar"
  8. }
  9. },
  10. "name": "tv.twitch:twitch:6.5"
  11. }

上面的这种格式中,我们可以只看“downloads”键,其对应了一个“artifact”键,然后就包括了四个键,分别是“path”:该库文件相对libraries文件夹的正确存放路径、“sha1”:该库文件的sha1校验码、“size”该库文件的大小、“url”:该库文件的下载地址。
从“artifact”中提取“url”,即可下载该库文件,然后记得将“libraries”文件夹的绝对路径拼接上“path”键对应的路径,作为该库文件的存放位置。
但是有的时候,您还会看到下面这样的情况,属于这种格式的变种:

  1. {
  2. "downloads": {
  3. "artifact": {
  4. "path": "org/lwjgl/lwjgl/lwjgl_util/2.9.2-nightly-20140822/lwjgl_util-2.9.2-nightly-20140822.jar",
  5. "sha1": "f0e612c840a7639c1f77f68d72a28dae2f0c8490",
  6. "size": 173887,
  7. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.2-nightly-20140822/lwjgl_util-2.9.2-nightly-20140822.jar"
  8. }
  9. },
  10. "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.2-nightly-20140822",
  11. "rules": [
  12. {
  13. "action": "allow",
  14. "os": {
  15. "name": "osx"
  16. }
  17. }
  18. ]
  19. },

多了一个“rules”键,然后是“action”键和另一个“os”键;“action”的值是“allow”,而“os”则指定了一个操作系统“osx”,即macOS。
翻译成人话就是,这个库,仅macOS系统上运行的Minecraft需要,其他平台并不需要。
注意,有时这个“action”后面跟的值是“disallow”,记得在您的代码中写好处理此的部分。


再往下则是其中另一种键的格式。

  1. {
  2. "downloads": {
  3. "classifiers": {
  4. "natives-linux": {
  5. "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-linux.jar",
  6. "sha1": "d898a33b5d0a6ef3fed3a4ead506566dce6720a5",
  7. "size": 578539,
  8. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-linux.jar"
  9. },
  10. "natives-osx": {
  11. "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar",
  12. "sha1": "79f5ce2fea02e77fe47a3c745219167a542121d7",
  13. "size": 468116,
  14. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar"
  15. },
  16. "natives-windows": {
  17. "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-windows.jar",
  18. "sha1": "78b2a55ce4dc29c6b3ec4df8ca165eba05f9b341",
  19. "size": 613680,
  20. "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-windows.jar"
  21. }
  22. }
  23. },
  24. "extract": {
  25. "exclude": [
  26. "META-INF/"
  27. ]
  28. },
  29. "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.2-nightly-20140822",
  30. "natives": {
  31. "linux": "natives-linux",
  32. "osx": "natives-osx",
  33. "windows": "natives-windows"
  34. },
  35. "rules": [
  36. {
  37. "action": "allow",
  38. "os": {
  39. "name": "osx"
  40. }
  41. }
  42. ]
  43. }

对于这种,“downloads”键下有一个“classifiers”键,此库文件被称作natives库文件,其他的库文件则是普通库文件
首先,既然这个“downloads”下面有一个“rules”键,那我们就应该先读取“rules”,用之前的办法判断该库是否需要下载,比如对我(Windows)来说这就是一个可以pass掉的natives库。

  1. {
  2. "downloads": {
  3. "classifiers": {
  4. "natives-linux": {
  5. "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar",
  6. "sha1": "7ff832a6eb9ab6a767f1ade2b548092d0fa64795",
  7. "size": 10362,
  8. "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar"
  9. },
  10. "natives-osx": {
  11. "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar",
  12. "sha1": "53f9c919f34d2ca9de8c51fc4e1e8282029a9232",
  13. "size": 12186,
  14. "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar"
  15. },
  16. "natives-windows": {
  17. "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar",
  18. "sha1": "385ee093e01f587f30ee1c8a2ee7d408fd732e16",
  19. "size": 155179,
  20. "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar"
  21. }
  22. }
  23. },
  24. "extract": {
  25. "exclude": [
  26. "META-INF/"
  27. ]
  28. },
  29. "name": "net.java.jinput:jinput-platform:2.0.5",
  30. "natives": {
  31. "linux": "natives-linux",
  32. "osx": "natives-osx",
  33. "windows": "natives-windows"
  34. }
  35. },

比如这里是一个我需要下载的natives库文件,我就需要读“classifiers”键,然后往下读“natives-windows”键,再读里面的“url”键来获取下载地址、“path”键来获取存放相对路径。

注意:包括普通库文件和natives库文件在内,有的库文件还区分“natives-windows-64”,这部分可以在代码中使用if嵌套解决。

natives库文件不需要在生成启动脚本时把路径加入到“-cp”后面,它们用不在此。您需要做的,是把natives库文件解压到一个指定目录,然后把这个指定目录填到前面JVM参数里的“-Djava.library.path”里面。这就是JVM里那个奇怪的natives库参数的处理办法。
众所周知,jar文件的本质就是zip文件,解压到一个指定目录是完全没有问题的。至于这个目录到底应该在哪,Mojang并没有规定,您可以参考以下两种做法:

  • Minecraft官方启动器:将natives库文件全部解压到一个临时目录,每次启动都重新解压。
  • 大部分第三方启动器:将其解压到位于游戏目录中的一个永久目录,只要玩家不手动删,不会重新解压。

记得在将启动脚本送到cmd里面之前先解压哦,不然Minecraft是无法启动的。您可以在读取JSON时用if语句完成这一点:如果有“classifiers”键,就当做natives库文件处理;否则当做普通库文件处理。


参考一下我使用Python完成这一步骤的代码:

  1. import threading, func # func为一在其他地方定义的类
  2. def download_libraries(version_json_path: str, libraries_path: str):
  3. """
  4. 读取版本JSON文件,并依据其中的内容下载补全libraries文件。下载操作由另一函数执行。
  5. :param libraries_path: 需要为libraries文件夹路径
  6. :param version_json_path: 需要为该版本的JSON路径。
  7. :return: 此函数无论是否顺利执行都不返回值。
  8. """
  9. dividing_str = "\\"
  10. with open(file=version_json_path, encoding="utf-8") as json_file:
  11. json_data = json.load(json_file)
  12. libraries_list = json_data['libraries']
  13. for i in libraries_list:
  14. file_temp_1 = i['downloads']
  15. if "classifiers" in file_temp_1:
  16. file_temp_1_ = file_temp_1['classifiers']
  17. if "natives-windows-64" in file_temp_1_:
  18. file_temp_2 = file_temp_1_['natives-windows-64']
  19. elif "natives-windows" in file_temp_1_:
  20. file_temp_2 = file_temp_1_['natives-windows']
  21. else:
  22. return None
  23. elif "artifact" in file_temp_1:
  24. file_temp_2 = file_temp_1['artifact']
  25. else:
  26. return None
  27. file_url = str(file_temp_2['url'])
  28. file_name_ = str(file_temp_2['path']).split("/")
  29. file_name = libraries_path + dividing_str.join(file_name_)
  30. file_sha1 = str(file_temp_2['sha1'])
  31. download_package = (file_url, file_name, file_sha1)
  32. print(download_package)
  33. func.threading_manager.acquire()
  34. threading.Thread(target=func.download_something, args=(0, download_package)).start()
  35. func.threading_manager.release()
  36. return None
  37. # threading模块用来创建子线程以下载,主线程能够继续循环下一项,可节省时间。
  38. # acquire和release用法均源自threading模块,您可以单独寻找该模块的教程以学习。
  1. import config # 一个写在其他地方的用来放语言文本的类
  2. def get_libraries_json(self: int, game_version_info: list):
  3. """
  4. 返回拼接成的“-cp”+普通库1+普通库2+……
  5. :param game_version_info: 该版本的相关信息组成的列表,需要:[0]版本名称,[1]版本JSON路径,[2]版本libraries路径,[3]版本游戏本体路径,[4]版本natives文件路径
  6. :return 从该JSON文件中提取出的,可直接拼接成脚本使用的代码片段
  7. """
  8. output_path = []
  9. game_version_name = game_version_info[0]
  10. game_version_json_path = game_version_info[1]
  11. libraries_path = game_version_info[2]
  12. minecraft_jar_path = game_version_info[3]
  13. natives_path = game_version_info[4]
  14. with open(file=game_version_json_path) as json_file:
  15. json_data = json.load(json_file)
  16. info_back_type_list = json_data['libraries']
  17. for i in info_back_type_list:
  18. if "rules" in i:
  19. data_temp_1 = list(i['rules'])
  20. if len(data_temp_1) == 1: # 如果“rules”键对应的列表长度为1,则该列表为允许
  21. allowing_list = list(dict(dict(data_temp_1[0])["os"])['name'])
  22. if not "windows" in allowing_list:
  23. continue
  24. if len(data_temp_1) == 2: # 如果对应的列表长度为2, 则列表第二项为禁止
  25. disallowing_list = list(dict(dict(data_temp_1[1])['os'])['name'])
  26. if "windows" in disallowing_list:
  27. continue
  28. # ↑那些规则是我自己推断出来的,不一定对每隔版本都适用
  29. data_temp_2 = dict(i['downloads'])
  30. if "classifiers" in data_temp_2:
  31. print("调试:0")
  32. func.zip_natives(0, data_temp_2, libraries_path, natives_path)
  33. continue
  34. elif not 'artifact' in data_temp_2:
  35. continue
  36. else:
  37. data_temp_2_ = dict(data_temp_2['artifact'])
  38. data_temp_3 = str(data_temp_2_['path'])
  39. data_temp_4 = list(data_temp_3.split("/"))
  40. dividing_str_1 = "\\"
  41. data_temp_5 = dividing_str_1.join(data_temp_4)
  42. real_path = libraries_path + data_temp_5
  43. if not real_path in output_path:
  44. output_path.append(real_path)
  45. output_path.append(minecraft_jar_path)
  46. dividing_str_2 = ";"
  47. output_path_str = dividing_str_2.join(output_path)
  48. print(config.lang_Functions_successfully_split_cp_path + game_version_name)
  49. print(output_path_str)
  50. return output_path_str

那,这边一部分也就搞定了,顺便解决了natives文件夹的问题。

在这里面找找,有没有哪个文件夹的名字里包含“natives”,这个文件夹大概率就是“-Djava.library.path=”需要的参数路径,把文件夹的路径填进去吧。

现在您知道为什么可以这么办了嘛?因为第三方启动器的创作者也跟我们的思路一样!如果你找到了这样一个包括“natives”字样的文件夹,说明该启动器的作者也是把natives库文件解压到了这样一个永久目录!
哦对了,记得在-cp部分,每两个绝对路径中间是用英文“;”隔开的,并且在最后要加上该版本client.jar的路径,否则JVM会报错“找不到主类”。
主类就是下面那个东西……

主类


主类是最简单的部分了。我们再次拿出这张图:
image.png
看到上面那个“mainClass”了嘛?
那个对应的“net.minecraft.client.main.Main”就是主类,接在-cp部分的后面就行,主类搞定。

Minecraft参数


还是上面那张图,先别往下滑!
“minecraftArguments”键,后面跟着的,就是Minecraft参数的模板。我们需要在这个模板上替换掉一些东西,下面是Minecraft 1.8.9的模板。

  1. --username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} --assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} --accessToken ${auth_access_token} --userProperties ${user_properties} --userType ${user_type}

(新版本的)参数通常有:

  • —username 后接用户名。
  • —version 后接游戏版本。
  • —gameDir 后接游戏路径。
  • —assetsDir 后接资源文件路径。
  • —assetIndex 后接资源索引版本。
  • —uuid 后接用户UUID。
  • —accessToken 后接登录令牌。
  • —userType 后接用户类型。
  • —versionType 后接版本类型,会显示在游戏主界面右下角。
  • —width 后接窗口宽度。
  • —height 后接窗口高度。
  • —server 后接服务器地址,游戏进入时将直接连入服务器
  • —port 后接服务器的端口号
  • 等等,可能因版本而异,具体应参考当前版本json文件内提供的信息

连带着${abaabaabaaba}这个整体,一起替换成其他东西即可。并不是所有的参数都必须提供,比如你可以不写—width和—height,游戏还是能启动的。
啊对了,有的参数可以直接从版本JSON中顺便读取,比如—assetIndex后面就跟“assets”键对的“1.8”就行,而—versionType可以跟“type”键的值“release”;另外有的参数我们目前提供不了的,比如—uuid,可以去找一个UUID生成网站暂时随意填一个,—accessToken可以先{}这样空着,而—userType可以填legacy,就是离线模式了。
(其实—accessToken是令牌,我们现在获取不到令牌,所以就算—userType填了mojang——验证不了身份照样进离线模式,懒得话一律写mojang就行了)
Python中替换长字符串中的短字符串可以使用replace语句。由于不同版本的上面参数有差异,我就不放出来了,这一步毕竟也不是很难(?真的

拼接


上面五个,拼起来,然后print出来,复制一下敲到cmd里试试叭!