FCLauncher/fclauncher/minecraft.go

217 lines
4.8 KiB
Go
Raw Normal View History

2024-10-29 21:48:59 -06:00
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)
}