package main import ( "crypto/sha1" "encoding/hex" "encoding/json" "fmt" "io" "net/http" "os" "path/filepath" "strings" ) type Fabric struct { } type FabricDefinition struct { Separator string Build int Maven string Version string Stable bool } type FabricLibrary struct { Name string Url string Sha1 string } type FabricLibraries struct { Client []FabricLibrary Common []FabricLibrary Server []FabricLibrary } type FabricMeta struct { Version int Libraries FabricLibraries MainClass map[string]string } type FabricVersion struct { Loader FabricDefinition Intermediary FabricDefinition LauncherMeta FabricMeta } func (Fabric)GetFabricVersions(mcVersion string) ([]FabricVersion, error) { resp, err := http.Get("https://meta.fabricmc.net/v2/versions/loader/"+mcVersion) if err != nil { return []FabricVersion{}, fmt.Errorf("Unable to pull fabric version manifest: %s\n", err) } defer resp.Body.Close() data, _ := io.ReadAll(resp.Body) versions := []FabricVersion{} json.Unmarshal(data, &versions) return versions, nil } func GetFabricMetadata(mcVersion string, fabricVersion string) (FabricVersion, error) { versions, err := Fabric{}.GetFabricVersions(mcVersion) if err != nil { return FabricVersion{}, fmt.Errorf("unable to download versions manifest: %e\n", err) } for _, version := range versions { if version.Loader.Version == fabricVersion { return version, nil } } return FabricVersion{}, fmt.Errorf("Unable to find requested version.\n") } func InstallLib(lib FabricLibrary, libDir string) { path := filepath.Join(ProcessMavenPath(lib.Name), ProcessMavenFilename(lib.Name)) if _, err := os.Stat(filepath.Join(libDir, path)); err == nil { f, _ := os.OpenFile(filepath.Join(libDir, path), os.O_RDONLY, 0755) defer f.Close() data, _ := io.ReadAll(f) sha := sha1.Sum(data) if hex.EncodeToString(sha[:20]) == lib.Sha1 { return } } resp, err := http.Get(lib.Url+path) if err != nil { return } defer resp.Body.Close() os.MkdirAll(filepath.Join(libDir, ProcessMavenPath(lib.Name)), 0755) f, _ := os.OpenFile(filepath.Join(libDir, path), os.O_CREATE|os.O_RDWR, 0755) defer f.Close() io.Copy(f, resp.Body) } func InstallFabricLibs(mcVersion string, fabricVersion string, libDir string) { metadata, _ := GetFabricMetadata(mcVersion, fabricVersion) for _, lib := range metadata.LauncherMeta.Libraries.Client { InstallLib(lib, libDir) } for _, lib := range metadata.LauncherMeta.Libraries.Common { InstallLib(lib, libDir) } InstallLib(FabricLibrary{Name: metadata.Loader.Maven, Sha1: "", Url: "https://maven.fabricmc.net/"}, libDir) InstallLib(FabricLibrary{Name: metadata.Intermediary.Maven, Sha1: "", Url: "https://maven.fabricmc.net/"}, libDir) } func ProcessMavenPath(maven string) string { tokens := strings.Split(maven, ":") path := filepath.Join(strings.Split(tokens[0], ".")...) pack := tokens[1] version := tokens[2] path = filepath.Join(path, pack, version) return path } func ProcessMavenFilename(maven string) string { tokens := strings.Split(maven, ":") pack := tokens[1] version := tokens[2] return pack+"-"+version+".jar" }