diff --git a/main.go b/main.go index c67f940..edccfb3 100644 --- a/main.go +++ b/main.go @@ -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") diff --git a/minecraft b/minecraft index f887cb8..cb9ef3e 100755 Binary files a/minecraft and b/minecraft differ