教程/編寫啟動器

出自Minecraft Wiki
前往: 導覽搜尋
Iron Pickaxe Revision 2.png
該頁面編輯正在進行中,並且需要你的幫助
請幫助這篇文章的創作。
討論頁可能包含一些建議。
本教程部分內容參考了wiki.vg
Information icon.svg
此特性為Java版獨有。

本教程介紹如何製作Java版啟動器,並假定你已掌握任何一門編程語言。

基本原理[編輯 | 編輯原始碼]

因為Minecraft製作時採用了「啟動器+遊戲文件」的模式:

  • 將遊戲文件單獨存儲,而通過啟動器調用JVM(Java Virtual Machine)執行遊戲主文件並傳入一些遊戲參數來啟動Minecraft。
  • 遊戲依賴庫文件以及遊戲資源文件由啟動器補全。
  • 玩家登錄認證由啟動器完成。

這使得我們能通過編寫第三方啟動器來接管遊戲文件管理和登錄認證。

準備[編輯 | 編輯原始碼]

要編寫一個啟動器,你需要:

  • 一門編程語言其開發環境
  • Java運行時環境(Java Runtime Environment,JRE),可於Java官網下載

並擁有支持下列功能的庫:

  • 解析JSON文檔(得到啟動參數的關鍵)
  • 解壓文件(解壓natives文件,也可使用連結外部程序替代)
  • 網絡庫(正版驗證、外觀管理)

啟動參數[編輯 | 編輯原始碼]

啟動參數將傳入java.exejavaw.exe,使JVM通過傳入的主類正確地啟動遊戲。

啟動參數分為JVM參數和Minecraft參數兩部分。

獲取參數[編輯 | 編輯原始碼]

運行此指令可獲取當前運行的Minecraft進程的參數:

wmic process where caption="javaw.exe" get caption,commandline /value>args.txt

此時args.txt大致有這樣的文件內容:

Caption=javaw.exe
CommandLine="<javaw或java路径>" -XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump "-Dos.name=Windows 10" -Dos.version=10.0 -Xss1M -Djava.library.path=<natives文件夹路径> -Dminecraft.launcher.brand=minecraft-launcher -Dminecraft.launcher.version=2.1.3674 -cp <一大串用;分开的文件路径> -Xmx2G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -Dlog4j.configurationFile=<log4j配置文件路径> net.minecraft.client.main.Main --username <用户名> --version <游戏版本号> --gameDir <游戏路径> --assetsDir <资源文件路径> --assetIndex <资源索引版本> --uuid <用户uuid> --accessToken <登录令牌> --userType mojang --versionType release

僅保留CommandLine後的內容,然後將該文件後綴改為.bat,雙擊即可啟動Minecraft。

運行前注意文件編碼。並注意官方啟動器的解壓出的natives庫文件存儲在臨時資料夾下,可能因刪除導致無法啟動。

JVM參數[編輯 | 編輯原始碼]

-X-XX參數[編輯 | 編輯原始碼]

配置JVM,如GC等:

  • -Xmx1024m 最大堆大小為1024MB
  • -Xmn128m 新生代堆大小為128MB
  • -XX:+UseG1GC 開啟G1
  • -XX:-UseAdaptiveSizePolicy 自動選擇年輕代區大小和相應的Survivor區比例
  • -XX:-OmitStackTraceInFastThrow 省略異常棧信息從而快速拋出

-D參數[編輯 | 編輯原始碼]

配置JVM系統屬性,格式為-D<name>=<value>

  • Dos.name=Windows 10 -Dos.version=10.0 當前系統名稱及版本
  • -Dminecraft.launcher.brand=minecraft-launcher -Dminecraft.launcher.version=2.1.3674 當前啟動器名稱及版本
  • -Dlog4j.configurationFile=<文件路径>\client-1.12.xml 遊戲日誌配置文件
  • -Djava.library.path=<natives文件夹路径> 當前系統下遊戲運行所需的動態連結庫

