installation and launching of vanilla minecraft working
This commit is contained in:
parent
ab0bfebe87
commit
2bbb4b8cf0
@ -7,17 +7,23 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Instance struct {
|
||||
InstanceName string
|
||||
ModpackId string
|
||||
ModpackVersion string
|
||||
MinecraftVersion string
|
||||
ForgeVersion string
|
||||
NeoForgeVersion string
|
||||
FabricVersion string
|
||||
QuiltVersion string
|
||||
JavaVersion int
|
||||
}
|
||||
|
||||
type InstanceManager struct {
|
||||
@ -36,7 +42,8 @@ type component struct {
|
||||
|
||||
func (i *InstanceManager)SearchInstances() {
|
||||
i.instances = []Instance{}
|
||||
dir := i.app.PrismLauncher.GetInstanceDir()
|
||||
dir, _ := os.UserConfigDir()
|
||||
dir = filepath.Join(dir, "FCLauncher", "instances")
|
||||
if _, err := os.Stat(dir); err != nil {
|
||||
return
|
||||
}
|
||||
@ -148,13 +155,59 @@ func (i *InstanceManager)InstallModpack(modpack Modpack, instanceName string){
|
||||
}
|
||||
|
||||
func (i *InstanceManager)InstallVanilla(version string, instanceName string) {
|
||||
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)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to download libs: %s\n", err)
|
||||
} else {
|
||||
fmt.Printf("Libs Downloaded")
|
||||
}
|
||||
InstallNatives(version, filepath.Join(dir, "FCLauncher", "instances", instanceName, "minecraft", "natives"))
|
||||
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 {
|
||||
fmt.Printf("Unable to obtain metadata: %s\n", err)
|
||||
} else {
|
||||
fmt.Printf("Version Metadata: %+v", metadata)
|
||||
fmt.Printf("unable to pull metadata: %s\n", err)
|
||||
}
|
||||
time.Sleep(time.Second * 1)
|
||||
|
||||
err = os.MkdirAll(filepath.Join(dir, "FCLauncher", "instances", instanceName, "minecraft"), 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to create directory: %s\n", err)
|
||||
}
|
||||
|
||||
|
||||
instance := Instance{InstanceName: instanceName, MinecraftVersion: version, JavaVersion: metadata.JavaVersion.MajorVersion}
|
||||
data, err := json.Marshal(instance)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to marshal json data: %s\n", err)
|
||||
}
|
||||
f, err := os.OpenFile(filepath.Join(dir, "FCLauncher", "instances", instanceName, "instance.json"), os.O_CREATE|os.O_RDWR, 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to open file: %s\n", err)
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
_, err = f.Write(data)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to write data: %s\n", err)
|
||||
}
|
||||
i.instances = append(i.instances, instance)
|
||||
|
||||
if !i.app.Java.CheckJavaVer(instance.JavaVersion) {
|
||||
i.app.Status(fmt.Sprintf("Installing Java Version %d", instance.JavaVersion))
|
||||
i.app.Java.InstallJavaVer(instance.JavaVersion)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -163,6 +216,7 @@ func (i *InstanceManager)GetInstances() []Instance{
|
||||
}
|
||||
|
||||
func (i *InstanceManager)CheckUpdate(instance Instance){
|
||||
return
|
||||
i.app.Status("Checking for Updates")
|
||||
i.app.Modpacks.QuerryModpacks()
|
||||
pack := i.app.Modpacks.GetModpack(instance.ModpackId)
|
||||
@ -185,3 +239,37 @@ 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")
|
||||
}
|
||||
instanceObject := Instance{}
|
||||
found := false
|
||||
for _, inst := range i.instances {
|
||||
if inst.InstanceName == instance {
|
||||
instanceObject = inst
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
fmt.Printf("unable to find instance %s\n", instance)
|
||||
}
|
||||
execName := "java"
|
||||
suffix := "lin"
|
||||
if runtime.GOOS == "windows" {
|
||||
execName = "Java.exe"
|
||||
suffix = "win"
|
||||
}
|
||||
dir = filepath.Join(dir, "FCLauncher")
|
||||
args, err := GetOfflineLaunchArgs(instanceObject.MinecraftVersion, filepath.Join(dir, "lib"), filepath.Join(dir, "bin"), filepath.Join(dir, "assets"), filepath.Join(dir, "instances", instance, "minecraft"), "Player")
|
||||
if err != nil {
|
||||
fmt.Printf("unable to get launch args: %s\n", err)
|
||||
}
|
||||
fmt.Printf("Args: %+v", args)
|
||||
child := exec.Command(filepath.Join(dir, "java", fmt.Sprintf("java-%d-%s", instanceObject.JavaVersion, suffix), "bin", execName), args...)
|
||||
data, err := child.CombinedOutput()
|
||||
fmt.Printf("Command Output: %s\n", data)
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,9 @@ import (
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
)
|
||||
|
||||
|
||||
const client_id string = "9305aeb8-5ecb-4e7a-b28f-c33aefcfbd8d"
|
||||
|
||||
// App struct
|
||||
type App struct {
|
||||
Ctx context.Context
|
||||
|
@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {GetModpacks, GetModpack} from '../wailsjs/go/main/ModpackManager.js'
|
||||
import {InstallVanilla, GetInstances, CheckUpdate} from '../wailsjs/go/main/InstanceManager.js'
|
||||
import {LaunchInstance} from '../wailsjs/go/main/Prism.js'
|
||||
import {InstallVanilla, LaunchInstance, GetInstances, CheckUpdate} from '../wailsjs/go/main/InstanceManager.js'
|
||||
import {GetVersions} from '../wailsjs/go/main/App.js'
|
||||
import {onMount} from 'svelte'
|
||||
import {loading} from './global.ts'
|
||||
@ -10,7 +9,7 @@
|
||||
let modpacks: string[] = []
|
||||
let pack: string
|
||||
let instances: Instance[] = []
|
||||
let instance: Instance
|
||||
let instance: string
|
||||
let addingInstance: boolean = false
|
||||
let name: string = "New Modpack"
|
||||
|
||||
@ -22,7 +21,7 @@
|
||||
})
|
||||
GetInstances().then((result) => {
|
||||
instances = result
|
||||
instance = instances[0]
|
||||
instance = instances[0].InstanceName
|
||||
})
|
||||
}
|
||||
|
||||
@ -32,11 +31,9 @@
|
||||
|
||||
function onclick(event) {
|
||||
$loading = true
|
||||
CheckUpdate(instance).then(() => {
|
||||
LaunchInstance(instance).then(() => {
|
||||
$loading = false
|
||||
window.runtime.Quit()
|
||||
})
|
||||
LaunchInstance(instance).then(() => {
|
||||
$loading = false
|
||||
window.runtime.Quit()
|
||||
})
|
||||
}
|
||||
|
||||
@ -59,7 +56,7 @@
|
||||
<main>
|
||||
<select bind:value={instance} name="pack">Select a Modpack:
|
||||
{#each instances as instance}
|
||||
<option value={instance}>{instance.InstanceName}</option>
|
||||
<option value={instance.InstanceName}>{instance.InstanceName}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<button on:click={onclick}>Launch</button>
|
||||
|
@ -10,4 +10,6 @@ export function InstallModpack(arg1:main.Modpack,arg2:string):Promise<void>;
|
||||
|
||||
export function InstallVanilla(arg1:string,arg2:string):Promise<void>;
|
||||
|
||||
export function LaunchInstance(arg1:string):Promise<void>;
|
||||
|
||||
export function SearchInstances():Promise<void>;
|
||||
|
@ -18,6 +18,10 @@ export function InstallVanilla(arg1, arg2) {
|
||||
return window['go']['main']['InstanceManager']['InstallVanilla'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function LaunchInstance(arg1) {
|
||||
return window['go']['main']['InstanceManager']['LaunchInstance'](arg1);
|
||||
}
|
||||
|
||||
export function SearchInstances() {
|
||||
return window['go']['main']['InstanceManager']['SearchInstances']();
|
||||
}
|
||||
|
@ -4,6 +4,12 @@ export namespace main {
|
||||
InstanceName: string;
|
||||
ModpackId: string;
|
||||
ModpackVersion: string;
|
||||
MinecraftVersion: string;
|
||||
ForgeVersion: string;
|
||||
NeoForgeVersion: string;
|
||||
FabricVersion: string;
|
||||
QuiltVersion: string;
|
||||
JavaVersion: number;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new Instance(source);
|
||||
@ -14,6 +20,12 @@ export namespace main {
|
||||
this.InstanceName = source["InstanceName"];
|
||||
this.ModpackId = source["ModpackId"];
|
||||
this.ModpackVersion = source["ModpackVersion"];
|
||||
this.MinecraftVersion = source["MinecraftVersion"];
|
||||
this.ForgeVersion = source["ForgeVersion"];
|
||||
this.NeoForgeVersion = source["NeoForgeVersion"];
|
||||
this.FabricVersion = source["FabricVersion"];
|
||||
this.QuiltVersion = source["QuiltVersion"];
|
||||
this.JavaVersion = source["JavaVersion"];
|
||||
}
|
||||
}
|
||||
export class Version {
|
||||
|
BIN
fclauncher/logs/2024-10-30-1.log.gz
Normal file
BIN
fclauncher/logs/2024-10-30-1.log.gz
Normal file
Binary file not shown.
BIN
fclauncher/logs/2024-10-30-2.log.gz
Normal file
BIN
fclauncher/logs/2024-10-30-2.log.gz
Normal file
Binary file not shown.
BIN
fclauncher/logs/2024-10-30-3.log.gz
Normal file
BIN
fclauncher/logs/2024-10-30-3.log.gz
Normal file
Binary file not shown.
BIN
fclauncher/logs/2024-10-30-4.log.gz
Normal file
BIN
fclauncher/logs/2024-10-30-4.log.gz
Normal file
Binary file not shown.
BIN
fclauncher/logs/2024-10-30-5.log.gz
Normal file
BIN
fclauncher/logs/2024-10-30-5.log.gz
Normal file
Binary file not shown.
77
fclauncher/logs/latest.log
Normal file
77
fclauncher/logs/latest.log
Normal file
File diff suppressed because one or more lines are too long
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
@ -9,7 +10,12 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
wruntime "github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"github.com/zhyee/zipstream"
|
||||
)
|
||||
|
||||
type McVersionManifestEntry struct {
|
||||
@ -59,6 +65,7 @@ type McLibraryArtifact struct {
|
||||
|
||||
type McLibraryDownload struct {
|
||||
Artifact McLibraryArtifact
|
||||
Classifiers map[string]interface{}
|
||||
}
|
||||
|
||||
type McRuleOs struct {
|
||||
@ -77,6 +84,7 @@ type McLibrary struct {
|
||||
Downloads McLibraryDownload
|
||||
Name string
|
||||
Rules []McRule
|
||||
Natives map[string]string
|
||||
}
|
||||
|
||||
type McDownload struct {
|
||||
@ -100,6 +108,7 @@ type McMetadata struct {
|
||||
ReleaseTime time.Time
|
||||
Time time.Time
|
||||
Type string
|
||||
MinecraftArguments string
|
||||
}
|
||||
|
||||
func GetVersionManifest() (McVersionManifest, error) {
|
||||
@ -176,7 +185,6 @@ func GetVersionMetadata(wantedVersion string) (McMetadata, error) {
|
||||
if hex.EncodeToString(sha[:20]) == version.Sha1{
|
||||
metadata := McMetadata{}
|
||||
json.Unmarshal(data, &metadata)
|
||||
fmt.Printf("Found cache!\n")
|
||||
return metadata, nil
|
||||
}
|
||||
}
|
||||
@ -214,3 +222,379 @@ func GetVersionMetadata(wantedVersion string) (McMetadata, error) {
|
||||
}
|
||||
return McMetadata{}, fmt.Errorf("Unable to find version %s\n", wantedVersion)
|
||||
}
|
||||
|
||||
func GetAssetIndex(mcVersion string) ([]string, error) {
|
||||
found := false
|
||||
var data []byte
|
||||
metadata, err := GetVersionMetadata(mcVersion)
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("Unable to pull manifest: %e\n", err)
|
||||
}
|
||||
dir, _ := os.UserConfigDir()
|
||||
path := filepath.Join(dir, "FCLauncher", "assets", "indexes")
|
||||
if _, err := os.Stat(filepath.Join(path, metadata.Assets+".json")); err == nil {
|
||||
//cache file exists
|
||||
if f, err := os.OpenFile(filepath.Join(path, metadata.Assets+".json"), 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]) == metadata.AssetIndex.Sha1 {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
//no cache file
|
||||
data = []byte{}
|
||||
resp, err := http.Get(metadata.AssetIndex.Url)
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("Unable to pull asset index: %e\n", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("Unable to pull asset index: %e\n", err)
|
||||
}
|
||||
sha := sha1.Sum(data)
|
||||
if hex.EncodeToString(sha[:20]) != metadata.AssetIndex.Sha1 {
|
||||
return []string{}, fmt.Errorf("Sha mismatch!\n")
|
||||
}
|
||||
os.MkdirAll(path, 0755)
|
||||
f, _ := os.OpenFile(filepath.Join(path, metadata.Assets+".json"), os.O_CREATE|os.O_RDWR, 0755)
|
||||
defer f.Close()
|
||||
f.Write(data)
|
||||
}
|
||||
|
||||
//at this point data is populated
|
||||
var index map[string]interface{}
|
||||
json.Unmarshal(data, &index)
|
||||
index = index["objects"].(map[string]interface{})
|
||||
hashes := []string{}
|
||||
for _, val := range index {
|
||||
index_map := val.(map[string]interface{})
|
||||
hashes = append(hashes, index_map["hash"].(string))
|
||||
}
|
||||
return hashes, nil
|
||||
}
|
||||
|
||||
func DownloadAssets(mcVersion string, assetPath string, a App) error {
|
||||
a.Status("Downloading Minecraft Assets")
|
||||
assets, err := GetAssetIndex(mcVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to get asset index: %e\n", err)
|
||||
}
|
||||
metadata, err := GetVersionMetadata(mcVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to get version metadata: %e\n", err)
|
||||
}
|
||||
total := metadata.AssetIndex.TotalSize
|
||||
downloaded := 0
|
||||
wruntime.EventsEmit(a.Ctx, "download", downloaded, total)
|
||||
for _, hash := range assets {
|
||||
if _, err := os.Stat(filepath.Join(assetPath, "objects", hash[:2], hash)); err == nil {
|
||||
f, _ := os.OpenFile(filepath.Join(assetPath, "objects", hash[:2], hash), os.O_RDONLY, 0755)
|
||||
defer f.Close()
|
||||
data, _ := io.ReadAll(f)
|
||||
sha := sha1.Sum(data)
|
||||
if hex.EncodeToString(sha[:20]) == hash {
|
||||
downloaded += len(data)
|
||||
wruntime.EventsEmit(a.Ctx, "download", downloaded, total)
|
||||
continue
|
||||
}
|
||||
}
|
||||
resp, err := http.Get(fmt.Sprintf("https://resources.download.minecraft.net/%s/%s", hash[:2], hash))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to download assets: %e\n", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
buff := new(bytes.Buffer)
|
||||
for {
|
||||
count, err := io.CopyN(buff, resp.Body, BlockSize)
|
||||
if err == io.EOF {
|
||||
downloaded += int(count)
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error Downloading assets: %e\n", err)
|
||||
}
|
||||
downloaded += int(count)
|
||||
wruntime.EventsEmit(a.Ctx, "download", downloaded, total)
|
||||
}
|
||||
data := buff.Bytes()
|
||||
sha := sha1.Sum(data)
|
||||
if hex.EncodeToString(sha[:20]) != hash {
|
||||
return fmt.Errorf("unable to download assets: Sha1 Mismatch\n")
|
||||
}
|
||||
err = os.MkdirAll(filepath.Join(assetPath, "objects", hash[:2]), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to download assets: Unable to create directory\n")
|
||||
}
|
||||
f, err := os.OpenFile(filepath.Join(assetPath, "objects", hash[:2], hash), os.O_CREATE|os.O_RDWR, 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to download assets: Unable to open file\n")
|
||||
}
|
||||
defer f.Close()
|
||||
f.Write(data)
|
||||
wruntime.EventsEmit(a.Ctx, "download", downloaded, total)
|
||||
}
|
||||
wruntime.EventsEmit(a.Ctx, "download_complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
func DownloadLibraries(mcVersion string, libPath string, a App) error {
|
||||
metadata, err := GetVersionMetadata(mcVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to pull version metadata: %e\n", err)
|
||||
}
|
||||
for _, lib := range metadata.Libraries {
|
||||
a.Status(fmt.Sprintf("Checking %s\n", lib.Name))
|
||||
if _, err := os.Stat(filepath.Join(libPath, lib.Downloads.Artifact.Path)); err == nil {
|
||||
f, _ := os.OpenFile(filepath.Join(libPath, lib.Downloads.Artifact.Path), os.O_CREATE|os.O_RDWR, 0755)
|
||||
defer f.Close()
|
||||
data, _ := io.ReadAll(f)
|
||||
sha := sha1.Sum(data)
|
||||
if hex.EncodeToString(sha[:20]) == lib.Downloads.Artifact.Sha1 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
a.Status(fmt.Sprintf("Downloading %s\n", lib.Name))
|
||||
resp, err := http.Get(lib.Downloads.Artifact.Url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to download libs: %e\n", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
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 {
|
||||
return fmt.Errorf("Error Downloading libs: %e\n", err)
|
||||
}
|
||||
downloaded += int(count)
|
||||
wruntime.EventsEmit(a.Ctx, "download", downloaded, resp.ContentLength)
|
||||
}
|
||||
data := buff.Bytes()
|
||||
sha := sha1.Sum(data)
|
||||
if hex.EncodeToString(sha[:20]) != lib.Downloads.Artifact.Sha1 {
|
||||
return fmt.Errorf("unable to download libs: Sha1 Mismatch\n")
|
||||
}
|
||||
path := ""
|
||||
tokens := strings.Split(lib.Downloads.Artifact.Path, "/")
|
||||
for ind, token := range tokens {
|
||||
if ind != len(tokens)-1 {
|
||||
path = filepath.Join(path, token)
|
||||
}
|
||||
}
|
||||
err = os.MkdirAll(filepath.Join(libPath, path), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to download libs: Unable to create directory\n")
|
||||
}
|
||||
f, err := os.OpenFile(filepath.Join(libPath, lib.Downloads.Artifact.Path), os.O_CREATE|os.O_RDWR, 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to download libs: Unable to open file\n")
|
||||
}
|
||||
defer f.Close()
|
||||
f.Write(data)
|
||||
wruntime.EventsEmit(a.Ctx, "download_complete")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func InstallNatives(mcVersion string, nativesDir string){
|
||||
metadata, _ := GetVersionMetadata(mcVersion)
|
||||
for _, lib := range metadata.Libraries {
|
||||
if lib.Natives != nil {
|
||||
glob := lib.Natives[runtime.GOOS]
|
||||
fmt.Printf("glob is: %s\n", glob)
|
||||
if lib.Downloads.Classifiers[glob] != nil {
|
||||
artifact := lib.Downloads.Classifiers[glob].(map[string]interface{})
|
||||
resp, _ := http.Get(artifact["url"].(string))
|
||||
defer resp.Body.Close()
|
||||
zr := zipstream.NewReader(resp.Body)
|
||||
for {
|
||||
e, err := zr.GetNextEntry()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if e.IsDir() {
|
||||
os.MkdirAll(filepath.Join(nativesDir, e.Name), 0755)
|
||||
} else {
|
||||
zc, _ := e.Open()
|
||||
f, _ := os.OpenFile(filepath.Join(nativesDir, e.Name), os.O_CREATE|os.O_RDWR, 0755)
|
||||
defer zc.Close()
|
||||
defer f.Close()
|
||||
io.Copy(f, zc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func DownloadExecutable(mcVersion string, binDir string, a App) error {
|
||||
metadata, err := GetVersionMetadata(mcVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to pull version metadata: %e\n", err)
|
||||
}
|
||||
a.Status(fmt.Sprintf("Checking Minecraft %s Executable\n", mcVersion))
|
||||
if _, err := os.Stat(filepath.Join(binDir, mcVersion, "client.jar")); err == nil {
|
||||
f, _ := os.OpenFile(filepath.Join(binDir, mcVersion, "client.jar"), os.O_CREATE|os.O_RDWR, 0755)
|
||||
defer f.Close()
|
||||
data, _ := io.ReadAll(f)
|
||||
sha := sha1.Sum(data)
|
||||
if hex.EncodeToString(sha[:20]) == metadata.Downloads["client"].Sha1 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
a.Status(fmt.Sprintf("Downloading Minecraft %s Executable\n", mcVersion))
|
||||
resp, err := http.Get(metadata.Downloads["client"].Url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to download executable: %e\n", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
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 {
|
||||
return fmt.Errorf("Error Downloading executable: %e\n", err)
|
||||
}
|
||||
downloaded += int(count)
|
||||
wruntime.EventsEmit(a.Ctx, "download", downloaded, resp.ContentLength)
|
||||
}
|
||||
data := buff.Bytes()
|
||||
sha := sha1.Sum(data)
|
||||
if hex.EncodeToString(sha[:20]) != metadata.Downloads["client"].Sha1 {
|
||||
return fmt.Errorf("unable to download executable: Sha1 Mismatch\n")
|
||||
}
|
||||
err = os.MkdirAll(filepath.Join(binDir, mcVersion), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to download executable: Unable to create directory\n")
|
||||
}
|
||||
f, err := os.OpenFile(filepath.Join(binDir, mcVersion, "client.jar"), os.O_CREATE|os.O_RDWR, 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to download executable: Unable to open file\n")
|
||||
}
|
||||
defer f.Close()
|
||||
f.Write(data)
|
||||
wruntime.EventsEmit(a.Ctx, "download_complete")
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func GetBaseLaunchArgs(mcVersion string, libDir string, binDir string, assetDir string, gameDir string) ([]string, error) {
|
||||
args := []string{}
|
||||
metadata, err := GetVersionMetadata(mcVersion)
|
||||
if err != nil {
|
||||
return args, fmt.Errorf("GetLaunchArgs: %e\n", err)
|
||||
}
|
||||
|
||||
searchArgs := []string{}
|
||||
|
||||
if metadata.MinecraftArguments != "" {
|
||||
searchArgs = strings.Split(metadata.MinecraftArguments, " ")
|
||||
} else {
|
||||
searchArgs = metadata.Arguments.Game
|
||||
}
|
||||
|
||||
args = append(args, "-Djava.library.path="+filepath.Join(gameDir, "natives"))
|
||||
args = append(args, "-Djna.tmpdir="+filepath.Join(gameDir, "natives"))
|
||||
args = append(args, "-Dorg.lwjgl.system.SharedLibraryExtractpath="+filepath.Join(gameDir, "natives"))
|
||||
args = append(args, "-Dio.netty.native.workdir="+filepath.Join(gameDir, "natives"))
|
||||
args = append(args, "-Xms512m")
|
||||
args = append(args, "-Xmx1024m")
|
||||
args = append(args, "-cp")
|
||||
arg := ""
|
||||
for _, lib := range metadata.Libraries {
|
||||
arg += filepath.Join(libDir, lib.Downloads.Artifact.Path) + ":"
|
||||
}
|
||||
arg += filepath.Join(binDir, mcVersion, "client.jar")
|
||||
args = append(args, arg)
|
||||
|
||||
|
||||
|
||||
args = append(args, metadata.MainClass)
|
||||
|
||||
for _, val := range searchArgs {
|
||||
switch val {
|
||||
case "${version_name}":
|
||||
args = append(args, mcVersion)
|
||||
case "${game_directory}":
|
||||
args = append(args, gameDir)
|
||||
case "${assets_root}":
|
||||
args = append(args, assetDir)
|
||||
case "${clientid}":
|
||||
args = append(args, client_id)
|
||||
case "${version_type}":
|
||||
args = append(args, metadata.Type)
|
||||
case "${user_type}":
|
||||
args = append(args, "mojang")
|
||||
case "${assets_index_name}":
|
||||
args = append(args, metadata.Assets)
|
||||
case "${user_properties}":
|
||||
args = append(args, "null")
|
||||
default:
|
||||
args = append(args, val)
|
||||
}
|
||||
}
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
||||
|
||||
func GetOfflineLaunchArgs(mcVersion string, libDir string, binDir string, assetDir string, gameDir string, playerName string) ([]string, error) {
|
||||
args, err := GetBaseLaunchArgs(mcVersion, libDir, binDir, assetDir, gameDir)
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("GatOfflineLaunchArgs: %e\n", err)
|
||||
}
|
||||
|
||||
for ind, val := range args {
|
||||
switch val{
|
||||
case "${auth_player_name}":
|
||||
args[ind] = playerName
|
||||
case "${auth_uuid}":
|
||||
args[ind] = "null"
|
||||
case "${auth_access_token}":
|
||||
args[ind] = "null"
|
||||
case "${auth_xuid}":
|
||||
args[ind] = "null"
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func GetOnlineLaunchArgs(mcVersion string, libDir string, binDir string, assetDir string, gameDir string, playerName string) ([]string, error) {
|
||||
args, err := GetBaseLaunchArgs(mcVersion, libDir, binDir, assetDir, gameDir)
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("GatOfflineLaunchArgs: %e\n", err)
|
||||
}
|
||||
|
||||
for ind, val := range args {
|
||||
switch val{
|
||||
case "${auth_player_name}":
|
||||
args[ind] = val
|
||||
case "${auth_uuid}":
|
||||
args[ind] = val
|
||||
case "${auth_access_token}":
|
||||
args[ind] = val
|
||||
case "${auth_xuid}":
|
||||
args[ind] = val
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user