package main import ( "crypto/sha1" "encoding/hex" "encoding/json" "fmt" "io" "net/http" "os" "path/filepath" "time" ) 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 []string Jvm []string } type McAssetIndex struct { Id string Sha1 string Size int TotalSize int Url string } type McJavaVersion struct { Component string MajorVersion int } type McLibraryArtifact struct { Path string Sha1 string Size int Url string } type McLibraryDownload struct { Artifact McLibraryArtifact } type McRuleOs struct { Name string Version string ARch string } type McRule struct { Action string Features map[string]bool Os McRuleOs } type McLibrary struct { Downloads McLibraryDownload Name string Rules []McRule } type McDownload struct { Sha1 string Size int Url string } type McMetadata struct { Arguments McArguments AssetIndex McAssetIndex Assets string ComplianceLevel int Downloads map[string]McDownload Id string JavaVersion McJavaVersion Libraries []McLibrary Logging interface{} MainClass string MinimumLauncherVersion int ReleaseTime time.Time Time time.Time Type string } func GetVersionManifest() (McVersionManifest, error) { resp, err := http.Get("https://piston-meta.mojang.com/mc/game/version_manifest_v2.json") var returnError error = nil if err == nil { defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err == nil { versionManifest := McVersionManifest{} err = json.Unmarshal(data, &versionManifest) if err == nil { dir, err := os.UserConfigDir() if err != nil { return versionManifest, nil } err = os.MkdirAll(filepath.Join(dir, "FCLauncher", "cache"), 0755) f, err := os.OpenFile(filepath.Join(dir, "FCLauncher", "cache", "versionManifest.json"), os.O_CREATE|os.O_RDWR, 0755) defer f.Close() f.Write(data) return versionManifest, nil } else { returnError = fmt.Errorf("Unable to parse Json: %e\n", err) } } else { returnError = fmt.Errorf("Unable to read version manifest: %e\n", err) } } else { returnError = fmt.Errorf("Unable to download version manifest: %e\n", err) } dir, err := os.UserConfigDir() if err != nil { return McVersionManifest{}, returnError } path := filepath.Join(dir, "FCLauncher", "cache", "versionManifest.json") if _, err = os.Stat(path); err != nil { return McVersionManifest{}, returnError } f, err := os.OpenFile(path, os.O_RDONLY, 0755) if err != nil { return McVersionManifest{}, returnError } data, _ := io.ReadAll(f) if err != nil { return McVersionManifest{}, returnError } versionManifest := McVersionManifest{} err = json.Unmarshal(data, &versionManifest) if err != nil { return McVersionManifest{}, returnError } return versionManifest, nil } func GetVersionMetadata(wantedVersion string) (McMetadata, error) { manifest, err := GetVersionManifest() if err != nil { return McMetadata{}, fmt.Errorf("GetVersionMetadata: %e\n", err) } for _, version := range manifest.Versions { if wantedVersion == version.Id { //found it dir, err := os.UserConfigDir() if err == nil { path := filepath.Join(dir, "FCLauncher", "cache", "versionMetadata", wantedVersion+".json") if _, err := os.Stat(path); err == nil { if f, err := os.OpenFile(path, os.O_RDONLY, 0755); err == nil { defer f.Close() if data, err := io.ReadAll(f); err == nil { sha := sha1.Sum(data) if hex.EncodeToString(sha[:20]) == version.Sha1{ metadata := McMetadata{} json.Unmarshal(data, &metadata) fmt.Printf("Found cache!\n") return metadata, nil } } } } } resp, err := http.Get(version.Url) if err != nil { return McMetadata{}, fmt.Errorf("Unable to download metadata: %e\n", err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { return McMetadata{}, fmt.Errorf("Unable to download metadata: %e\n", err) } sha := sha1.Sum(data) if hex.EncodeToString(sha[:20]) != version.Sha1 { return McMetadata{}, fmt.Errorf("GetMetadata: Sha1 hash does not match\n") } metadata := McMetadata{} err = json.Unmarshal(data, &metadata) dir, err = os.UserConfigDir() if err == nil { path := filepath.Join(dir, "FCLauncher", "cache", "versionMetadata") if os.MkdirAll(path, 0755) == nil { if f, err := os.OpenFile(filepath.Join(path, wantedVersion+".json"), os.O_CREATE|os.O_RDWR, 0755); err == nil { defer f.Close() f.Write(data) } } } return metadata, nil } } return McMetadata{}, fmt.Errorf("Unable to find version %s\n", wantedVersion) }