Skip to content

Commit 6464727

Browse files
committed
feat: linux(WIP)
1 parent c3c6e88 commit 6464727

File tree

3 files changed

+95
-93
lines changed

3 files changed

+95
-93
lines changed

internal/extractor/extractor_linux.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,15 @@ func MiHoYo(msixvcPath string, outDir string) (int, string) {
122122
return 1, "ERR_WRAPPER_NOT_FOUND"
123123
}
124124
// Prefer Wine built from WineGDK
125-
wg := filepath.Join(utils.BaseRoot(), "WineGDK")
126-
bd := filepath.Join(wg, "build")
127-
wine := filepath.Join(bd, "wine")
125+
wine := filepath.Join(utils.BaseRoot(), "wine", "files", "bin", "wine")
128126
if _, err := os.Stat(wine); err != nil {
129-
alt := filepath.Join(bd, "wine64")
130-
if _, er2 := os.Stat(alt); er2 == nil { wine = alt } else { return 1, "ERR_WINE_NOT_AVAILABLE" }
127+
wow := filepath.Join(utils.BaseRoot(), "wine", "files", "bin-wow64", "wine")
128+
if _, er2 := os.Stat(wow); er2 == nil {
129+
wine = wow
130+
} else {
131+
alt := filepath.Join(utils.BaseRoot(), "wine", "files", "bin", "wine64")
132+
if _, er3 := os.Stat(alt); er3 == nil { wine = alt } else { return 1, "ERR_WINE_NOT_AVAILABLE" }
133+
}
131134
}
132135
pf := filepath.Join(utils.BaseRoot(), "prefix")
133136
_ = os.MkdirAll(pf, 0755)

internal/winegdk/setup_linux.go

Lines changed: 79 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
package winegdk
44

