2024-10-26 14:00:53 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-10-26 18:14:12 -06:00
|
|
|
"bufio"
|
2024-10-26 14:00:53 -06:00
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
2024-11-25 14:28:32 -07:00
|
|
|
"net/http"
|
2024-10-26 14:00:53 -06:00
|
|
|
"os"
|
2024-10-30 15:39:11 -06:00
|
|
|
"os/exec"
|
2024-10-26 14:00:53 -06:00
|
|
|
"path/filepath"
|
2024-10-26 18:14:12 -06:00
|
|
|
"runtime"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2024-10-30 19:11:24 -06:00
|
|
|
|
|
|
|
wruntime "github.com/wailsapp/wails/v2/pkg/runtime"
|
2024-11-25 13:23:06 -07:00
|
|
|
"github.com/zhyee/zipstream"
|
2024-10-26 14:00:53 -06:00
|
|
|
)
|
|
|
|
|
2024-11-25 13:23:06 -07:00
|
|
|
type MrData struct {
|
|
|
|
FormatVersion int
|
|
|
|
Game string
|
|
|
|
VersionId string
|
|
|
|
Name string
|
|
|
|
Summary string
|
|
|
|
Files []MrFile
|
|
|
|
Dependencies map[string]string
|
|
|
|
}
|
|
|
|
|
|
|
|
type MrFile struct {
|
|
|
|
Path string
|
|
|
|
Hashes map[string]string
|
|
|
|
Env map[string]string
|
|
|
|
Downloads []string
|
|
|
|
FileSize int
|
|
|
|
}
|
|
|
|
|
2024-10-26 14:00:53 -06:00
|
|
|
type Instance struct {
|
2024-11-01 05:55:41 -06:00
|
|
|
InstanceName string
|
|
|
|
ModpackId string
|
|
|
|
ModpackVersion string
|
2024-10-30 15:39:11 -06:00
|
|
|
MinecraftVersion string
|
2024-11-01 05:55:41 -06:00
|
|
|
ForgeVersion string
|
|
|
|
NeoForgeVersion string
|
|
|
|
FabricVersion string
|
|
|
|
QuiltVersion string
|
|
|
|
JavaVersion int
|
|
|
|
Libraries []string
|
|
|
|
MainClass string
|
2024-10-26 14:00:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type InstanceManager struct {
|
|
|
|
instances []Instance
|
2024-11-01 05:55:41 -06:00
|
|
|
app *App
|
2024-10-26 14:00:53 -06:00
|
|
|
}
|
|
|
|
|
2024-10-26 18:14:12 -06:00
|
|
|
type mmcpack struct {
|
|
|
|
Components []component
|
|
|
|
}
|
|
|
|
|
|
|
|
type component struct {
|
2024-11-01 05:55:41 -06:00
|
|
|
Uid string
|
2024-10-26 18:14:12 -06:00
|
|
|
Version string
|
|
|
|
}
|
|
|
|
|
2024-11-01 05:55:41 -06:00
|
|
|
func (i *InstanceManager) SearchInstances() {
|
2024-10-26 14:00:53 -06:00
|
|
|
i.instances = []Instance{}
|
2024-10-30 15:39:11 -06:00
|
|
|
dir, _ := os.UserConfigDir()
|
|
|
|
dir = filepath.Join(dir, "FCLauncher", "instances")
|
2024-10-26 14:00:53 -06:00
|
|
|
if _, err := os.Stat(dir); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
subdirs, _ := os.ReadDir(dir)
|
|
|
|
for _, d := range subdirs {
|
|
|
|
if !d.IsDir() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if _, err := os.Stat(filepath.Join(dir, d.Name(), "instance.json")); err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
f, _ := os.OpenFile(filepath.Join(dir, d.Name(), "instance.json"), os.O_RDONLY, 0755)
|
|
|
|
defer f.Close()
|
|
|
|
buff := new(bytes.Buffer)
|
|
|
|
io.Copy(buff, f)
|
|
|
|
instance := Instance{}
|
|
|
|
json.Unmarshal(buff.Bytes(), &instance)
|
|
|
|
i.instances = append(i.instances, instance)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-01 05:55:41 -06:00
|
|
|
func (i *InstanceManager) checkJavaVersion(instance Instance) {
|
2024-10-26 18:14:12 -06:00
|
|
|
infoPath := filepath.Join(i.app.PrismLauncher.GetInstanceDir(), instance.InstanceName, "mmc-pack.json")
|
|
|
|
f, _ := os.OpenFile(infoPath, os.O_RDONLY, 0755)
|
|
|
|
defer f.Close()
|
2024-11-01 05:55:41 -06:00
|
|
|
dataStr, _ := io.ReadAll(f)
|
2024-10-26 18:14:12 -06:00
|
|
|
var data mmcpack
|
|
|
|
json.Unmarshal(dataStr, &data)
|
|
|
|
mc_version := "0.0"
|
|
|
|
for _, comp := range data.Components {
|
|
|
|
if comp.Uid == "net.minecraft" {
|
|
|
|
mc_version = comp.Version
|
2024-11-01 05:55:41 -06:00
|
|
|
break
|
2024-10-26 18:14:12 -06:00
|
|
|
}
|
|
|
|
}
|
2024-11-01 05:55:41 -06:00
|
|
|
fmt.Printf("MC Version: %s", mc_version)
|
2024-10-26 18:14:12 -06:00
|
|
|
tokensStr := strings.Split(mc_version, ".")
|
|
|
|
tokens := []int{0, 0, 0}
|
|
|
|
tokens[0], _ = strconv.Atoi(tokensStr[0])
|
|
|
|
tokens[1], _ = strconv.Atoi(tokensStr[1])
|
2024-10-26 19:27:39 -06:00
|
|
|
if len(tokensStr) > 2 {
|
|
|
|
tokens[2], _ = strconv.Atoi(tokensStr[2])
|
|
|
|
}
|
2024-10-26 18:14:12 -06:00
|
|
|
javaVer := 8
|
|
|
|
if tokens[1] == 17 {
|
|
|
|
javaVer = 17
|
|
|
|
} else if tokens[1] == 18 || tokens[1] == 19 {
|
|
|
|
javaVer = 17
|
|
|
|
} else if tokens[1] > 19 {
|
|
|
|
if tokens[1] == 20 && tokens[2] < 5 {
|
|
|
|
javaVer = 17
|
|
|
|
} else {
|
|
|
|
javaVer = 21
|
|
|
|
}
|
|
|
|
}
|
2024-11-01 05:55:41 -06:00
|
|
|
fmt.Printf("Req Java Version: %d", javaVer)
|
2024-10-26 18:14:12 -06:00
|
|
|
if !i.app.Java.CheckJavaVer(javaVer) {
|
|
|
|
i.app.Java.InstallJavaVer(javaVer)
|
|
|
|
}
|
2024-11-01 05:55:41 -06:00
|
|
|
|
2024-10-26 18:14:12 -06:00
|
|
|
confPath := filepath.Join(i.app.PrismLauncher.GetInstanceDir(), instance.InstanceName, "instance.cfg")
|
|
|
|
f, _ = os.OpenFile(confPath, os.O_RDONLY, 0755)
|
|
|
|
defer f.Close()
|
|
|
|
buff := new(bytes.Buffer)
|
|
|
|
io.Copy(buff, f)
|
|
|
|
sc := bufio.NewScanner(buff)
|
|
|
|
f, _ = os.OpenFile(confPath, os.O_CREATE|os.O_RDWR, 0755)
|
|
|
|
plat := "lin"
|
|
|
|
exe := "java"
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
plat = "win"
|
|
|
|
exe = "Java.exe"
|
|
|
|
}
|
|
|
|
confDir, _ := os.UserConfigDir()
|
|
|
|
found := false
|
|
|
|
for sc.Scan() {
|
|
|
|
line := sc.Text()
|
|
|
|
if strings.HasPrefix(line, "JavaPath=") {
|
2024-10-26 22:33:33 -06:00
|
|
|
line = fmt.Sprintf("JavaPath=%s/FCLauncher/java/java-%d-%s/bin/%s", strings.ReplaceAll(confDir, "\\", "/"), javaVer, plat, exe)
|
2024-10-26 18:14:12 -06:00
|
|
|
found = true
|
|
|
|
}
|
2024-11-01 05:55:41 -06:00
|
|
|
f.WriteString(line + "\n")
|
2024-10-26 18:14:12 -06:00
|
|
|
}
|
|
|
|
if !found {
|
2024-10-26 22:33:33 -06:00
|
|
|
line := fmt.Sprintf("JavaPath=%s/FCLauncher/java/java-%d-%s/bin/%s", strings.ReplaceAll(confDir, "\\", "/"), javaVer, plat, exe)
|
2024-11-01 05:55:41 -06:00
|
|
|
f.WriteString(line + "\n")
|
2024-10-26 18:14:12 -06:00
|
|
|
f.WriteString("OverrideJavaLocation=true\nOverrideJava=true\n")
|
|
|
|
}
|
|
|
|
f.Close()
|
|
|
|
}
|
|
|
|
|
2024-11-01 05:55:41 -06:00
|
|
|
func (i *InstanceManager) InstallModpack(modpack Modpack, instanceName string) {
|
2024-10-26 14:00:53 -06:00
|
|
|
i.app.Status(fmt.Sprintf("Installing %s", modpack.Name))
|
|
|
|
version := modpack.Versions[len(modpack.Versions)-1]
|
|
|
|
dname, _ := os.MkdirTemp("", "fclauncher-*")
|
|
|
|
f, _ := os.OpenFile(filepath.Join(dname, instanceName+".mrpack"), os.O_CREATE|os.O_RDWR, 0755)
|
|
|
|
defer f.Close()
|
2024-11-01 05:55:41 -06:00
|
|
|
HttpDownload(modpack.Id+"/"+version.File, f, i.app.Ctx)
|
2024-10-26 14:00:53 -06:00
|
|
|
i.app.PrismLauncher.ImportModpack(f.Name())
|
|
|
|
instance := Instance{InstanceName: instanceName, ModpackVersion: version.Version, ModpackId: modpack.Id}
|
|
|
|
i.instances = append(i.instances, instance)
|
|
|
|
f, _ = os.OpenFile(filepath.Join(i.app.PrismLauncher.GetInstanceDir(), instanceName, "instance.json"), os.O_CREATE|os.O_RDWR, 0755)
|
|
|
|
defer f.Close()
|
|
|
|
data, _ := json.Marshal(instance)
|
|
|
|
f.Write(data)
|
2024-10-26 18:14:12 -06:00
|
|
|
i.checkJavaVersion(instance)
|
|
|
|
|
2024-10-26 14:00:53 -06:00
|
|
|
}
|
|
|
|
|
2024-11-01 05:55:41 -06:00
|
|
|
func (i *InstanceManager) InstallVanilla(version string, instanceName string) {
|
2024-10-30 15:39:11 -06:00
|
|
|
dir, _ := os.UserConfigDir()
|
|
|
|
err := DownloadAssets(version, filepath.Join(dir, "FCLauncher", "assets"), *i.app)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Unable to download assets: %s\n", err)
|
|
|
|
} else {
|
|
|
|
fmt.Printf("Assets Downloaded")
|
|
|
|
}
|
|
|
|
err = DownloadLibraries(version, filepath.Join(dir, "FCLauncher", "lib"), *i.app)
|
2024-10-29 21:48:59 -06:00
|
|
|
if err != nil {
|
2024-10-30 15:39:11 -06:00
|
|
|
fmt.Printf("Unable to download libs: %s\n", err)
|
2024-10-29 21:48:59 -06:00
|
|
|
} else {
|
2024-10-30 15:39:11 -06:00
|
|
|
fmt.Printf("Libs Downloaded")
|
|
|
|
}
|
|
|
|
InstallNatives(version, filepath.Join(dir, "FCLauncher", "instances", instanceName, "minecraft", "natives"))
|
2024-10-30 15:58:05 -06:00
|
|
|
DownloadLoggingConfig(version, filepath.Join(dir, "FCLauncher", "instances", instanceName, "minecraft"))
|
2024-10-30 15:39:11 -06:00
|
|
|
err = DownloadExecutable(version, filepath.Join(dir, "FCLauncher", "bin"), *i.app)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Unable to download binaries: %s\n", err)
|
|
|
|
} else {
|
|
|
|
fmt.Printf("Binaries Downloaded")
|
|
|
|
}
|
|
|
|
metadata, err := GetVersionMetadata(version)
|
|
|
|
if err != nil {
|
2024-11-01 05:55:41 -06:00
|
|
|
fmt.Printf("unable to pull metadata: %s\n", err)
|
2024-10-30 15:39:11 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
err = os.MkdirAll(filepath.Join(dir, "FCLauncher", "instances", instanceName, "minecraft"), 0755)
|
|
|
|
if err != nil {
|
2024-11-01 05:55:41 -06:00
|
|
|
fmt.Printf("unable to create directory: %s\n", err)
|
2024-10-30 15:39:11 -06:00
|
|
|
}
|
2024-10-31 16:23:38 -06:00
|
|
|
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)
|
|
|
|
}
|
2024-10-30 15:39:11 -06:00
|
|
|
data, err := json.Marshal(instance)
|
|
|
|
if err != nil {
|
2024-11-01 05:55:41 -06:00
|
|
|
fmt.Printf("unable to marshal json data: %s\n", err)
|
2024-10-30 15:39:11 -06:00
|
|
|
}
|
|
|
|
f, err := os.OpenFile(filepath.Join(dir, "FCLauncher", "instances", instanceName, "instance.json"), os.O_CREATE|os.O_RDWR, 0755)
|
|
|
|
if err != nil {
|
2024-11-01 05:55:41 -06:00
|
|
|
fmt.Printf("unable to open file: %s\n", err)
|
2024-10-30 15:39:11 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
defer f.Close()
|
|
|
|
_, err = f.Write(data)
|
|
|
|
if err != nil {
|
2024-11-01 05:55:41 -06:00
|
|
|
fmt.Printf("unable to write data: %s\n", err)
|
2024-10-30 15:39:11 -06:00
|
|
|
}
|
|
|
|
i.instances = append(i.instances, instance)
|
2024-11-01 05:55:41 -06:00
|
|
|
|
2024-10-30 15:39:11 -06:00
|
|
|
if !i.app.Java.CheckJavaVer(instance.JavaVersion) {
|
|
|
|
i.app.Status(fmt.Sprintf("Installing Java Version %d", instance.JavaVersion))
|
|
|
|
i.app.Java.InstallJavaVer(instance.JavaVersion)
|
2024-10-29 21:48:59 -06:00
|
|
|
}
|
2024-10-30 15:39:11 -06:00
|
|
|
|
2024-10-29 21:48:59 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-11-01 05:55:41 -06:00
|
|
|
func (i *InstanceManager) GetInstances() []string {
|
|
|
|
names := []string{}
|
|
|
|
for _, inst := range i.instances {
|
|
|
|
names = append(names, inst.InstanceName)
|
|
|
|
}
|
|
|
|
return names
|
2024-10-26 14:00:53 -06:00
|
|
|
}
|
|
|
|
|
2024-11-01 05:55:41 -06:00
|
|
|
func (i *InstanceManager) CheckUpdate(instance Instance) {
|
2024-10-30 15:39:11 -06:00
|
|
|
return
|
2024-10-26 18:14:12 -06:00
|
|
|
i.app.Status("Checking for Updates")
|
|
|
|
i.app.Modpacks.QuerryModpacks()
|
|
|
|
pack := i.app.Modpacks.GetModpack(instance.ModpackId)
|
|
|
|
if pack.Versions[len(pack.Versions)-1].Version == instance.ModpackVersion {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
i.app.Status(fmt.Sprintf("Updating %s", instance.InstanceName))
|
|
|
|
version := pack.Versions[len(pack.Versions)-1]
|
|
|
|
dname, _ := os.MkdirTemp("", "fclauncher-*")
|
|
|
|
f, _ := os.OpenFile(filepath.Join(dname, instance.InstanceName+".mrpack"), os.O_CREATE|os.O_RDWR, 0755)
|
|
|
|
defer f.Close()
|
2024-11-01 05:55:41 -06:00
|
|
|
HttpDownload(pack.Id+"/"+version.File, f, i.app.Ctx)
|
2024-10-26 18:14:12 -06:00
|
|
|
i.app.PrismLauncher.ImportModpack(f.Name())
|
|
|
|
instance.ModpackVersion = version.Version
|
|
|
|
f, _ = os.OpenFile(filepath.Join(i.app.PrismLauncher.GetInstanceDir(), instance.InstanceName, "instance.json"), os.O_CREATE|os.O_RDWR, 0755)
|
|
|
|
defer f.Close()
|
|
|
|
data, _ := json.Marshal(instance)
|
|
|
|
f.Write(data)
|
|
|
|
i.checkJavaVersion(instance)
|
|
|
|
i.SearchInstances()
|
|
|
|
}
|
|
|
|
|
2024-11-01 05:55:41 -06:00
|
|
|
func (i *InstanceManager) GetInstance(instance string) (Instance, error) {
|
2024-10-30 15:39:11 -06:00
|
|
|
instanceObject := Instance{}
|
|
|
|
found := false
|
|
|
|
for _, inst := range i.instances {
|
|
|
|
if inst.InstanceName == instance {
|
|
|
|
instanceObject = inst
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
2024-10-31 16:23:38 -06:00
|
|
|
return Instance{}, fmt.Errorf("unable to find instance %s\n", instance)
|
|
|
|
}
|
|
|
|
return instanceObject, nil
|
|
|
|
}
|
|
|
|
|
2024-11-01 05:55:41 -06:00
|
|
|
func (i *InstanceManager) LaunchInstance(instance string) {
|
2024-11-26 10:22:37 -07:00
|
|
|
i.app.Status(fmt.Sprintf("Launching %s", instance))
|
2024-10-31 16:23:38 -06:00
|
|
|
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")
|
2024-10-30 15:39:11 -06:00
|
|
|
}
|
|
|
|
execName := "java"
|
|
|
|
suffix := "lin"
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
execName = "Java.exe"
|
|
|
|
suffix = "win"
|
|
|
|
}
|
|
|
|
dir = filepath.Join(dir, "FCLauncher")
|
2024-10-30 17:16:10 -06:00
|
|
|
auth, err := MicrosoftAuth(i.app.Auth)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("unable to authenticate: %s\n", err)
|
|
|
|
return
|
|
|
|
}
|
2024-10-31 16:23:38 -06:00
|
|
|
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)
|
2024-10-30 15:39:11 -06:00
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("unable to get launch args: %s\n", err)
|
|
|
|
}
|
2024-11-01 18:08:29 -06:00
|
|
|
if instanceObject.ForgeVersion != "" {
|
|
|
|
args = append(args, "--launchTarget")
|
|
|
|
args = append(args, "forge_client")
|
|
|
|
}
|
2024-10-30 15:39:11 -06:00
|
|
|
fmt.Printf("Args: %+v", args)
|
|
|
|
child := exec.Command(filepath.Join(dir, "java", fmt.Sprintf("java-%d-%s", instanceObject.JavaVersion, suffix), "bin", execName), args...)
|
2024-10-31 17:50:45 -06:00
|
|
|
child.Dir = filepath.Join(dir, "instances", instance, "minecraft")
|
2024-11-01 05:55:41 -06:00
|
|
|
wruntime.WindowHide(i.app.Ctx)
|
2024-10-30 15:39:11 -06:00
|
|
|
data, err := child.CombinedOutput()
|
2024-10-30 19:11:24 -06:00
|
|
|
wruntime.WindowShow(i.app.Ctx)
|
2024-10-30 15:39:11 -06:00
|
|
|
fmt.Printf("Command Output: %s\n", data)
|
|
|
|
}
|
|
|
|
|
2024-11-01 05:55:41 -06:00
|
|
|
func (i *InstanceManager) InstallFabric(instance string, fabricVersion string) {
|
2024-10-31 16:23:38 -06:00
|
|
|
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")
|
|
|
|
}
|
2024-11-01 05:55:41 -06:00
|
|
|
client:
|
2024-10-31 16:23:38 -06:00
|
|
|
for _, lib := range metadata.LauncherMeta.Libraries.Client {
|
2024-11-26 16:23:54 -07:00
|
|
|
tokens := strings.Split(ProcessMavenPath(lib.Name), "/")
|
2024-10-31 17:47:50 -06:00
|
|
|
pkg := tokens[len(tokens)-2]
|
2024-10-31 16:46:12 -06:00
|
|
|
instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(ProcessMavenPath(lib.Name), ProcessMavenFilename(lib.Name)))
|
2024-10-31 17:47:50 -06:00
|
|
|
for ind, path := range instanceObject.Libraries {
|
2024-11-26 16:23:54 -07:00
|
|
|
tokens := strings.Split(path, "/")
|
2024-10-31 17:47:50 -06:00
|
|
|
if pkg == tokens[len(tokens)-3] {
|
|
|
|
instanceObject.Libraries[ind] = filepath.Join(ProcessMavenPath(lib.Name), ProcessMavenFilename(lib.Name))
|
|
|
|
fmt.Printf("duplicate library %s\n", pkg)
|
|
|
|
continue client
|
|
|
|
}
|
|
|
|
}
|
2024-11-01 05:55:41 -06:00
|
|
|
}
|
|
|
|
common:
|
2024-10-31 16:23:38 -06:00
|
|
|
for _, lib := range metadata.LauncherMeta.Libraries.Common {
|
2024-11-26 16:23:54 -07:00
|
|
|
tokens := strings.Split(ProcessMavenPath(lib.Name), "/")
|
2024-10-31 17:47:50 -06:00
|
|
|
pkg := tokens[len(tokens)-2]
|
2024-10-31 16:46:12 -06:00
|
|
|
instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(ProcessMavenPath(lib.Name), ProcessMavenFilename(lib.Name)))
|
2024-10-31 17:47:50 -06:00
|
|
|
for ind, path := range instanceObject.Libraries {
|
2024-11-26 16:21:26 -07:00
|
|
|
tokens := strings.Split(path, "/")
|
2024-11-26 16:19:46 -07:00
|
|
|
fmt.Printf("Inspecing path %s with %d tokens", path, len(tokens))
|
2024-10-31 17:47:50 -06:00
|
|
|
if pkg == tokens[len(tokens)-3] {
|
|
|
|
instanceObject.Libraries[ind] = filepath.Join(ProcessMavenPath(lib.Name), ProcessMavenFilename(lib.Name))
|
|
|
|
fmt.Printf("duplicate library %s\n", pkg)
|
|
|
|
continue common
|
|
|
|
}
|
|
|
|
}
|
2024-11-01 05:55:41 -06:00
|
|
|
}
|
2024-10-31 16:46:12 -06:00
|
|
|
instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(ProcessMavenPath(metadata.Loader.Maven), ProcessMavenFilename(metadata.Loader.Maven)))
|
2024-10-31 16:23:38 -06:00
|
|
|
|
2024-10-31 16:46:12 -06:00
|
|
|
instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(ProcessMavenPath(metadata.Intermediary.Maven), ProcessMavenFilename(metadata.Intermediary.Maven)))
|
2024-11-01 05:55:41 -06:00
|
|
|
|
2024-10-31 16:23:38 -06:00
|
|
|
instanceObject.MainClass = metadata.LauncherMeta.MainClass["client"]
|
|
|
|
instanceObject.FabricVersion = fabricVersion
|
|
|
|
dir, _ := os.UserConfigDir()
|
2024-11-26 10:22:37 -07:00
|
|
|
InstallFabricLibs(instanceObject.MinecraftVersion, fabricVersion, filepath.Join(dir, "FCLauncher", "lib"), i.app)
|
2024-10-31 16:23:38 -06:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-10-31 18:21:09 -06:00
|
|
|
|
2024-11-01 05:55:41 -06:00
|
|
|
func (i *InstanceManager) InstallQuilt(instance string, quiltVersion string) {
|
2024-10-31 18:21:09 -06:00
|
|
|
i.app.Status("Installing Quilt")
|
|
|
|
instanceObject, err := i.GetInstance(instance)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Instance does not exist\n")
|
|
|
|
}
|
|
|
|
metadata, err := GetQuiltMetadata(instanceObject.MinecraftVersion, quiltVersion)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("unable to get version metadata\n")
|
|
|
|
}
|
2024-11-01 05:55:41 -06:00
|
|
|
client:
|
2024-10-31 18:21:09 -06:00
|
|
|
for _, lib := range metadata.LauncherMeta.Libraries.Client {
|
2024-11-26 16:23:54 -07:00
|
|
|
tokens := strings.Split(ProcessMavenPath(lib.Name), "/")
|
2024-10-31 18:21:09 -06:00
|
|
|
pkg := tokens[len(tokens)-2]
|
|
|
|
instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(ProcessMavenPath(lib.Name), ProcessMavenFilename(lib.Name)))
|
|
|
|
for ind, path := range instanceObject.Libraries {
|
2024-11-26 16:23:54 -07:00
|
|
|
tokens := strings.Split(path, "/")
|
2024-10-31 18:21:09 -06:00
|
|
|
if pkg == tokens[len(tokens)-3] {
|
|
|
|
instanceObject.Libraries[ind] = filepath.Join(ProcessMavenPath(lib.Name), ProcessMavenFilename(lib.Name))
|
|
|
|
fmt.Printf("duplicate library %s\n", pkg)
|
|
|
|
continue client
|
|
|
|
}
|
|
|
|
}
|
2024-11-01 05:55:41 -06:00
|
|
|
}
|
|
|
|
common:
|
2024-10-31 18:21:09 -06:00
|
|
|
for _, lib := range metadata.LauncherMeta.Libraries.Common {
|
2024-11-26 16:23:54 -07:00
|
|
|
tokens := strings.Split(ProcessMavenPath(lib.Name), "/")
|
2024-10-31 18:21:09 -06:00
|
|
|
pkg := tokens[len(tokens)-2]
|
|
|
|
instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(ProcessMavenPath(lib.Name), ProcessMavenFilename(lib.Name)))
|
|
|
|
for ind, path := range instanceObject.Libraries {
|
2024-11-26 16:23:54 -07:00
|
|
|
tokens := strings.Split(path, "/")
|
2024-10-31 18:21:09 -06:00
|
|
|
if pkg == tokens[len(tokens)-3] {
|
|
|
|
instanceObject.Libraries[ind] = filepath.Join(ProcessMavenPath(lib.Name), ProcessMavenFilename(lib.Name))
|
|
|
|
fmt.Printf("duplicate library %s\n", pkg)
|
|
|
|
continue common
|
|
|
|
}
|
|
|
|
}
|
2024-11-01 05:55:41 -06:00
|
|
|
}
|
2024-10-31 18:21:09 -06:00
|
|
|
instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(ProcessMavenPath(metadata.Loader.Maven), ProcessMavenFilename(metadata.Loader.Maven)))
|
|
|
|
|
|
|
|
instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(ProcessMavenPath(metadata.Intermediary.Maven), ProcessMavenFilename(metadata.Intermediary.Maven)))
|
2024-11-01 05:55:41 -06:00
|
|
|
|
2024-10-31 18:57:54 -06:00
|
|
|
instanceObject.Libraries = append(instanceObject.Libraries, filepath.Join(ProcessMavenPath(metadata.Hashed.Maven), ProcessMavenFilename(metadata.Hashed.Maven)))
|
|
|
|
|
2024-10-31 18:21:09 -06:00
|
|
|
instanceObject.MainClass = metadata.LauncherMeta.MainClass["client"]
|
|
|
|
instanceObject.QuiltVersion = quiltVersion
|
|
|
|
dir, _ := os.UserConfigDir()
|
2024-11-26 10:22:37 -07:00
|
|
|
InstallQuiltLibs(instanceObject.MinecraftVersion, quiltVersion, filepath.Join(dir, "FCLauncher", "lib"), i.app)
|
2024-10-31 18:21:09 -06:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-11-01 18:08:29 -06:00
|
|
|
|
|
|
|
func (i *InstanceManager) InstallForge(instance string, forgeVersion string) {
|
|
|
|
instanceObject, err := i.GetInstance(instance)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Unable to find instance: %s\n", err)
|
|
|
|
}
|
|
|
|
installData, err := GetForgeInstallData(instanceObject.MinecraftVersion, forgeVersion)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Unable to get install data: %s\n", err)
|
|
|
|
}
|
|
|
|
dir, _ := os.UserConfigDir()
|
|
|
|
InstallForgeLibs(instanceObject.MinecraftVersion, forgeVersion, filepath.Join(dir, "FCLauncher", "lib"))
|
|
|
|
instanceObject.ForgeVersion = forgeVersion
|
|
|
|
outer:
|
|
|
|
for _, lib := range installData.Libraries {
|
2024-11-26 16:23:54 -07:00
|
|
|
tokens := strings.Split(lib.Downloads.Artifact.Path, "/")
|
2024-11-01 18:08:29 -06:00
|
|
|
pkg := tokens[len(tokens)-2]
|
|
|
|
instanceObject.Libraries = append(instanceObject.Libraries, lib.Downloads.Artifact.Path)
|
|
|
|
for ind, path := range instanceObject.Libraries {
|
2024-11-26 16:23:54 -07:00
|
|
|
tokens := strings.Split(path, "/")
|
2024-11-01 18:08:29 -06:00
|
|
|
if pkg == tokens[len(tokens)-3] {
|
|
|
|
instanceObject.Libraries[ind] = filepath.Join(ProcessMavenPath(lib.Name), ProcessMavenFilename(lib.Name))
|
|
|
|
fmt.Printf("duplicate library %s\n", pkg)
|
|
|
|
continue outer
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
instanceObject.MainClass = installData.MainClass
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2024-11-25 13:23:06 -07:00
|
|
|
|
|
|
|
func (i *InstanceManager) ImportModpack(modpack Modpack, name string) {
|
2024-11-26 10:22:37 -07:00
|
|
|
i.app.Status(fmt.Sprintf("Downloading %s", modpack.Name))
|
2024-11-25 13:23:06 -07:00
|
|
|
buff := new(bytes.Buffer)
|
2024-11-26 15:37:35 -07:00
|
|
|
err := HttpDownload(filepath.Join(modpack.Id, modpack.Versions[len(modpack.Versions)-1].File), buff, i.app.Ctx)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Unable to download modpack file: %s\n", err)
|
|
|
|
return
|
|
|
|
}
|
2024-11-25 13:23:06 -07:00
|
|
|
i.ImportMrpack(buff, name)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *InstanceManager) ImportMrpack(data io.Reader, name string) {
|
2024-11-25 14:28:32 -07:00
|
|
|
dir, _ := os.UserConfigDir()
|
|
|
|
InstancePath := filepath.Join(dir, "FCLauncher", "instances", name, "minecraft")
|
2024-11-25 13:23:06 -07:00
|
|
|
zr := zipstream.NewReader(data)
|
|
|
|
mrdata := MrData{}
|
2024-11-26 10:22:37 -07:00
|
|
|
i.app.Status("Unpacking modpack File")
|
2024-11-25 13:23:06 -07:00
|
|
|
for {
|
|
|
|
entry, err := zr.GetNextEntry()
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
2024-11-26 15:31:01 -07:00
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error unpacking modpack file: %s\n", err)
|
2024-11-26 15:37:35 -07:00
|
|
|
break
|
2024-11-26 15:31:01 -07:00
|
|
|
}
|
2024-11-25 13:23:06 -07:00
|
|
|
if entry.Name == "modrinth.index.json" {
|
2024-11-26 10:22:37 -07:00
|
|
|
i.app.Status("Loading metadata")
|
2024-11-25 13:23:06 -07:00
|
|
|
file, _ := entry.Open()
|
|
|
|
data, _ := io.ReadAll(file)
|
|
|
|
json.Unmarshal(data, &mrdata)
|
2024-11-25 14:28:32 -07:00
|
|
|
} else {
|
2024-11-26 10:22:37 -07:00
|
|
|
i.app.Status(fmt.Sprintf("Unpacking %s", entry.Name))
|
2024-11-25 14:28:32 -07:00
|
|
|
prefix := strings.Split(entry.Name, "/")[0]
|
|
|
|
if prefix == "overrides" || prefix == "client-overrides" {
|
|
|
|
path := strings.SplitN(entry.Name, "/", 2)[1]
|
|
|
|
if entry.IsDir() {
|
2024-11-25 14:55:04 -07:00
|
|
|
fmt.Printf("creating directory %s\n", filepath.Join(InstancePath, path))
|
2024-11-25 14:28:32 -07:00
|
|
|
if _, err := os.Stat(filepath.Join(InstancePath, path)); err != nil {
|
|
|
|
os.MkdirAll(filepath.Join(InstancePath, path), 0755)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
zf, _ := entry.Open()
|
|
|
|
defer zf.Close()
|
2024-11-25 14:55:04 -07:00
|
|
|
fileDir := ""
|
|
|
|
tokens := strings.Split(path, "/")
|
|
|
|
for ind, token := range tokens {
|
|
|
|
if ind != len(tokens)-1 {
|
|
|
|
fileDir = filepath.Join(fileDir, token)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Printf("creating directory %s\n", filepath.Join(InstancePath, fileDir))
|
|
|
|
if _, err := os.Stat(filepath.Join(InstancePath, fileDir)); err != nil {
|
|
|
|
os.MkdirAll(filepath.Join(InstancePath, fileDir), 0755)
|
|
|
|
}
|
2024-11-25 14:28:32 -07:00
|
|
|
file, _ := os.OpenFile(filepath.Join(InstancePath, path), os.O_CREATE|os.O_RDWR, 0755)
|
|
|
|
defer file.Close()
|
|
|
|
io.Copy(file, zf)
|
|
|
|
}
|
|
|
|
}
|
2024-11-25 13:23:06 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
i.InstallVanilla(mrdata.Dependencies["minecraft"], name)
|
|
|
|
if mrdata.Dependencies["forge"] != "" {
|
|
|
|
fmt.Printf("Forge not implemented!")
|
|
|
|
//implement forge
|
|
|
|
} else if mrdata.Dependencies["neoforge"] != "" {
|
|
|
|
fmt.Printf("Neoforge not implemented!")
|
|
|
|
//implement neoforge
|
|
|
|
} else if mrdata.Dependencies["fabric-loader"] != "" {
|
|
|
|
i.InstallFabric(name, mrdata.Dependencies["fabric-loader"])
|
|
|
|
} else if mrdata.Dependencies["quilt-loader"] != "" {
|
|
|
|
i.InstallQuilt(name, mrdata.Dependencies["quilt-loader"])
|
|
|
|
}
|
2024-11-26 10:22:37 -07:00
|
|
|
i.app.Status("Downloading Mods")
|
2024-11-25 14:28:32 -07:00
|
|
|
for _, f := range mrdata.Files {
|
|
|
|
fmt.Printf("Downloading %s\n", f.Path)
|
2024-11-26 10:22:37 -07:00
|
|
|
i.app.Status(fmt.Sprintf("Downloading %s", f.Path))
|
2024-11-25 14:28:32 -07:00
|
|
|
resp, err := http.Get(f.Downloads[0])
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Unable to download file %s\n", err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
2024-11-26 10:22:37 -07:00
|
|
|
buff := new(bytes.Buffer)
|
|
|
|
downloaded := 0
|
|
|
|
for {
|
|
|
|
count, err := io.CopyN(buff, resp.Body, BlockSize)
|
|
|
|
if err == io.EOF {
|
|
|
|
downloaded += int(count)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error Downloading libs: %e\n", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
downloaded += int(count)
|
|
|
|
wruntime.EventsEmit(i.app.Ctx, "download", downloaded, f.FileSize)
|
|
|
|
}
|
2024-11-25 14:28:32 -07:00
|
|
|
fileDir := ""
|
|
|
|
tokens := strings.Split(f.Path, "/")
|
|
|
|
for ind, token := range tokens {
|
|
|
|
if ind != len(tokens)-1 {
|
|
|
|
fileDir = filepath.Join(fileDir, token)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if _, err := os.Stat(filepath.Join(InstancePath, fileDir)); err != nil {
|
|
|
|
os.MkdirAll(filepath.Join(InstancePath, fileDir), 0755)
|
|
|
|
}
|
|
|
|
file, _ := os.OpenFile(filepath.Join(InstancePath, f.Path), os.O_CREATE|os.O_RDWR, 0755)
|
|
|
|
defer file.Close()
|
2024-11-26 10:22:37 -07:00
|
|
|
io.Copy(file, buff)
|
|
|
|
wruntime.EventsEmit(i.app.Ctx, "download_complete")
|
2024-11-25 14:28:32 -07:00
|
|
|
}
|
2024-11-25 13:23:06 -07:00
|
|
|
}
|