Skip to content

Latest commit

 

History

History
335 lines (313 loc) · 10 KB

Guide2.md

File metadata and controls

335 lines (313 loc) · 10 KB

登录与启动

游戏启动前,需要玩家登录账户,而账户又分为很多种
总体分为新版OAuth登录与旧方式登录

目前登录微软账户需要使用新版OAuth流程

OAuth 微软登录 -> XBox Xbox验证 -> XSTS 好像是Xbox附属验证 -> Token 客户端密匙 -> Profile 账户信息

走完这套流程后就能拿到游戏UUID与token来启动游戏了

OAuth需要去申请一个client_key才能使用
注册一个Azure 账户 点击Microsoft Entra ID

注册一个应用

然后按照下面设置


复制客户端ID,后面要用到

然后开始登录,准备一个HttpClient,开始请求,下面的{类型}都需要替换为对应的东西

OAuth登录新账户

  • OAuth
POST https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode
Content-Type: application/x-www-form-urlencoded

client_id={client_key}&scope=XboxLive.signin offline_access

结果返回

{
    "user_code": "5MTFVRR7",
    "device_code": "BAQABIQEAAADnfolhJpSnRYBxxxxA",
    "verification_uri": "https://www.microsoft.com/link",
    "expires_in": 900,
    "interval": 5,
    "message": "To sign in, use a web browser to open the page https://www.microsoft.com/link and enter the code 5MTFVRR7 to authenticate."
}

其中user_code需要展示出去,device_code需要储存,然后用户点击verification_uri链接,填写user_code进行登录
然后在此期间,需要定时interval秒请求

POST https://login.microsoftonline.com/consumers/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

client_id={client_key}&grant_type=urn:ietf:params:oauth:grant-type:device_code&code={device_code}

结果返回分几种
表示用户还没有登录成功,你需要继续等待后再次请求

{
    "error": "authorization_pending",
    "error_description": "AADSTS70016: Pending end-user authorization.\r\nTrace ID: aff0fcc8-257a-400c-a275-bba4a6a72600\r\nCorrelation ID: f820aa6d-9dd7-4fab-8e68-5521013aea2e\r\nTimestamp: 2019-04-04 16:04:58Z",
    "error_codes": [
        70016
    ],
    "timestamp": "2019-04-04 16:04:58Z",
    "trace_id": "aff0fcc8-257a-400c-a275-bba4a6a72600",
    "correlation_id": "f820aa6d-9dd7-4fab-8e68-5521013aea2e"
}

表示用户已经登录成功了

{
    "token_type": "Bearer",
    "scope": "XboxLive.signin offline_access",
    "expires_in": 3600,
    "ext_expires_in": 3600,
    "access_token": "{token1}",
    "refresh_token": "{token2}",
    "id_token": "{token3}"
}

access_token用与后续请求,refresh_token用于刷新用户密钥,也就是免再次登录

  • Xbox登录
POST https://user.auth.xboxlive.com/user/authenticate
Content-Type: application/json

{
    "Properties": {
        "AuthMethod": "RPS",
        "SiteName": "user.auth.xboxlive.com",
        "RpsTicket": "d={token1}"
    },
    "RelyingParty": "http://auth.xboxlive.com",
    "TokenType": "JWT"
}

结果返回

{
   "IssueInstant":"2020-12-07T19:52:08.4463796Z",
   "NotAfter":"2020-12-21T19:52:08.4463796Z",
   "Token": "{xboxtoken}",
   "DisplayClaims":{
        "xui":[
            {
                "uhs": "{xboxuhs}"
            }
        ]
   }
}

其中Token需要保存

  • XSTS
POST https://xsts.auth.xboxlive.com/xsts/authorize
Content-Type: application/json

{
    "Properties": {
        "SandboxId": "RETAIL",
        "UserTokens": [
            "{xboxtoken}"
        ]
    },
    "RelyingParty": "rp://api.minecraftservices.com/",
    "TokenType": "JWT"
}

结果返回

{
   "IssueInstant":"2020-12-07T19:52:09.2345095Z",
   "NotAfter":"2020-12-08T11:52:09.2345095Z",
   "Token": "{xststoken}",
   "DisplayClaims":{
        "xui":[
            {
                "uhs": "{xstsuhs}"
            }
        ]
    }
}

其中TokenDisplayClaims.xui.uhs需要保存

  • 游戏Token
POST https://api.minecraftservices.com/authentication/login_with_xbox
Content-Type: application/json

{
    "identityToken": "XBL3.0 x={xstsuhs};{xststoken}"
}

结果返回

{
    "username" : {username},
    "roles" : [ ],
    "access_token" : "{gametoken}",
    "token_type" : "Bearer",
    "expires_in" : 86400
}

其中access_token需要保存

  • 游戏Profile
GET https://api.minecraftservices.com/minecraft/profile
Authorization: Bearer {gametoken}

结果返回

{
  "id" : "cced95f30a844377b8c18e60cf1b3fea",
  "name" : "Color_yr",
  "skins" : [ {
    "id" : "89fe094b-6511-4117-b9d4-46cf5ba9d99c",
    "state" : "ACTIVE",
    "url" : "http://textures.minecraft.net/texture/be9b4b65c81c47cda6effe173a90abc32864e4b147d37a7a3854287393c48bec",
    "textureKey" : "be9b4b65c81c47cda6effe173a90abc32864e4b147d37a7a3854287393c48bec",
    "variant" : "SLIM"
  } ],
  "capes" : [ {
    "id" : "5af20372-79e0-4e1f-80f8-6bd8e3135995",
    "state" : "ACTIVE",
    "url" : "http://textures.minecraft.net/texture/2340c0e03dd24a11b15a8b33c2a7e9e32abb2051b2481d0ba7defd635ca7a933",
    "alias" : "Migrator"
  } ],
  "profileActions" : { }
}

