Skip to content

Commit

Permalink
new java management. fixes basic 1.17 compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
fiws committed Jul 4, 2021
1 parent d12d268 commit e63cbcd
Show file tree
Hide file tree
Showing 10 changed files with 543 additions and 160 deletions.
5 changes: 1 addition & 4 deletions cmd/join.go
Expand Up @@ -102,15 +102,12 @@ func (j *joinRunner) RunE(cmd *cobra.Command, args []string) error {
Instance: instance,
ServerMode: false,
MinepkgVersion: rootCmd.Version,
UseSystemJava: viper.GetBool("useSystemJava"),
}
if err := cliLauncher.Prepare(); err != nil {
return err
}

if viper.GetBool("useSystemJava") {
instance.UseSystemJava()
}

opts := &instances.LaunchOptions{
JoinServer: ip + ":" + port,
RamMiB: j.ramMiB,
Expand Down
5 changes: 1 addition & 4 deletions cmd/launch.go
Expand Up @@ -94,10 +94,6 @@ func (l *launchRunner) RunE(cmd *cobra.Command, args []string) error {
logger.Fail("Can not launch forge modpacks for now. Sorry.")
}

if viper.GetBool("useSystemJava") {
l.instance.UseSystemJava()
}

// we need login credentials to launch the client
// the server needs no creds
if !l.serverMode {
Expand All @@ -115,6 +111,7 @@ func (l *launchRunner) RunE(cmd *cobra.Command, args []string) error {
ForceUpdate: l.forceUpdate,
MinepkgVersion: rootCmd.Version,
NonInteractive: viper.GetBool("nonInteractive"),
UseSystemJava: viper.GetBool("useSystemJava"),
}

if err := cliLauncher.Prepare(); err != nil {
Expand Down
76 changes: 40 additions & 36 deletions cmd/launch/prepare.go
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/jwalton/gchalk"
"github.com/minepkg/minepkg/internals/downloadmgr"
"github.com/minepkg/minepkg/internals/instances"
"github.com/minepkg/minepkg/internals/java"
"github.com/minepkg/minepkg/internals/minecraft"
"github.com/spf13/viper"
)
Expand Down Expand Up @@ -41,6 +42,12 @@ type CLILauncher struct {
// NonInteractive determines if fancy spinners or prompts should be displayed
NonInteractive bool

// UseSystemJava sets the instance to use the system java
// instead of the internal installation. This skips downloading java
UseSystemJava bool

javaFactory *java.Factory
java *java.Java
introPrinted bool
originalServerProps []byte
}
Expand All @@ -56,17 +63,7 @@ func (c *CLILauncher) Prepare() error {
c.printIntro()
c.introPrinted = true

javaUpdate := make(chan error)

if !instance.HasJava() {
go func() {
javaUpdate <- instance.UpdateJava()
}()
} else {
go func() {
javaUpdate <- nil
}()
}
javaUpdate := make(chan error, 1)

// resolve requirements
outdatedReqs, err := instance.AreRequirementsOutdated()
Expand All @@ -84,6 +81,28 @@ func (c *CLILauncher) Prepare() error {
instance.SaveLockfile()
}
fmt.Println()

if c.UseSystemJava {
// nothing gets downloaded. this is a success
javaUpdate <- nil
} else {
// we check if we need to download java
java, err := instance.Java()
if err != nil {
return err
}

if java.NeedsDownloading() {
fmt.Printf("│ %s\n", gchalk.Gray("[i] Starting Java download …"))
go func() {
javaUpdate <- java.Update(ctx)
}()
} else {
// nothing to download
javaUpdate <- nil
}
}

req := gchalk.Gray(fmt.Sprintf(" resolved from %s", c.Instance.Manifest.Requirements.Minecraft))
fmt.Println("│ Minecraft " + c.Instance.Lockfile.MinecraftVersion() + req)
if instance.Manifest.PlatformString() == "fabric" {
Expand Down Expand Up @@ -243,34 +262,19 @@ func (c *CLILauncher) printIntro() {

func (c *CLILauncher) printOutro() {
instance := c.Instance

javaDir := "(system java)"
if !c.UseSystemJava {
java, err := instance.Java()
if err != nil {
panic(err)
}
javaDir = java.Bin()
}
fmt.Println("│ minepkg " + c.MinepkgVersion)
fmt.Println("│ Java " + instance.JavaDir())
fmt.Println("│ Java " + javaDir)
}

// func (c *CLILauncher) newFetchDependencies(ctx context.Context) error {
// instance := c.Instance

// resolveStartTime := time.Now()
// resolver, err := instance.GetResolver(ctx)
// if err != nil {
// return err
// }

// p := tea.NewProgram(NewResolverUI(resolver))
// if err := p.Start(); err != nil {
// return err
// }

// timing := fmt.Sprintf(
// "Resolved %d packages in %s",
// len(resolver.BetterResolved),
// time.Since(resolveStartTime),
// )
// fmt.Print("│ " + gchalk.Gray(timing) + ".\n")

// return nil
// }

func (c *CLILauncher) newFetchDependencies(ctx context.Context) error {
instance := c.Instance

Expand Down
5 changes: 1 addition & 4 deletions cmd/try.go
Expand Up @@ -142,16 +142,13 @@ func (t *tryRunner) RunE(cmd *cobra.Command, args []string) error {
// add/overwrite the wanted mod or modpack
instance.Manifest.AddDependency(release.Package.Name, release.Package.Version)

if viper.GetBool("useSystemJava") {
instance.UseSystemJava()
}

cliLauncher := launch.CLILauncher{
Instance: instance,
ServerMode: t.serverMode,
OfflineMode: t.offlineMode,
MinepkgVersion: rootCmd.Version,
NonInteractive: viper.GetBool("nonInteractive"),
UseSystemJava: viper.GetBool("useSystemJava"),
}
if err := cliLauncher.Prepare(); err != nil {
return err
Expand Down
24 changes: 14 additions & 10 deletions internals/instances/instances.go
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/jwalton/gchalk"
"github.com/minepkg/minepkg/internals/commands"
"github.com/minepkg/minepkg/internals/java"

"github.com/minepkg/minepkg/internals/api"
"github.com/minepkg/minepkg/internals/mojang"
Expand Down Expand Up @@ -57,10 +58,11 @@ type Instance struct {
Lockfile *manifest.Lockfile
MojangCredentials *mojang.AuthResponse
MinepkgAPI *api.MinepkgAPI
JavaFactory *java.Factory

isFromWd bool
launchCmd string
javaBinary string
isFromWd bool
launchCmd string
java *java.Java
}

// LaunchCmd returns the cmd used to launch minecraft (if started)
Expand Down Expand Up @@ -164,8 +166,9 @@ func NewEmptyInstance() *Instance {
}

return &Instance{
GlobalDir: filepath.Join(userConfig, "minepkg"),
CacheDir: filepath.Join(userCache, "minepkg"),
GlobalDir: filepath.Join(userConfig, "minepkg"),
CacheDir: filepath.Join(userCache, "minepkg"),
JavaFactory: java.NewFactory(filepath.Join(userCache, "minepkg", "java")),
}
}

Expand Down Expand Up @@ -197,11 +200,12 @@ func NewInstanceFromWd() (*Instance, error) {
}

instance := &Instance{
Manifest: &manifest,
Directory: dir,
GlobalDir: filepath.Join(userConfig, "minepkg"),
CacheDir: filepath.Join(userCache, "minepkg"),
isFromWd: true,
Manifest: &manifest,
Directory: dir,
GlobalDir: filepath.Join(userConfig, "minepkg"),
CacheDir: filepath.Join(userCache, "minepkg"),
isFromWd: true,
JavaFactory: java.NewFactory(filepath.Join(userCache, "minepkg", "java")),
}

// initialize manifest
Expand Down
105 changes: 14 additions & 91 deletions internals/instances/java.go
@@ -1,104 +1,27 @@
package instances

import (
"errors"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"runtime"
"context"

"github.com/mholt/archiver/v3"
"github.com/Masterminds/semver/v3"
"github.com/minepkg/minepkg/internals/java"
)

// HasJava returns true if the internal java installation has been detected
// for this instance
func (i *Instance) HasJava() bool {
return i.javaBin() != ""
}

// UseSystemJava sets the instance to use the system java
// instead of the internal installation
func (i *Instance) UseSystemJava() {
i.javaBinary = "java"
}

// UpdateJava updates the local java installation
func (i *Instance) UpdateJava() error {
java, err := i.downloadJava()
if err != nil {
return err
}
i.javaBinary = java
return nil
}

// javaBin returns the internal java binary
// it caches the path if it finds a java installation
func (i *Instance) javaBin() string {
if i.javaBinary != "" {
return i.javaBinary
}
localJava, err := ioutil.ReadDir(i.JavaDir())

if err == nil && len(localJava) != 0 {
bin := "bin/java" // linux. somehow also works with windows
switch runtime.GOOS {
case "windows":
bin = "bin/java.exe"
case "darwin": // macOS
bin = "Contents/Home/bin/java"
}
i.javaBinary = filepath.Join(i.JavaDir(), localJava[0].Name(), bin)
return i.javaBinary
}

return ""
}

// downloadJava downloads the internal java binary
// TODO: version should not be static!
func (i *Instance) downloadJava() (string, error) {
url := ""
ext := ".tar.gz"

os.MkdirAll(i.JavaDir(), os.ModePerm)
switch runtime.GOOS {
case "linux":
url = "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u212-b03/OpenJDK8U-jre_x64_linux_hotspot_8u212b03.tar.gz"
case "windows":
ext = ".zip"
url = "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u212-b03/OpenJDK8U-jre_x64_windows_hotspot_8u212b03.zip"
case "darwin": // macOS
url = "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u212-b03/OpenJDK8U-jre_x64_mac_hotspot_8u212b03.tar.gz"
default:
return "", errors.New("unknown operating system. Can't download java for it")
func (i *Instance) Java() (*java.Java, error) {
if i.java != nil {
return i.java, nil
}
res, err := http.Get(url)
if err != nil {
return "", err
}

target, err := ioutil.TempFile("", "minepkg-java.*"+ext)
v := uint8(8)

if err != nil {
return "", err
}
_, err = io.Copy(target, res.Body)
if err != nil {
return "", err
mcSemver := semver.MustParse(i.Lockfile.MinecraftVersion())
if mcSemver.Equal(semver.MustParse("1.17.0")) || mcSemver.GreaterThan(semver.MustParse("1.17.0")) {
v = 16
}

err = archiver.Unarchive(target.Name(), i.JavaDir())
java, err := i.JavaFactory.Version(context.TODO(), v)
if err != nil {
return "", err
return nil, err
}

// macos tar contains some uneeded stuff that we need to remove
if runtime.GOOS == "darwin" {
os.Remove(filepath.Join(i.JavaDir(), "._jdk8u212-b03-jre"))
}

return i.javaBin(), nil
i.java = java
return java, nil
}
24 changes: 13 additions & 11 deletions internals/instances/launch.go
Expand Up @@ -32,8 +32,10 @@ var (
ErrNoCredentials = errors.New("can not launch without mojang credentials")
// ErrNoPaidAccount is returned when an instance is launched without `MojangProfile` beeing set
ErrNoPaidAccount = errors.New("you need to buy Minecraft to launch it")
// ErrorNoVersion is returned if no mc version was detected
ErrorNoVersion = errors.New("could not detect minecraft version")
// ErrNoVersion is returned if no mc version was detected
ErrNoVersion = errors.New("could not detect minecraft version")
// ErrNoJava is returned if no java runtime is available to launch
ErrNoJava = errors.New("no java runtime set to launch instance")
)

// GetLaunchManifest returns the merged manifest for the instance
Expand Down Expand Up @@ -136,15 +138,15 @@ func (i *Instance) BuildLaunchCmd(opts *LaunchOptions) (*exec.Cmd, error) {

// ensure some java binary is set
if opts.Java == "" {
opts.Java = i.javaBin()
// no local java installation
if opts.Java == "" {
// download java
if err := i.UpdateJava(); err != nil {
return nil, err
}
opts.Java = i.javaBinary
java, err := i.Java()
if err != nil {
return nil, err
}
if java.NeedsDownloading() {
return nil, ErrNoJava
}

opts.Java = java.Bin()
}

// Download assets if not skipped
Expand Down Expand Up @@ -439,7 +441,7 @@ func (i *Instance) fetchVanillaManifest(version string) (*minecraft.LaunchManife
}
}
if manifestURL == "" {
return nil, ErrorNoVersion
return nil, ErrNoVersion
}

manifest := minecraft.LaunchManifest{}
Expand Down

0 comments on commit e63cbcd

Please sign in to comment.