55
import (
6+
"archive/tar"
67
"bufio"
8+
"compress/gzip"
79
"context"
10+
"io"
11+
"net/http"
812
"os"
913
"os/exec"
1014
"path/filepath"
@@ -28,94 +32,63 @@ func Setup(ctx context.Context) string {
2832
return "ERR_BASE_ROOT"
2933
}
3034
application.Get().Event.Emit(EventSetupStatus, "start")
31-
// Prefer Wine built from WineGDK (local path)
32-
wg := filepath.Join(base, "WineGDK")
33-
bd := filepath.Join(wg, "build")
34-
wineBin := func() string {
35-
cands := []string{filepath.Join(bd, "wine"), filepath.Join(bd, "wine64")}
36-
for _, p := range cands { if fi, err := os.Stat(p); err == nil && fi.Mode().IsRegular() { return p } }
37-
return ""
38-
}()
39-
if strings.TrimSpace(wineBin) == "" {
40-
application.Get().Event.Emit(EventSetupStatus, "deps_warning_wine_missing")
35+
wineDir := filepath.Join(base, "wine")
36+
_ = os.MkdirAll(wineDir, 0755)
37+
url := "https://github.com/Weather-OS/GDK-Proton/releases/download/release/GE-Proton10-25.tar.gz"
38+
tmp := filepath.Join(wineDir, "GE-Proton10-25.tar.gz")
39+
application.Get().Event.Emit(EventSetupStatus, "download_start")
40+
if err := downloadWithProgress(url, tmp, "download"); err != nil {
41+
application.Get().Event.Emit(EventSetupError, "ERR_DOWNLOAD")
42+
return "ERR_DOWNLOAD"
4143
}
42-
id := func() string {
43-
b, err := os.ReadFile("/etc/os-release")
44-
if err != nil {
45-
return ""
46-
}
47-
for _, l := range strings.Split(string(b), "\n") {
48-
s := strings.TrimSpace(l)
49-
if strings.HasPrefix(s, "ID=") {
50-
v := strings.TrimPrefix(s, "ID=")
51-
v = strings.Trim(v, "\"'")
52-
return strings.ToLower(strings.TrimSpace(v))
53-
}
54-
}
55-
return ""
56-
}()
57-
if id == "arch" {
58-
application.Get().Event.Emit(EventSetupStatus, "deps_warning_arch")
59-
pkgs := "mingw-w64-gcc base-devel git gcc multilib-devel winetricks wine vulkan-icd-loader lib32-vulkan-icd-loader libx11 lib32-libx11 freetype2 lib32-freetype2 mesa lib32-mesa glu lib32-glu alsa-lib lib32-alsa-lib libxrandr lib32-libxrandr libxi lib32-libxi libxext lib32-libxext libxrender lib32-libxrender libxcursor lib32-libxcursor libxinerama lib32-libxinerama libxcomposite lib32-libxcomposite libxfixes lib32-libxfixes libpng lib32-libpng libjpeg-turbo lib32-libjpeg-turbo libtiff lib32-libtiff openal lib32-openal mpg123 lib32-mpg123 sdl2 lib32-sdl2 libxml2 lib32-libxml2 libldap lib32-libldap vulkan-headers cups"
60-
application.Get().Event.Emit(EventSetupStatus, "deps_install_arch")
61-
cmd := exec.Command("bash", "-c", "sudo pacman -S --needed --noconfirm "+pkgs)
62-
_ = streamCmd(cmd, "deps")
63-
} else {
64-
application.Get().Event.Emit(EventSetupStatus, "deps_warning_other")
65-
}
66-
if _, err := os.Stat(wg); err != nil {
67-
application.Get().Event.Emit(EventSetupStatus, "cloning")
68-
cmd := exec.Command("git", "clone", "https://github.com/Weather-OS/WineGDK.git", wg)
69-
if err := streamCmd(cmd, "clone"); err != nil {
70-
application.Get().Event.Emit(EventSetupError, "ERR_GIT_CLONE")
71-
return "ERR_GIT_CLONE"
72-
}
73-
} else {
74-
application.Get().Event.Emit(EventSetupStatus, "updating")
75-
_ = streamCmd(exec.Command("bash", "-c", "cd '"+wg+"' && git remote update"), "update")
44+
application.Get().Event.Emit(EventSetupStatus, "extract_start")
45+
f, err := os.Open(tmp)
46+
if err != nil {
47+
application.Get().Event.Emit(EventSetupError, "ERR_OPEN_TAR")
48+
return "ERR_OPEN_TAR"
7649
}
77-
needBuild := false
78-
if _, err := os.Stat(wg); err == nil {
79-
chk := exec.Command("bash", "-c", "cd '"+wg+"' && if [ \"$(git rev-parse HEAD)\" = \"$(git rev-parse @{u})\" ]; then echo up_to_date; else echo needs_update; fi")
80-
out, _ := chk.CombinedOutput()
81-
s := strings.ToLower(strings.TrimSpace(string(out)))
82-
if s == "needs_update" {
83-
application.Get().Event.Emit(EventSetupStatus, "pulling")
84-
if er := streamCmd(exec.Command("bash", "-c", "cd '"+wg+"' && git pull --rebase"), "pull"); er != nil {
85-
application.Get().Event.Emit(EventSetupError, "ERR_GIT_PULL")
86-
return "ERR_GIT_PULL"
87-
}
88-
needBuild = true
89-
}
90-
// Build if local wine binary is missing
91-
if strings.TrimSpace(wineBin) == "" {
92-
needBuild = true
93-
}
94-
} else {
95-
needBuild = true
50+
defer f.Close()
51+
gz, err := gzip.NewReader(f)
52+
if err != nil {
53+
application.Get().Event.Emit(EventSetupError, "ERR_OPEN_GZ")
54+
return "ERR_OPEN_GZ"
9655
}
97-
_ = os.MkdirAll(bd, 0755)
98-
if needBuild {
99-
application.Get().Event.Emit(EventSetupStatus, "configuring")
100-
cfg := exec.Command("bash", "-c", "cd '"+bd+"' && ../configure --enable-win64")
101-
if err := streamCmd(cfg, "configure"); err != nil {
102-
application.Get().Event.Emit(EventSetupError, "ERR_CONFIGURE")
103-
return "ERR_CONFIGURE"
56+
defer gz.Close()
57+
tr := tar.NewReader(gz)
58+
for {
59+
hdr, er := tr.Next()
60+
if er == io.EOF { break }
61+
if er != nil { application.Get().Event.Emit(EventSetupError, "ERR_EXTRACT"); return "ERR_EXTRACT" }
62+
name := strings.TrimSpace(hdr.Name)
63+
if name == "" { continue }
64+
parts := strings.SplitN(name, "/", 2)
65+
if len(parts) < 2 { continue }
66+
rel := parts[1]
67+
if strings.TrimSpace(rel) == "" { continue }
68+
outPath := filepath.Join(wineDir, rel)
69+
switch hdr.Typeflag {
70+
case tar.TypeDir:
71+
_ = os.MkdirAll(outPath, os.FileMode(hdr.Mode))
72+
case tar.TypeReg:
73+
if err := os.MkdirAll(filepath.Dir(outPath), 0755); err != nil { application.Get().Event.Emit(EventSetupError, "ERR_WRITE_FILE"); return "ERR_WRITE_FILE" }
74+
of, e2 := os.OpenFile(outPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(hdr.Mode))
75+
if e2 != nil { application.Get().Event.Emit(EventSetupError, "ERR_WRITE_FILE"); return "ERR_WRITE_FILE" }
76+
if _, e3 := io.Copy(of, tr); e3 != nil { _ = of.Close(); application.Get().Event.Emit(EventSetupError, "ERR_WRITE_FILE"); return "ERR_WRITE_FILE" }
77+
_ = of.Close()
78+
default:
10479
}
105-
application.Get().Event.Emit(EventSetupStatus, "compiling")
106-
mk := exec.Command("bash", "-c", "cd '"+bd+"' && make -j$(nproc)")
107-
if err := streamCmd(mk, "make"); err != nil {
108-
application.Get().Event.Emit(EventSetupError, "ERR_MAKE")
109-
return "ERR_MAKE"
80+
application.Get().Event.Emit(EventSetupProgress, map[string]interface{}{"phase": "extract", "line": rel})
81+
}
82+
_ = os.Remove(tmp)
83+
wineBin := filepath.Join(wineDir, "files", "bin", "wine")
84+
if _, err := os.Stat(wineBin); err != nil {
85+
wow := filepath.Join(wineDir, "files", "bin-wow64", "wine")
86+
if _, er2 := os.Stat(wow); er2 == nil {
87+
wineBin = wow
88+
} else {
89+
alt := filepath.Join(wineDir, "files", "bin", "wine64")
90+
if _, er3 := os.Stat(alt); er3 == nil { wineBin = alt } else { application.Get().Event.Emit(EventSetupError, "ERR_WINE_NOT_AVAILABLE"); return "ERR_WINE_NOT_AVAILABLE" }
11091
}
111-
// refresh wineBin after build
112-
wineBin = func() string {
113-
cands := []string{filepath.Join(bd, "wine"), filepath.Join(bd, "wine64")}
114-
for _, p := range cands { if fi, err := os.Stat(p); err == nil && fi.Mode().IsRegular() { return p } }
115-
return ""
116-
}()
117-
} else {
118-
application.Get().Event.Emit(EventSetupStatus, "skip_build")
11992
}
12093
pf := filepath.Join(base, "prefix")
12194
_ = os.MkdirAll(pf, 0755)
@@ -129,6 +102,29 @@ func Setup(ctx context.Context) string {
129102
return ""
130103
}
131104

105+
func downloadWithProgress(url string, dest string, phase string) error {
106+
resp, err := http.Get(url)
107+
if err != nil { return err }
108+
defer resp.Body.Close()
109+
if resp.StatusCode != 200 { return io.ErrUnexpectedEOF }
110+
if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { return err }
111+
f, err := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
112+
if err != nil { return err }
113+
defer f.Close()
114+
buf := make([]byte, 256*1024)
115+
var total int64
116+
for {
117+
n, e := resp.Body.Read(buf)
118+
if n > 0 {
119+
if _, werr := f.Write(buf[:n]); werr != nil { return werr }
120+
total += int64(n)
121+
application.Get().Event.Emit(EventSetupProgress, map[string]interface{}{"phase": phase, "line": total})
122+
}
123+
if e != nil { if e == io.EOF { break } else { return e } }
124+
}
125+
return nil
126+
}
127+
132128
func streamCmd(cmd *exec.Cmd, phase string) error {
133129
stdout, _ := cmd.StdoutPipe()
134130
stderr, _ := cmd.StderrPipe()

minecraft.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -611,12 +611,15 @@ func (a *Minecraft) launchVersionInternal(name string, checkRunning bool) string
611611
var cmd *exec.Cmd
612612
if runtime.GOOS == "linux" {
613613
base := utils.BaseRoot()
614-
wg := filepath.Join(base, "WineGDK")
615-
bd := filepath.Join(wg, "build")
616-
wine := filepath.Join(bd, "wine")
614+
wine := filepath.Join(base, "wine", "files", "bin", "wine")
617615
if _, err := os.Stat(wine); err != nil {
618-
alt := filepath.Join(bd, "wine64")
619-
if _, er2 := os.Stat(alt); er2 == nil { wine = alt } else { return "ERR_WINE_NOT_AVAILABLE" }
616+
wow := filepath.Join(base, "wine", "files", "bin-wow64", "wine")
617+
if _, er2 := os.Stat(wow); er2 == nil {
618+
wine = wow
619+
} else {
620+
alt := filepath.Join(base, "wine", "files", "bin", "wine64")
621+
if _, er3 := os.Stat(alt); er3 == nil { wine = alt } else { return "ERR_WINE_NOT_AVAILABLE" }
622+
}
620623
}
621624
pf := filepath.Join(base, "prefix")
622625
_ = os.MkdirAll(pf, 0755)

0 commit comments

Comments
 (0)