Minecraft Wiki

除另有声明,转载时均必须注明出处若簡繁轉換出錯,請以遊戲內為準请勇于扩充与修正内容有兴趣逛逛我们的微博沟通交流,欢迎到社区专页需要协助,请在告示板留言

了解更多

Minecraft Wiki
Advertisement
Iron Pickaxe
該頁面的編輯正在進行中。 討論

請幫助我們擴充或改進這篇文章。

本教學部分內容參考了wiki.vg

Information icon
此特性為Java版獨有。

本教學介紹如何製作Java版啟動器,並假定你已掌握任何一門編程語言(C#最好,因為它Java有較多共同點,容易入門)。

基本原理

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

  • 將遊戲檔案單獨儲存,而透過啟動器調用JVM(Java Virtual Machine,Java虛擬機)執行遊戲主檔案並傳入一些遊戲參數來啟動Minecraft。
  • 遊戲依賴庫檔案以及遊戲資源檔案由啟動器補全。
  • 玩家離線登入為啟動器完成,正版登入則需調用Mojang API。

這使得我們能透過編寫第三方啟動器來接管遊戲檔案管理和登入認證。

準備

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

  • 一門編程語言其開發環境。
  • Java執行時環境(Java Runtime Environment,一般使用它的縮寫JRE),支持最新版本的Java 18可於甲骨文官網下載;支持老版本的Java 8可於Java官網下載。

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

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

啟動參數

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

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

這對debug很有幫助,另外參考官方啟動器的方法能得到更優良的參數。

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的普通庫檔案路徑及遊戲主檔案,中間在Windows下用;隔開,其它系統下用:隔開。

Minecraft參數

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

參數通常有:

  • --username 後接使用者名稱。
  • --version 後接遊戲版本。
  • --gameDir 後接遊戲路徑。
  • --assetsDir 後接資源檔案路徑。
  • --assetIndex 後接資源索引版本。
  • --uuid 後接使用者UUID。
  • --accessToken 後接登入令牌。
  • --userType 後接使用者類型。
  • --versionType 後接版本類型,會顯示在遊戲主介面右下角。
  • --width 後接窗口寬度。
  • --height 後接窗口高度。
  • --server 後接伺服器地址,遊戲進入時將直接連入伺服器
  • --port 後接伺服器的端口號
  • 等等,可能因版本而異,具體應參考目前版本json檔案內提供的資訊

取得參數

執行此指令可取得目前執行的Minecraft進程的參數:

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

此時args.txt或args_java.txt中大致有這樣的檔案內容:

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 --width <窗口宽度> --height <窗口高度>

僅保留CommandLine=後的內容,然後將該檔案後綴改為Shell可識別的,如:.bat,用cmd指令即可啟動Minecraft。

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

遊戲檔案

列表

JSON檔案

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

版本清單檔案

該檔案可以在mojang官方伺服器下載:

https://piston-meta.mojang.com/mc/game/version_manifest.json

其中,latest中為目前最新版本,分為發佈版和快照版。versions後為所有可下載的遊戲版本,url後為該版本的json檔案下載地址。

版本json檔案

主條目:/version.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/有一份拷貝。

下載地址等資訊儲存在資源索引檔案中。

這些檔案可能在發佈後更新,留意更新資源索引檔案來更新他們。

正版驗證

Mojang 帳號

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)

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

Microsoft 帳號

Minecraft正在遷移至微軟賬號。自2020年12月起,所有新賬號已經使用了新版系統,舊的賬號也將在之後遷移。新版系統需要多個步驟以及不同的令牌,但是最後你還是會獲得一個普通的Mineceaft令牌。啟動遊戲本身並沒有改變。

微軟 Oauth 流程

第一步,我們登入微軟賬號。這一步必須在瀏覽器/網頁視圖中完成!用戶端 id(client_id)被硬編碼為(00000000402b5328),也就是 Minecraft 這個遊戲的id,無需變更。

