diff --git a/fclauncher/InstanceManager.go b/fclauncher/InstanceManager.go index 9968e3e..957d0cb 100644 --- a/fclauncher/InstanceManager.go +++ b/fclauncher/InstanceManager.go @@ -26,6 +26,8 @@ type Instance struct { FabricVersion string QuiltVersion string JavaVersion int + Libraries []string + MainClass string } type InstanceManager struct { @@ -187,9 +189,10 @@ func (i *InstanceManager)InstallVanilla(version string, instanceName string) { if err != nil { fmt.Printf("unable to create directory: %s\n", err) } - - - instance := Instance{InstanceName: instanceName, MinecraftVersion: version, JavaVersion: metadata.JavaVersion.MajorVersion} + instance := Instance{InstanceName: instanceName, MinecraftVersion: version, JavaVersion: metadata.JavaVersion.MajorVersion, MainClass: metadata.MainClass} + for _, lib := range metadata.Libraries { + instance.Libraries = append(instance.Libraries, lib.Downloads.Artifact.Path) + } data, err := json.Marshal(instance) if err != nil { fmt.Printf("unable to marshal json data: %s\n", err) @@ -242,11 +245,7 @@ func (i *InstanceManager)CheckUpdate(instance Instance){ i.SearchInstances() } -func (i *InstanceManager)LaunchInstance(instance string) { - dir, err := os.UserConfigDir() - if err != nil { - fmt.Printf("unable to get config directory\n") - } +func (i *InstanceManager)GetInstance(instance string) (Instance, error) { instanceObject := Instance{} found := false for _, inst := range i.instances { @@ -257,7 +256,19 @@ func (i *InstanceManager)LaunchInstance(instance string) { } } if !found { - fmt.Printf("unable to find instance %s\n", instance) + return Instance{}, fmt.Errorf("unable to find instance %s\n", instance) + } + return instanceObject, nil +} + +func (i *InstanceManager)LaunchInstance(instance string) { + dir, err := os.UserConfigDir() + if err != nil { + fmt.Printf("unable to get config directory\n") + } + instanceObject, err := i.GetInstance(instance) + if err != nil { + fmt.Printf("Unable to find instance\n") } execName := "java" suffix := "lin" @@ -271,7 +282,7 @@ func (i *InstanceManager)LaunchInstance(instance string) { fmt.Printf("unable to authenticate: %s\n", err) return } - args, err := GetOnlineLaunchArgs(instanceObject.MinecraftVersion, filepath.Join(dir, "lib"), filepath.Join(dir, "bin"), filepath.Join(dir, "assets"), filepath.Join(dir, "instances", instance, "minecraft"), auth) + args, err := GetOnlineLaunchArgs(instanceObject.MinecraftVersion, instanceObject, filepath.Join(dir, "lib"), filepath.Join(dir, "bin"), filepath.Join(dir, "assets"), filepath.Join(dir, "instances", instance, "minecraft"), auth) if err != nil { fmt.Printf("unable to get launch args: %s\n", err) } @@ -283,3 +294,64 @@ func (i *InstanceManager)LaunchInstance(instance string) { fmt.Printf("Command Output: %s\n", data) } + + +func (i *InstanceManager)InstallFabric(instance string, fabricVersion string) { + i.app.Status("Installing Fabric") + instanceObject, err := i.GetInstance(instance) + if err != nil { + fmt.Printf("Instance does not exist\n") + } + metadata, err := GetFabricMetadata(instanceObject.MinecraftVersion, fabricVersion) + if err != nil { + fmt.Printf("unable to get version metadata\n") + } + for _, lib := range metadata.LauncherMeta.Libraries.Client { + tokens := strings.SplitN(lib.Name, ".", 2) + org1 := tokens[0] + tokens = strings.Split(tokens[1], ":") + org2 := tokens[0] + pack := tokens[1] + version := tokens[2] + instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(org1, org2, pack, version, pack+"-"+version+".jar")) + } + for _, lib := range metadata.LauncherMeta.Libraries.Common { + tokens := strings.SplitN(lib.Name, ".", 2) + org1 := tokens[0] + tokens = strings.Split(tokens[1], ":") + org2 := tokens[0] + pack := tokens[1] + version := tokens[2] + instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(org1, org2, pack, version, pack+"-"+version+".jar")) + } + tokens := strings.SplitN(metadata.Loader.Maven, ".", 2) + org1 := tokens[0] + tokens = strings.Split(tokens[1], ":") + org2 := tokens[0] + pack := tokens[1] + version := tokens[2] + instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(org1, org2, pack, version, pack+"-"+version+".jar")) + + tokens = strings.SplitN(metadata.Intermediary.Maven, ".", 2) + org1 = tokens[0] + tokens = strings.Split(tokens[1], ":") + org2 = tokens[0] + pack = tokens[1] + version = tokens[2] + instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(org1, org2, pack, version, pack+"-"+version+".jar")) + + instanceObject.MainClass = metadata.LauncherMeta.MainClass["client"] + instanceObject.FabricVersion = fabricVersion + dir, _ := os.UserConfigDir() + InstallFabricLibs(instanceObject.MinecraftVersion, fabricVersion, filepath.Join(dir, "FCLauncher", "lib")) + f, _ := os.OpenFile(filepath.Join(dir, "FCLauncher", "instances", instance, "instance.json"), os.O_CREATE|os.O_RDWR, 0755) + data, _ := json.Marshal(instanceObject) + defer f.Close() + f.Write(data) + for ind, inst := range i.instances { + if inst.InstanceName == instance { + i.instances[ind] = instanceObject + break + } + } +} diff --git a/fclauncher/fabric.go b/fclauncher/fabric.go index 83bc09d..a4c553c 100644 --- a/fclauncher/fabric.go +++ b/fclauncher/fabric.go @@ -1,10 +1,15 @@ package main import ( + "crypto/sha1" + "encoding/hex" "encoding/json" "fmt" "io" "net/http" + "os" + "path/filepath" + "strings" ) type Fabric struct { @@ -23,6 +28,7 @@ type FabricDefinition struct { type FabricLibrary struct { Name string Url string + Sha1 string } type FabricLibraries struct { @@ -52,6 +58,58 @@ func (Fabric)GetFabricVersions(mcVersion string) ([]FabricVersion, error) { data, _ := io.ReadAll(resp.Body) versions := []FabricVersion{} json.Unmarshal(data, &versions) - fmt.Printf("fabric versions found for %s: %+v\n", mcVersion, 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) { + tokens := strings.SplitN(lib.Name, ".", 2) + org1 := tokens[0] + tokens = strings.Split(tokens[1], ":") + org2 := tokens[0] + pack := tokens[1] + version := tokens[2] + path := filepath.Join(org1, org2, pack, version, pack+"-"+version+".jar") + 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, org1, org2, pack, version), 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) +} diff --git a/fclauncher/frontend/src/Instances.svelte b/fclauncher/frontend/src/Instances.svelte index 9720103..12043b6 100644 --- a/fclauncher/frontend/src/Instances.svelte +++ b/fclauncher/frontend/src/Instances.svelte @@ -1,6 +1,5 @@