这里就是用户信息了,需要取出id在启动时充当auth_uuid
注意Bearer后面是带一个空格的,不要漏了 最后对应的启动参数替换值

auth_access_token -> gametoken
auth_uuid -> id
auth_player_name -> username

OAuth刷新密钥

该步骤需要OAtuh步骤中的,refresh_token,然后请求

POST https://login.microsoftonline.com/consumers/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

client_id={client_key}&grant_type=refresh_token&refresh_token={token2}

返回结果和初次OAuth登录一样,同样需要重新存储refresh_token,也就是登录一次refresh_token要刷新一次
后面的步骤就是一模一样的了

第三方登录

例如统一通行证Nide8littleskin皮肤站这种外置登录
都是用了旧版登录方式

旧版登录方式很简单,只需要请求

POST https://验证地址/authserver/authenticate
Content-Type: application/json

{
    // 可选
    "agent": {	
        // 启动器名称
        "name": "ColorMC",	
        // 启动器版本
        "version": "1.25"
    },
    "username": "用户名",
    "password": "密码",
    // 客户端UUID
    "clientToken": "XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX"
}

注意,该部分为明文传输,请一定要使用https而不是http 结果返回

{
    // 访问令牌
    "accessToken": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",	
    // 客户端UUID
    "clientToken": "XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX",	
    "selectedProfile": {
        "id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",	//玩家UUID
        "name": "游戏ID"
    }
}

accessToken是需要保存的东西,建议clientToken不为空的发送到服务器,方便后续操作

刷新token使用

POST  https://验证地址/authserver/refresh
Content-Type: application/json

{
    "accessToken": "{accessToken}"
    "clientToken": "{clientToken}"
}

结果返回和登录一样的东西

游戏启动

游戏启动需要JAVA,JAVA的下载与安装不在该教程范围内 启动前需要检查所有游戏文件,运行库,资源文件,游戏核心等,然后开始拼接启动参数
启动参数主要由几部分组成

javaw.exe(其他操作系统为java) JVM参数 主类 游戏参数

这里以1.20.4为例子
JVM参数 主类 游戏参数 都能在游戏元数据中获取,然后再加入最大内存与最小内存等,然后得到下面的结果

javaw.exe
-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump
-Xss1M
-Xmx4G 
-Xms512M
-Djna.tmpdir=${natives_directory}
-Dorg.lwjgl.system.SharedLibraryExtractPath=${natives_directory}
-Dio.netty.native.workdir=${natives_directory}
-Dminecraft.launcher.brand=${launcher_name}
-Dminecraft.launcher.version=${launcher_version}
-cp
${classpath}
net.minecraft.client.main.Main
--username"
${auth_player_name}
--version
${version_name}
--gameDir
${game_directory}
--assetsDir
${assets_root}
--assetIndex
${assets_index_name}
--uuid
${auth_uuid}
--accessToken
${auth_access_token}
--clientId
${clientid}
--xuid
${auth_xuid}
--userType
${user_type}
--versionType
${version_type}

然后还要把参数中的各项${}东西换掉
${natives_directory}->Native所在的目录
${launcher_name}->启动器名字
${launcher_version}->启动器版本 ${classpath}->ClassPath ${auth_player_name}->用户名 ${version_name}->版本号 ${game_directory}->游戏目录,就是config啥的目录 ${assets_root}->资源目录 ${assets_index_name}->资源元数据名,不用带json 例如1.12.2,12 ${auth_uuid}->用户UUID ${auth_access_token}->登录密钥 ${clientid}->客户端ID(可以不换) ${auth_xuid}->不知道这是啥(可以不换) ${user_type}->账户类型,如果是正版登录就为msa,其他为mojang ${version_type}->游戏类型,就是发布版类型,填release好像也行

  • ClassPath
    这是JVM所需的运行库引导,需要填绝对路径
    在游戏元数据中,已经获取到了所有的运行库,那么需要一个个的获取绝对路径填进来
    例如
E:\code\ColorMC\src\ColorMC.Launcher\bin\Release\net8.0\minecraft\libraries\com\cleanroommc\cleanroom\15.24.0.3028\cleanroom-15.24.0.3028.jar;E:\code\ColorMC\src\ColorMC.Launcher\bin\Release\net8.0\minecraft\libraries\org\lwjgl3\lwjgl3-glfw\3.3.4-27-CLEANROOM\lwjgl3-glfw-3.3.4-27-CLEANROOM.jar;E:\code\ColorMC\src\ColorMC.Launcher\bin\Release\net8.0\minecraft\libraries\org\lwjgl3\lwjgl3-jemalloc\3.3.4-27-CLEANROOM\lwjgl3-jemalloc-3.3.4-27-CLEANROOM.jar;E:\code\ColorMC\src\ColorMC.Launcher\bin\Release\net8.0\minecraft\libraries\org\lwjgl3\lwjgl3-openal\3.3.4-27-CLEANROOM\lwjgl3-openal-3.3.4-27-CLEANROOM.jar;
...

jar之间用;隔开,如果是Linux或者Unix操作系统,则需要使用:隔开
将所有参数替换掉,按照那个启动参数启动新进程,就可以开启游戏了

当然你也可以用JNI的方式启动,参数是一样的