https://login.live.com/oauth20_authorize.srf
 ?client_id=00000000402b5328
 &response_type=code
 &scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL
 &redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf

使用者需要在此處輸入使用者名稱(郵箱、手機號或別的登入方法)以及密碼,從而在瀏覽器窗口中登陸微軟賬號。如果使用者名稱和密碼正確,那麼使用者會被重新導向。在這一步中使用者不需要擁有Minecraft,那會在之後再檢查。

重新導向連結看起來會像這樣:

https://login.live.com/oauth20_desktop.srf?code=codegoeshere&lc=1033

你需要提取出其中的code參數,這是你的微軟授權碼。

授權碼 -> 授權令牌

下一步是從授權碼中取得授權令牌。由於安全原因,這一步不在瀏覽器中完成。

POST https://login.live.com/oauth20_token.srf

被提交的資料:

 Map<Object, Object> data = Map.of(
    "client_id", "00000000402b5328", // 还是Minecraft客户端id
    "code", authcode, // 第一步中获取的代码
    "grant_type", "authorization_code",
    "redirect_uri", "https://login.live.com/oauth20_desktop.srf",
    "scope", "service::user.auth.xboxlive.com::MBI_SSL"
 );

不要忘記設定Content-Type: application/x-www-form-urlencoded

響應看起來會像這樣:

 {
   "token_type":"bearer",
   "expires_in":86400,
   "scope":"service::user.auth.xboxlive.com::MBI_SSL",
   "access_token":"token here",
   "refresh_token":"M.R3_BAY.token here",
   "user_id":"889ed4a3d844f672",
   "foci":"1"
 }

我們需要關注到這裏的access_token

用於刷新的token

您可以使用您在之前請求中收到的refresh_token取得新access_token。只需調用與以前相同的API,請切換刷新的令牌authorization_code和授予類型的代碼refresh_token

 POST https://login.live.com/oauth20_token.srf
  client_id=<your client id>
  &client_secret=<your client secret>
  &refresh_token=<refresh token from previous step>
  &grant_type=refresh_token
  &redirect_uri=<your redirect uri>

(響應與請求access_token一致)

XBox Live 身份驗證

現在,我們已透過微軟身份驗證,可以向xbox live進行身份驗證。

我們需要發送:

POST https://user.auth.xboxlive.com/user/authenticate
 {
    "Properties": {
        "AuthMethod": "RPS",
        "SiteName": "user.auth.xboxlive.com",
        "RpsTicket": "d=<access_token>" // 第二步中获取的访问令牌
    },
    "RelyingParty": "<nowiki>http://auth.xboxlive.com</nowiki>",
    "TokenType": "JWT"
 }

同樣,也得設定Content-Type: application/json以及Accept: application/json

響應看起來會像這樣:

 {
   "IssueInstant":"2020-12-07T19:52:08.4463796Z",
   "NotAfter":"2020-12-21T19:52:08.4463796Z",
   "Token":"token", // 保存它,这是你的xbl令牌
   "DisplayClaims":{
      "xui":[
         {
            "uhs":"uhs" // 保存它
         }
      ]
   }
 }

我們需要儲存這裏的Tokenuhs。uhs是user hash的縮寫,為使用者資訊哈希值。

XSTS 身份驗證

現在,我們已經透過XBL進行了身份驗證,我們需要取得XSTS令牌,使用它可以登入Minecraft。

POST https://xsts.auth.xboxlive.com/xsts/authorize
 {
    "Properties": {
        "SandboxId": "RETAIL",
        "UserTokens": [
            "xbl_token" // from above
        ]
    },
    "RelyingParty": "rp://api.minecraftservices.com/",
    "TokenType": "JWT"
 }

同樣還是設定Content-Type: application/json以及Accept: application/json

響應看起來會像這樣:

 {
   "IssueInstant":"2020-12-07T19:52:09.2345095Z",
   "NotAfter":"2020-12-08T11:52:09.2345095Z",
   "Token":"token", // 保存它,这是你的xsts令牌
   "DisplayClaims":{
      "xui":[
         {
            "uhs":"" // 与上个请求相同
         }
      ]
   }
}

