217 lines
4.8 KiB
Go
217 lines
4.8 KiB
Go
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)
|
|
}
|