-cp參數[編輯 | 編輯原始碼]

全稱為-classpath,後為所有當前版本Minecraft的普通庫文件路徑及遊戲主文件,中間用;隔開。

Minecraft參數[編輯 | 編輯原始碼]

以主類名開頭,通常為net.minecraft.client.main.Main,若安裝Mod加載器則一般為net.minecraft.launchwrapper.Launch

參數通常有:

  • --username 後接用戶名
  • --version 後接遊戲版本
  • --gameDir 後接遊戲路徑
  • --assetsDir 後接資源文件路徑
  • --assetIndex 後接資源索引版本
  • --uuid 後接用戶uuid
  • --accessToken 後接登錄令牌
  • --userType 後接用戶類型
  • --versionType 後接版本類型,會顯示在遊戲主介面右下角
  • 等等,可能因版本而異,具體應參考當前版本json文件內提供的信息

遊戲文件[編輯 | 編輯原始碼]

文件結構大致如下:

列表

以上文件結構經過簡化,具體可參考.minecraft頁面。

JSON文件[編輯 | 編輯原始碼]

Minecraft大多數信息使用JSON文檔存儲管理,使用這些JSON文件可以獲取下載、管理及啟動所需的大部分信息。

版本清單文件[編輯 | 編輯原始碼]

該文件可以在mojang官方伺服器下載:

https://launchermeta.mojang.com/mc/game/version_manifest.json

其中,latest中為當前最新版本,分為發布版和快照版。versions後為所有可下載的遊戲版本,url後為該版本的json文件下載地址。

版本json文件[編輯 | 編輯原始碼]

該文件一般下載後存儲在.minecraft/versions資料夾下,有如下內容:

rules
用於可選條目,使用features判斷並應用其action
arguments
1.13後新增鍵,舊版本為gameArguments,且不提供JVM參數及rules規則。
${****}
字符串模板,替換相應內容來使用。
assetIndex
當前版本的資源文件索引,包含其下載地址等信息。
downloads
遊戲主文件,分為客戶端及服務端,包含其下載地址等信息。
libraries
遊戲所有依賴庫,包含其下載地址等信息。
downloads下均含有artifact鍵,有些含有classifiers鍵。
  • 只含有artifact鍵的為-cp參數後所需拼接的路徑,注意path鍵中為不完整路徑,請補全為完整路徑。
  • 含有classifiers鍵的為natives庫,在遊戲啟動前將對應平台的含有jar文件解壓至natives資料夾。
logging
log4j配置文件,包含其下載地址等信息。
mainClass
主類名。

資源索引文件[編輯 | 編輯原始碼]

一般存儲於.minecraft/assets/indexes路徑下,用於指示objects文件的信息及其下載地址。

該文件的下載地址等信息存儲在版本json文件中,該文件可能需要不定期更新。

內容如下:

{
    "objects": {
        "icons/icon_16x16.png": {
            "hash": "bdf48ef6b5d0d23bbb02e17d04865216179f510a",
            "size": 3665
        }
        ...
    }
}

objects文件的下載地址為:

http://resources.download.minecraft.net/<hash的前兩位字符>/<hash>

存儲路徑為:

.minecraft/assets/objects/<hash的前两位字符>/<hash>

並在.minecraft/assets/virtual/legacy/留下一份拷貝。

啟動器配置文件[編輯 | 編輯原始碼]

該文件不是必須的,但它是官方啟動器的配置文件。所以可用於與官方啟動器數據互通,以及forge安裝檢驗。

最簡單的配置文件為:

 {
    "profiles": {
        "(Default)": {
            "gameDir": "<游戏目录>",
            "lastVersionId": "1.14.1",
            "name": "(Default)"
        }
    },
    "selectedProfileName": "(Default)",
    等等乱七八糟的配置
}

profiles為啟動器中創建的所有配置文件。

遊戲主文件[編輯 | 編輯原始碼]

通常存儲於.minecraft/versions/<version>/<version>.jar,下載地址等信息存儲在版本json文件中,下載時注意將該文件重命名為對應版本號。