獲得 Minecraft 訪問令牌

現在,我們終於可以回到Minecraft身上了,上一各請求中取得的XSTS令牌允許我們驗證Minecraft。

POST https://api.minecraftservices.com/authentication/login_with_xbox
 {
    "identityToken": "XBL3.0 x=<uhs>;<xsts_token>"
 }

響應:

 {
  "username" : "some uuid", // 这并不是账号的UUID
  "roles" : [ ],
  "access_token" : "minecraft access token", // JWT,Minecraft访问令牌
  "token_type" : "Bearer",
  "expires_in" : 86400
 }

這個訪問令牌(access_token)允許我們啟動遊戲,但是,在啟動遊戲之前——我們仍然需要檢查該使用者是否擁有 Minecraft,此前的眾多步驟都沒有進行這步檢查。

檢查遊戲擁有情況

那麼現在讓我們使用Minecraft的訪問令牌來檢查該賬號是否包含產品許可。

GET https://api.minecraftservices.com/entitlements/mcstore

訪問令牌在驗證檔案頭中:Authorization: Bearer token

如果使用者擁有遊戲,那麼響應會看起來像這樣:

 {
  "items" : [ {
    "name" : "product_minecraft",
    "signature" : "jwt sig"
  }, {
    "name" : "game_minecraft",
    "signature" : "jwt sig"
  } ],
  "signature" : "jwt sig",
  "keyId" : "1"
 }

第一個jwts會包含值:

 {
  "typ": "JWT",
  "alg": "RS256",
  "kid": "1"
 }.{
  "signerId": "2535416586892404",
  "name": "product_minecraft"
 }.[Signature]

最後一個jwt看起來是這樣解碼的:

 {
  "typ": "JWT",
  "alg": "RS256",
  "kid": "1"
 }.{
  "entitlements": [
    {
      "name": "product_minecraft"
    },
    {
      "name": "game_minecraft"
    }
  ],
  "signerId": "2535416586892404"
 }.[Signature]

如果該賬號沒有擁有遊戲,那麼項目為空。

取得玩家 UUID

啟動遊戲還需要玩家的UUID,我們目前也沒有獲得。不過只要玩家擁有遊戲,就一定有辦法取得其UUID:

現在我們知道了該賬號擁有遊戲,那麼可以取得他的檔案來得到UUID:

GET https://api.minecraftservices.com/minecraft/profile

同樣,訪問令牌在驗證檔案頭中:Authorization: Bearer token

如果賬號擁有遊戲,響應看起來會像這樣:

 {
  "id" : "986dec87b7ec47ff89ff033fdb95c4b5", // 账号的真实UUID
  "name" : "HowDoesAuthWork", // 该账号的Minecraft用户名
  "skins" : [ {
    "id" : "6a6e65e5-76dd-4c3c-a625-162924514568",
    "state" : "ACTIVE",
    "url" : "<nowiki>http://textures.minecraft.net/texture/1a4af718455d4aab528e7a61f86fa25e6a369d1768dcb13f7df319a713eb810b</nowiki>",
    "variant" : "CLASSIC",
    "alias" : "STEVE"
  } ],
  "capes" : [ ]
 }

否則會看起來像這樣:

 {
  "path" : "/minecraft/profile",
  "errorType" : "NOT_FOUND",
  "error" : "NOT_FOUND",
  "errorMessage" : "The server has not found anything matching the request URI",
  "developerMessage" : "The server has not found anything matching the request URI"
 }

那麼這樣就可以知道所有必要的資料(Minecraft訪問令牌、使用者名稱和UUID)來啟動遊戲了。干的漂亮!

(參考 https://wiki.vg/Zh:Microsoft_Authentication_Scheme

啟動遊戲

  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請求獲得外觀及披風地址:

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>
Advertisement