Working on downloading minecraft assets

This commit is contained in:
Samuel Walker 2024-10-29 12:01:22 -06:00
parent 4154fdeec9
commit 4d6dbd40ac
2 changed files with 183 additions and 7 deletions

190
main.go
View File

@ -2,6 +2,8 @@ package main
import (
"bytes"
"crypto/sha1"
"encoding/hex"
"encoding/json"
"fmt"
"io"
@ -9,6 +11,7 @@ import (
"net/url"
"os"
"path/filepath"
"strings"
"time"
)
@ -19,6 +22,7 @@ type Authentication struct {
XboxAuth xboxAuthResponse
XboxAPI xboxAuthResponse
McAPI xboxAuthResponse
McAuth McAuthResponse
}
type devCodeResp struct {
@ -88,11 +92,100 @@ type McAuthRequest struct {
Platform string `json:"platform"`
}
type McAuthRequest2 struct {
IdentityToken string `json:"identityToken"`
EnsureLegacyEnabled bool `json:"ensureLegacyEnabled"`
type McAuthResponse struct {
Username string
Access_token string
Expires_in int
token_type string
}
type McVersionManifestEntry struct {
Id string
Type string
Url string
Time time.Time
ReleaseTime time.Time
Sha1 string
ComplianceLevel int
}
type McLatestEntry struct {
Release string
Snapshot string
}
type McVersionManifest struct {
Latest McLatestEntry
Versions []McVersionManifestEntry
}
type McArguments struct {
Game interface{}
Jvm interface{}
}
type McAssetIndex struct {
Id string
Sha1 string
Size int
TotalSize int
Url string
}
type McDownload struct {
Sha1 string
Size int
Url string
}
type McDownloads struct {
Client []McDownload
Client_mappings []McDownload
Server []McDownload
Server_mappings []McDownload
}
type McJavaVersion struct {
Component string
MajorVersion int
}
type McLibraryArtifact struct {
Path string
Sha1 string
Size int
Url string
}
type McLibraryDownload struct {
Artifact McLibraryArtifact
}
type McLibrary struct {
Downloads McLibraryDownload
Name string
Rules interface{}
}
type McMetadata struct {
Arguments McArguments
AssetIndex McAssetIndex
Assets string
complianceLevel int
Downloads McDownloads
Id string
JavaVersion McJavaVersion
Libraries []McLibrary
Logging interface{}
MainClass string
MinimumLauncherVersion int
ReleaseTime time.Time
Time time.Time
Type string
}
func main() {
auth := Authentication{}
@ -219,9 +312,8 @@ func main() {
if auth.McAPI.DisplayClaims.Xui[0].Uhs != auth.XboxAPI.DisplayClaims.Xui[0].Uhs {
fmt.Printf("Warning: Inconsistant user hash!")
}
mcAuthData, _ := json.Marshal(McAuthRequest2{IdentityToken: "XBL3.0 x=" + auth.McAPI.DisplayClaims.Xui[0].Uhs + ";" + auth.McAPI.Token, EnsureLegacyEnabled: true})
fmt.Printf("MC Auth Data: %s\n", mcAuthData)
httpReqMC, _ := http.NewRequest("POST", "https://api.minecraftservices.com/authentication/login_with_xbox", bytes.NewBuffer(mcAuthData))
mcAuthData, _ := json.Marshal(McAuthRequest{Xtoken: "XBL3.0 x=" + auth.McAPI.DisplayClaims.Xui[0].Uhs + ";" + auth.McAPI.Token, Platform: "PC_LAUNCHER"})
httpReqMC, _ := http.NewRequest("POST", "https://api.minecraftservices.com/launcher/login", bytes.NewBuffer(mcAuthData))
httpReqMC.Header.Add("Content-Type", "application/json")
httpReqMC.Header.Add("Accept", "application/json")
resp, err := client.Do(httpReqMC)
@ -233,7 +325,91 @@ func main() {
fmt.Printf("MC Auth Error: %s\n", resp.Status)
}
d, _ = io.ReadAll(resp.Body)
fmt.Printf("MC Auth Response: %s\n", d)
json.Unmarshal(d, &auth.McAuth)
resp, err = http.Get("https://piston-meta.mojang.com/mc/game/version_manifest_v2.json")
if err != nil {
fmt.Printf("manifest error")
}
defer resp.Body.Close()
data, _ = io.ReadAll(resp.Body)
versionManifest := McVersionManifest{}
json.Unmarshal(data, &versionManifest)
resp, err = http.Get(versionManifest.Versions[0].Url)
if err != nil {
fmt.Printf("metadata error")
}
defer resp.Body.Close()
data, _ = io.ReadAll(resp.Body)
var metadata McMetadata
json.Unmarshal(data, &metadata)
resp, err = http.Get(metadata.AssetIndex.Url)
if err != nil {
fmt.Printf("asset index error")
}
defer resp.Body.Close()
data, _ = io.ReadAll(resp.Body)
sha := sha1.Sum(data)
if hex.EncodeToString(sha[:20]) != metadata.AssetIndex.Sha1 {
fmt.Printf("Error downloading asset index")
return
}
var index map[string]interface{}
json.Unmarshal(data, &index)
index = index["objects"].(map[string]interface{})
for name, asset := range index {
asset_map := asset.(map[string]interface{})
if _, err = os.Stat(filepath.Join(dir, "minecraft_test", "assets", metadata.Assets, name)); err == nil {
f, _ := os.OpenFile(filepath.Join(dir, "minecraft_test", "assets", metadata.Assets, name), os.O_RDONLY, 0755)
data, _ := io.ReadAll(f)
sha := sha1.Sum(data)
if hex.EncodeToString(sha[:20]) == asset_map["hash"].(string) {
continue
}
}
fmt.Printf("Downloading %s: ", name)
resp, err = http.Get(fmt.Sprintf("https://resources.download.minecraft.net/%s/%s", asset_map["hash"].(string)[:2], asset_map["hash"].(string)))
if err != nil {
fmt.Printf("Error\n")
return
}
defer resp.Body.Close()
data, _ = io.ReadAll(resp.Body)
sha = sha1.Sum(data)
if hex.EncodeToString(sha[:20]) != asset_map["hash"].(string) {
fmt.Printf("Sha1 Mismatch\n")
return
}
fmt.Printf("Ok\n")
path := ""
tokens := strings.Split(name, "/")
for ind, token := range tokens {
if ind != len(tokens)-1 {
path = filepath.Join(path, token)
}
}
os.MkdirAll(filepath.Join(dir, "minecraft_test", "assets", metadata.Assets, path), 0755)
f, _ := os.OpenFile(filepath.Join(dir, "minecraft_test", "assets", metadata.Assets, name), os.O_CREATE|os.O_RDWR, 0755)
defer f.Close()
f.Write(data)
}
for _, lib := range metadata.Libraries {
fmt.Printf("Downloading %s: ", lib.Name)
resp, err = http.Get(lib.Downloads.Artifact.Url)
if err != nil {
fmt.Printf("Error\n")
return
}
defer resp.Body.Close()
data, _ = io.ReadAll(resp.Body)
sha = sha1.Sum(data)
if hex.EncodeToString(sha[:20]) != lib.Downloads.Artifact.Sha1 {
fmt.Printf("Sha1 Mismatch\n")
return
}
fmt.Printf("OK\n")
}
/*
fmt.Println("Requesting Oauth")

BIN
minecraft

Binary file not shown.