依賴庫文件[編輯 | 編輯原始碼]

通常存儲於.minecraft/libraries/路徑下,下載地址等信息存儲在版本json文件中。

普通庫文件[編輯 | 編輯原始碼]

在啟動前需拼接在啟動參數的-cp參數後。

natives庫文件[編輯 | 編輯原始碼]

在啟動前需解壓至natives路徑下。

資源文件[編輯 | 編輯原始碼]

通常存儲在.minecraft/assets/objects/,並在.minecraft/assets/virtual/legacy/有一份拷貝。

下載地址等信息存儲在資源索引文件中。

這些文件可能在發布後更新,留意更新資源索引文件來更新他們。

正版驗證[編輯 | 編輯原始碼]

Minecraft自1.6後使用了Yggdrasil驗證方法,驗證伺服器為:

https://authserver.mojang.com

驗證時需要:

  • POST請求
  • Content-Type設定為application/json
  • 負載以JSON編碼

若請求成功則返回狀態碼200及一個JSON文檔。

若失敗則返回錯誤信息:

{
   "error": "错误简要描述",
   "errorMessage": "向用户显示的长描述",
   "cause": "错误原因" // 可选的
}

具體錯誤信息可參考https://wiki.vg/ZH:Authentication#錯誤。

驗證賬號密碼[編輯 | 編輯原始碼]

後綴:
/authenticate
負載:
{
   "agent": {
       "name": "Minecraft",                // 默认为Minecraft,可选
       "version": 1                        // 未来可能会改(不会)
   },
   "username": "mojang用户名",              // 可以是邮箱地址或旧版mojang用户名
   "password": "密码",
   "clientToken": "客户端标识符",            // 可选的,用于复用该值
}
響應:
{
   "accessToken": "随机令牌",
   "clientToken": "客户端标识符",
   "availableProfiles": [
       {
           "id": "profile identifier",
           "name": "玩家名"
       }
   ],
   "selectedProfile": {
       "id": "不含-的uuid",
       "name": "玩家名"
   }
}

(有刪節,參考https://wiki.vg/ZH:Authentication#Authentication)

你可以存儲這個clientToken,用來標識這個客戶端。

此處獲取的uuidaccessToken即為啟動參數中所需的,傳入你剛剛獲得的值,啟動遊戲後便能發現已顯示正版外觀,即完成了正版登錄。

檢驗令牌有效性[編輯 | 編輯原始碼]

accessToken具有有效期,可能因為一些原因失效。你可以發送請求,驗證當前accessToken是否還是有效的.

後綴:
/validate
負載:
{
   "accessToken": "valid accessToken",
   "clientToken": "associated clientToken" //可选的
}
響應:

如果狀態碼為204 No Content則有效,而403 Forbidden為已失效。

刷新令牌[編輯 | 編輯原始碼]

刷新一個accessToken,用於保持用戶在遊戲會話之間登錄。

後綴:
/refresh
負載:
{
   "accessToken": "valid accessToken",
   "clientToken": "associated clientToken" //可选的
}
響應:
{
   "accessToken": "随机令牌",
   "clientToken": "客户端标识符",
   "availableProfiles": [
       {
           "id": "profile identifier",
           "name": "玩家名"
       }
   ],
   "selectedProfile": {
       "id": "不含-的uuid",
       "name": "玩家名"
   }
}

(有刪節,參考https://wiki.vg/ZH:Authentication#Refresh)

與「驗證賬號密碼」中相同。

啟動遊戲[編輯 | 編輯原始碼]

  1. 首先必須保證啟動參數中出現的所有文件及提供的資源索引文件中的object文件都存在且未被損壞。
  2. 選定一個natives路徑,可以自由選定,也可像官方啟動器一樣使用臨時路徑。將natives庫文件解壓至該路徑,並將該路徑使用-Djava.library.path=傳入遊戲。
  3. 完成正版驗證,得到uuid及accessToken
  4. 拼接啟動參數,創建遊戲進程
  5. 處理遊戲輸出及遊戲錯誤

支持forge等Mod加載器[編輯 | 編輯原始碼]

運行forge等Mod加載器的安裝包後,可以發現:

  • 啟動器配置文件中添加了一條新安裝的配置
  • .minecraft/libraries/資料夾中多了一些文件
  • .minecraft/versions/資料夾中多了一個版本json文件(也可能會有jar文件)

額外的版本json文件[編輯 | 編輯原始碼]

該文件相比原版的版本json文件文件多了inheritsFromjar鍵,而且其他鍵內容明顯是不完整的。

inheritsFrom
該參數指定了當前版本所繼承的原版版本,意思為除此版本json文件外,同時使用inheritsFrom中指定的版本json文件內容。即,-cp參數後同時包含兩個版本json文件指定的普通庫文件,且natives庫文件也同時包含兩個版本json文件指定的,且該版本json文件優先於原版版本json文件
jar
該參數指定了-cp參數後的遊戲主文件
除此之外,版本json文件中的libraries鍵的格式也有些不一樣了,如:
{
  "name": "org.ow2.asm:asm-all:5.0.3",
  "serverreq": true
},
{
  "name": "jline:jline:2.13",
  "url": "http://files.minecraftforge.net/maven/",
  "checksums": [
    "2d9530d0a25daffaffda7c35037b046b627bb171"
  ],
  "serverreq": true,
  "clientreq": false
}

不再有downloads鍵了,只剩下nameurl,文件路徑及下載路徑需要根據一定規則拼接。

name鍵的格式為:

<package>:<name>:<version>

我們將它變形重組一下:

<package>/<name>/<version>/<name>-<version>.jar

前方接上.minecraft/libraries/即為文件路徑,而接上url的內容即為下載地址。

serverreqclientreq用於區分客戶端和服務端的需要。

優化下載[編輯 | 編輯原始碼]

有時,在官方伺服器下載文件會很緩慢,這時可以考慮使用第三方鏡像下載。

當前常用的第三方鏡像有:

另外,Minecraft的依賴庫文件資源索引文件很多為小文件,可以考慮使用多線程下載來優化速度。

外觀管理[編輯 | 編輯原始碼]

外觀管理需要使用Mojang API:

api.mojang.com

可通過發送GET請求獲得Mojang API的狀態:

https://status.mojang.com/check

獲取外觀及披風[編輯 | 編輯原始碼]

可通過發送GET請求獲得外觀及披風地址:

https://sessionserver.mojang.com/session/minecraft/profile/<uuid>
響應:
{
   "id": "<配置标识符>",
   "name": "<玩家名>",
   "properties": [ 
       {
           "name": "textures",
           "value": "<base64字符串>"
       }
   ]
}

解碼該base64字符串,可獲得另一JSON文檔:

{
   "timestamp": <java time in ms>,
   "profileId": "<配置uuid>",
   "profileName": "<玩家名>",
   "textures": {
       "SKIN": {
           "url": "<玩家皮肤URL>"
       },
       "CAPE": {
           "url": "<玩家披风URL>"
       }
   }
}

更換外觀[編輯 | 編輯原始碼]

發送POST請求至:

https://api.mojang.com/user/profile/<uuid>/skin
頭:
Authorization: Bearer <access token>
負載:
model=<""/"slim">&url=<皮肤url>

空字符串為Steve模型,「slim」為Alex模型。

上傳外觀[編輯 | 編輯原始碼]

發送PUT請求至:

https://api.mojang.com/user/profile/<uuid>/skin
頭:
Authorization: Bearer <access token>
負載:

由兩部分組成:

  • model:人物模型,空字符串為Steve模型,「slim」為Alex模型。
  • file:原始圖像文件數據

重置外觀[編輯 | 編輯原始碼]

發送DELETE請求至:

https://api.mojang.com/user/profile/<uuid>/skin
頭:
Authorization: Bearer <access token>